Generate Org-mode objects programmatically

左心房为你撑大大i 提交于 2020-01-12 03:32:12

问题


I want to generate strings containing Org-mode text without actually hard-coding the syntax. For example i want to run a function such as (org-generate (org-generate-heading "heading" (org-generate-plain-list '("foo" "bar" "baz"))) and it will return:

* heading
  - foo
  - bar
  - baz

In other words, i want to create Org-mode documents of arbitrary complexity without micromanaging syntactic features like asterisks and indentation, only via calling functions with parameters, that return some Org objects. Is it possible to do that? Maybe via org-element?


回答1:


INITIAL (March 14, 2014):  First rough draft.

EDIT (March 15, 2014):  Created and revised the function named example. The path of the let-bound variable org-file must coincide with an existing org-mode file. The let-bound variables main-heading and sub-heading are not being used at this time due to an apparent limitation with using variables in a list that begins with '( -- i.e., those two variables are not recognized under this circumstance. The function org-capture from org-capture.el has been modified to include the contents of the function org-capture-set-plist, which in turn has been modified to eliminate the first two elements of org-capture-entry (aka org-capture-templates) -- both entries (i.e., :key and :description) are for manually selecting a template from the user-interface, and are not needed when generating an org buffer programmatically as is being done with this example. In addition, the portions of the function org-capture relating to manually selecting a template have been removed.

EDIT (March 16, 2014):  Revised variables and list handling based upon lessons provided by @sds and @lunaryorn in the following thread: https://stackoverflow.com/a/22440518/2112489  Added four optional incoming variables -- (1) main-heading; (2) sub-heading-headline; (3) sub-heading-complete; and (4) plain-list. The example now work either interactively, or by evaluating the function using the following format:  (org-generate "PROJECT" "Thesis" "** Thesis\n:PROPERTIES:\n:END:" '("a" "b" "c"))

EDIT (March 19, 2014):  org-generate is now a non-interactive function that requires incoming variables -- the doc-string has been updated. Created a function named example that utilizes the new format for org-generate.


;; EXAMPLES:
;; (org-generate 'entry "/Users/HOME/Desktop/myproject.org" "PROJECT" "Thesis" "** Thesis\n   :PROPERTIES:\n   :END:")
;; (org-generate 'item "/Users/HOME/Desktop/myproject.org" "PROJECT" "Thesis" nil '("a" "b" "c"))

(defun example ()
(interactive)
  (let* (
      (org-file "/Users/HOME/Desktop/myproject.org")
      (level-one "TASKS")
      (level-two
        "Active [\#A] Generate Org-mode objects programmatically.")
      (full-level-two (concat
        "** Active [\#A] Generate Org-mode objects programmatically.\n"
        "   DEADLINE: <%<%Y-%m-%d %a>>\n"
        "   :PROPERTIES:\n"
        "   :ToodledoFolder: TASKS\n"
        "   :END:"))
       (plain-list '("foo" "bar" "baz")) )
    (org-generate 'entry org-file level-one level-two full-level-two)
    (org-generate 'item org-file level-one level-two nil plain-list) ))

(defun org-generate (type org-file level-one
  &optional level-two full-level-two plain-list)
"Formating options for `org-capture-entry` are similar to `org-capture-templates`.
However, the first two elements (i.e., `:key` and `:description`) are NOT used.
Please see the doc-string of the variable `org-capture-templates` for more info.
  (1) `type`:  required -- 'entry | 'item
  (2) `org-file`:  required -- path to the org-mode file.
  (3) `level-one`:  required -- main heading.
  (4) `level-two`:  optional -- sub-heading headline (only).
  (5) `full-level-two`:  optional -- complete sub-heading.
  (6) `plain-list`:  optional -- a list.
EXAMPLES:
  `(org-generate 'entry org-file level-one level-two full-level-two)`
  `(org-generate 'item org-file level-one level-two nil plain-list)` "
  (require 'org-capture)
  (let (org-capture-entry)
    (cond
      ((eq type 'entry)
        (setq org-capture-entry
          `(entry
            (file+headline ,org-file ,level-one)
              ,full-level-two :empty-lines 1 :immediate-finish t))
        (lawlist-org-capture))
      ((eq type 'item)
        (setq org-capture-entry
          `(item
            (file+olp ,org-file ,level-one ,level-two)
              nil :empty-lines 1 :immediate-finish t))
        (mapcar (lambda (x)
          (progn
            (setcar (nthcdr 2 org-capture-entry) x)
            (lawlist-org-capture) ))
          plain-list)))))

(defun lawlist-org-capture ()
    (let* ((orig-buf (current-buffer))
     (annotation (if (and (boundp 'org-capture-link-is-already-stored)
        org-capture-link-is-already-stored)
         (plist-get org-store-link-plist :annotation)
       (ignore-errors (org-store-link nil))))
     (entry org-capture-entry)
     initial)
      (setq initial (or org-capture-initial
      (and (org-region-active-p)
           (buffer-substring (point) (mark)))))
      (when (stringp initial)
  (remove-text-properties 0 (length initial) '(read-only t) initial))
      (when (stringp annotation)
  (remove-text-properties 0 (length annotation)
        '(read-only t) annotation))
  (setq org-capture-plist (copy-sequence (nthcdr 3 entry)))
  (org-capture-put :target (nth 1 entry))
  (let ((txt (nth 2 entry)) (type (or (nth 0 entry) 'entry)))
    (when (or (not txt) (and (stringp txt) (not (string-match "\\S-" txt))))
      (cond
       ((eq type 'item) (setq txt "- %?"))
       ((eq type 'checkitem) (setq txt "- [ ] %?"))
       ((eq type 'table-line) (setq txt "| %? |"))
       ((member type '(nil entry)) (setq txt "* %?\n  %a"))))
    (org-capture-put :template txt :type type))
  (org-capture-get-template)
  (org-capture-put :original-buffer orig-buf
       :original-file (or (buffer-file-name orig-buf)
              (and (featurep 'dired)
             (car (rassq orig-buf
                   dired-buffers))))
       :original-file-nondirectory
       (and (buffer-file-name orig-buf)
            (file-name-nondirectory
             (buffer-file-name orig-buf)))
       :annotation annotation
       :initial initial
       :return-to-wconf (current-window-configuration)
       :default-time
       (or org-overriding-default-time
           (org-current-time)))
  (org-capture-set-target-location)
  (condition-case error
      (org-capture-put :template (org-capture-fill-template))
    ((error quit)
     (if (get-buffer "*Capture*") (kill-buffer "*Capture*"))
     (error "Capture abort: %s" error)))
  (setq org-capture-clock-keep (org-capture-get :clock-keep))
    (condition-case error
        (org-capture-place-template
         (equal (car (org-capture-get :target)) 'function))
      ((error quit)
       (if (and (buffer-base-buffer (current-buffer))
          (string-match "\\`CAPTURE-" (buffer-name)))
     (kill-buffer (current-buffer)))
       (set-window-configuration (org-capture-get :return-to-wconf))
       (error "Error.")))
    (if (and (derived-mode-p 'org-mode)
       (org-capture-get :clock-in))
        (condition-case nil
      (progn
        (if (org-clock-is-active)
      (org-capture-put :interrupted-clock
           (copy-marker org-clock-marker)))
        (org-clock-in)
        (org-set-local 'org-capture-clock-was-started t))
    (error
     "Could not start the clock in this capture buffer")))
    (if (org-capture-get :immediate-finish)
        (org-capture-finalize))))


(source: lawlist.com)



来源:https://stackoverflow.com/questions/22411626/generate-org-mode-objects-programmatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!