zkry / yaml-pro

Edit YAML in Emacs like a pro
GNU General Public License v3.0
137 stars 9 forks source link

[feature request] Create a field given its outline path #30

Open rodrigomorales1 opened 11 months ago

rodrigomorales1 commented 11 months ago

In order to create headlines programmatically in Org Mode, I have written this function that creates this function given its headline. See minimal working example in the second code block below.

(defun my/org-create-headline-with-outline (outline)
  "Create headlines according to OUTLINE

After executing the function, the point will be located in
the headline with the given outline.

A post-condition is that the point will always be at the
beginning of the headline defined by OUTLINE."
  (widen)
  (condition-case nil
      (goto-char (org-find-olp outline t))
    ('error
     (let (prev)
       (dotimes (item (length outline))
         (setq sublist (cl-loop for i from 0
                                for x from 0 to item
                                when (<= i item)
                                collect (nth x outline)))
         (condition-case nil (setq prev (org-find-olp sublist t))
           ('error
            (cond ((eq (length sublist) 1)
                   (goto-char (point-max))
                   (unless (looking-at "^")
                     (newline))
                   (insert "* " (car sublist)))
                  (t
                   (goto-char prev)
                   (let ((end (org-element-property :end (org-element-context)))
                         (level (org-current-level)))
                     (unless end
                       (error "This shouldn't happen"))
                     (goto-char end)
                     (cond
                      ((not (looking-at "^"))
                       (insert "\n"))
                      ((not (eq (char-after) ? ))
                       (open-line 1)))
                     (insert (make-string (1+ level) ?*) " "))
                   (insert (car (last sublist)))
                   (move-beginning-of-line nil)))
            (setq prev (point)))))
       prev))))

Minimal working example:

(with-temp-buffer
  (org-mode)
  (insert
   (concat
    "* 1\n"
    "* 2\n"
    "* 3\n"))
  (my/org-create-headline-with-outline '("2" "2.1" "2.1.1"))
  (buffer-string))
* 1
* 2
** 2.1
*** 2.1.1
* 3

I believe that having a function that does the same in YAML files would be useful for creating YAML fields programmatically.

The function could be called yaml-create-field.

The following is a minimal working example that shows an idea of how the function should behave: Given the following YAML document

1:
2:
3:

Evaluating (yaml-create-field '("2" "2.1" "2.1.1")) would result in the following document. The position of point is represented with <point>.

1:
2:
  2.1:
    2.1.1:<point>
3:

PS: This link contains the function my/org-create-headline-with-outline shown above with some comments.

zkry commented 7 months ago

Hi! Sorry for the late comment, I've been busy with life for the past months but have started to get back into things.

I like this idea actually. This could even be made to be interactive and show the user what's being added where. I'll see if I can get something working.

zkry commented 6 months ago

I just merged a new function called yaml-pro-ts-add-mapping to do what you described here. Turns out to work really well for generating tree structures!

2024-02-17 22 12 10