7

在 Orgmode 中,有没有办法将子树匹配(或不匹配)特定标签中的块缠在一起

例如下面的代码

* A
#+BEGIN_SRC c
   printf("Not exported");
#+END_SRC

* B                :D:

#+BEGIN_SRC c
  printf("Exported");
#+END_SRC

沿标签D导出,缠结 C 文件将仅包含printf("Exported");

org-mode用来组织我的 emacs 配置,我的目标是从 master派生不同emacs-config.org的配置。(例如,通过仅标记特定的 lightconfig)

4

2 回答 2

4

为了实现这种行为,您可以利用除yesand之外的事实, Org Babel 代码块no的header 参数也可以理解文件名;即,对于任何给定的代码块,您可以告诉 Org Babel 您希望该块与哪个文件纠缠在一起。我的想法是在标题添加标签时自动为某个标题下的每个代码块设置文件名:tangle

(defun org-babel-set-tangle-file ()
  (let ((tag (car (org-get-local-tags))))
    (org-narrow-to-subtree)
    (while (re-search-forward "\\(:tangle \\).*" nil t)
      (replace-match (concat "\\1" tag ".el")))
    (widen)))

(add-hook 'org-after-tags-change-hook 'org-babel-set-tangle-file)

产生的行为是,当您调用org-babel-tangle当前文件时,所有属于

  • 没有标签的标题将被缠结到默认的缠结文件
  • 带标签的标题将与以该标签命名的文件纠缠在一起。

请注意,上面的函数将特定于标签的缠结文件的文件扩展名设置为.el; 因为您提到您想要生成不同的 Emacs 配置,所以我认为这将是一个合理的默认设置(即使您在示例中显示 C 代码)。

于 2014-05-18T20:34:59.083 回答
2

我前段时间尝试对此进行研究,但没有找到快速的答案。我最终修改org-babel-tangle-collect-blocks以实现此功能

这是修改后的功能。该列表org-babel-tags是 ok 标记的列表。对于您的示例,您需要将其设置为(setq org-babel-tags '("D"))

(我在第一次调用“除非”之后添加了前 4 行)

(defvar org-babel-tags nil
  "only tangle entries that has a tag in this list")

(defun org-babel-tangle-collect-blocks (&optional language)
  "Collect source blocks in the current Org-mode file.
Return an association list of source-code block specifications of
the form used by `org-babel-spec-to-string' grouped by language.
Optional argument LANG can be used to limit the collected source
code blocks by language."
  (let ((block-counter 1) (current-heading "") blocks)
    (org-babel-map-src-blocks (buffer-file-name)
      ((lambda (new-heading)
         (if (not (string= new-heading current-heading))
             (progn
               (setq block-counter 1)
               (setq current-heading new-heading))
           (setq block-counter (+ 1 block-counter))))
       (replace-regexp-in-string "[ \t]" "-"
                                 (condition-case nil
                                     (or (nth 4 (org-heading-components))
                                         "(dummy for heading without text)")
                                   (error (buffer-file-name)))))
      (let* ((start-line (save-restriction (widen)
                                           (+ 1 (line-number-at-pos (point)))))
             (file (buffer-file-name))
             (info (org-babel-get-src-block-info 'light))
             (src-lang (nth 0 info)))
        (unless (or (string= (cdr (assoc :tangle (nth 2 info))) "no")
                    (null (intersection (mapcar 'intern org-babel-tags)
                                        (save-excursion
                                          (org-back-to-heading)
                                          (mapcar 'intern (org-get-tags))))))

                    (unless (and language (not (string= language src-lang)))
                      (let* ((info (org-babel-get-src-block-info))
                             (params (nth 2 info))
                             (extra (nth 3 info))
                             (cref-fmt (or (and (string-match "-l \"\\(.+\\)\"" extra)
                                                (match-string 1 extra))
                                           org-coderef-label-format))
                             (link ((lambda (link)
                                      (and (string-match org-bracket-link-regexp link)
                                           (match-string 1 link)))
                                    (org-no-properties
                                     (org-store-link nil))))
                             (source-name
                              (intern (or (nth 4 info)
                                          (format "%s:%d"
                                                  current-heading block-counter))))
                             (expand-cmd
                              (intern (concat "org-babel-expand-body:" src-lang)))
                             (assignments-cmd
                              (intern (concat "org-babel-variable-assignments:" src-lang)))
                             (body
                              ((lambda (body) ;; run the tangle-body-hook
                                 (with-temp-buffer
                                   (insert body)
                                   (when (string-match "-r" extra)
                                     (goto-char (point-min))
                                     (while (re-search-forward
                                             (replace-regexp-in-string "%s" ".+" cref-fmt) nil t)
                                       (replace-match "")))
                                   (run-hooks 'org-babel-tangle-body-hook)
                                   (buffer-string)))
                               ((lambda (body) ;; expand the body in language specific manner
                                  (if (assoc :no-expand params)
                                      body
                                    (if (fboundp expand-cmd)
                                        (funcall expand-cmd body params)
                                      (org-babel-expand-body:generic
                                       body params
                                       (and (fboundp assignments-cmd)
                                            (funcall assignments-cmd params))))))
                                (if (org-babel-noweb-p params :tangle)
                                    (org-babel-expand-noweb-references info)
                                  (nth 1 info)))))
                             (comment
                              (when (or (string= "both" (cdr (assoc :comments params)))
                                        (string= "org" (cdr (assoc :comments params))))
                                ;; from the previous heading or code-block end
                                (funcall
                                 org-babel-process-comment-text
                                 (buffer-substring
                                  (max (condition-case nil
                                           (save-excursion
                                             (org-back-to-heading t)  ; sets match data
                                             (match-end 0))
                                         (error (point-min)))
                                       (save-excursion
                                         (if (re-search-backward
                                              org-babel-src-block-regexp nil t)
                                             (match-end 0)
                                           (point-min))))
                                  (point)))))
                             by-lang)
                        ;; add the spec for this block to blocks under it's language
                        (setq by-lang (cdr (assoc src-lang blocks)))
                        (setq blocks (delq (assoc src-lang blocks) blocks))
                        (setq blocks (cons
                                      (cons src-lang
                                            (cons (list start-line file link
                                                        source-name params body comment)
                                                  by-lang)) blocks)))))))
    ;; ensure blocks in the correct order
    (setq blocks
          (mapcar
           (lambda (by-lang) (cons (car by-lang) (reverse (cdr by-lang))))
           blocks))
blocks))
于 2014-05-18T19:43:49.997 回答