【问题标题】:Emacs org-mode insert text after heading propertiesEmacs org-mode 在标题属性后插入文本
【发布时间】:2018-08-31 19:59:48
【问题描述】:

我想在 org 文件的所有标题之后插入一些文本。

例如,假设我有:

* Header foo
  :PROPERTIES:
  :EXPORT_FILE_NAME: ./tmp/Test
  :END:
* Header bar

运行后(插入标题“NEW TEXT”),我应该有:

* Header foo
  :PROPERTIES:
  :EXPORT_FILE_NAME: ./tmp/Test
  :END:
NEW TEXT
* Header bar
NEW TEXT

到目前为止,我做到的最好的事情是:

  (goto-char (point-min))
  (goto-char (re-search-forward "^*"))
  (set-mark (line-beginning-position))
  (goto-char (point-max))
  (org-map-entries
   (lambda () (progn (forward-line)(new-line)(previous-line) (insert "NEW TEXT") )

但是,这会在属性之前插入文本。


编辑:

(defun goto-header()
  (interactive)
  (org-back-to-heading)
  (let ((beg-end (org-get-property-block))):
       (when beg-end
         (let ((end (cdr beg-end)))
           (goto-char end))))
  (forward-line)
  (newline)
  (previous-line))

用作将点移动到正确位置的一种方式,以便 insert 可以正确插入文本。有没有更好的办法?

【问题讨论】:

  • 你只有一级头条吗?如果不是,您希望将新文本插入到 每个 标题之后还是仅在顶级标题之后?顺便说一句,您还需要跳过调度信息以及属性。

标签: emacs org-mode


【解决方案1】:

这是一个注释很多的函数,可以满足你的需求。

(defun my/insert-text-after-heading (text)
  "Insert TEXT after every heading in the file, skipping property drawers."
  (interactive "sText to insert: ")

  ;; The Org Element API provides functions that allow you to map over all
  ;; elements of a particular type and perform modifications. However, as
  ;; as soon as the buffer is modified the parsed data becomes out of date.
  ;;
  ;; Instead, we treat the buffer as text and use other org-element-*
  ;; functions to parse out important data.

  ;; Use save-excursion so the user's point is not disturbed when this code
  ;; moves it around.
  (save-excursion
    ;; Go to the beginning of the buffer.
    (goto-char (point-min))

    ;; Use save-match-data as the following code uses re-search-forward,
    ;; will disturb any regexp match data the user already has.
    (save-match-data

      ;; Search through the buffer looking for headings. The variable
      ;; org-heading-regexp is defined by org-mode to match anything
      ;; that looks like a valid Org heading.
      (while (re-search-forward org-heading-regexp nil t)

        ;; org-element-at-point returns a list of information about
        ;; the element the point is on. This includes a :contents-begin
        ;; property which is the buffer location of the first character
        ;; of the contents after this headline.
        ;;
        ;; Jump to that point.
        (goto-char (org-element-property :contents-begin (org-element-at-point)))

        ;; Point is now on the first character after the headline. Find out
        ;; what type of element is here using org-element-at-point.
        (let ((first-element (org-element-at-point)))

          ;; The first item in the list returned by org-element-at-point
          ;; says what type of element this is.  See
          ;; https://orgmode.org/worg/dev/org-element-api.html for details of
          ;; the different types.
          ;;
          ;; If this is a property drawer we need to skip over it. It will
          ;; an :end property containing the buffer location of the first
          ;; character after the property drawer. Go there if necessary.
          (when (eq 'property-drawer (car first-element))
            (goto-char (org-element-property :end first-element))))

      ;; Point is now after the heading, and if there was a property
      ;; drawer then it's after that too. Insert the requested text.
      (insert text "\n\n")))))

【讨论】:

    【解决方案2】:

    要转到属性抽屉的末尾,您可以使用(org-end-of-meta-data t)。所以一个更短的函数是

    (defun goto-header()
      (interactive)
      (org-back-to-heading)
      (org-end-of-meta-data t)
      (forward-line)
      (newline)
      (previous-line))
    

    【讨论】:

      猜你喜欢
      • 2017-07-08
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 1970-01-01
      • 2021-12-27
      相关资源
      最近更新 更多