【问题标题】:Orgmode: how to filter the blocks to be tangle?Orgmode:如何过滤要缠结的块?
【发布时间】:2014-05-17 09:54:27
【问题描述】:

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

比如下面的代码

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

* B                :D:

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

沿标签D导出,tangle C 文件将只包含printf("Exported");

我正在使用org-mode 来组织我的emacs 配置,我的目标是派生不同的配置 从主emacs-config.org。 (例如,只标记特定的 lightconfig)

【问题讨论】:

    标签: emacs org-mode org-babel


    【解决方案1】:

    要实现此行为,您可以利用以下事实:除了 yesno,Org Babel 代码块的 :tangle 标头参数还有 understands file names;即,对于任何给定的代码块,您可以告诉 Org Babel 您希望该块与哪个文件纠缠在一起。我的想法是在给标题添加标签时,自动为某个标题下的每个代码块设置文件名

    (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 代码)。

    【讨论】:

    • 我刚刚尝试过,但并没有按预期工作。 (因为你除了有 :tangle 标签,而且我不喜欢将其添加到所有块中)我更喜欢 mike idea 来过滤收集的块。感觉更灵活,并且可以有更多的逻辑
    【解决方案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))
    

    【讨论】:

    • 嘿@mike,你基于什么版本的orgmode?我去ob-tangle函数出处,代码和签名都不一样:签名(defun org-babel-tangle-collect-blocks (&optional language tangle-file)
    • @AdrieanKhisbe 我正在使用 7.9.3f
    • Okey dokey,所以他们可能已经为主要版本 8 重构了整个功能。我暂时放弃了寻找实现它的方法,因为使用 use-package 我有一个解决方法。还是谢谢! :)
    • 所以我认为没有现成的方法可以在 Org-mode 8.3.2 中获得相同的功能?
    猜你喜欢
    • 2015-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    相关资源
    最近更新 更多