如何从目录中的 Org 文件列表中提取标题作为链接
How to extract titles as links from a list of Org files in a directory
我有一个目录下的 org 文件列表:
> org-file1.org
> org-file2.org
> org-file3.org
> ...
> org-fileN.org
我想提取他们的标题(使用 #+title
标签)作为链接如下:
[[file:org-file1.org][title for org file 1]]
[[file:org-file2.org][title for org file 2]]
[[file:org-file3.org][title for org file 3]]
...
[[file:org-fileN.org][title for org file N]]
如何使用 Emacs Lisp 将它们提取为列表?
下面是一些可用于单个文件以获取标题的代码。它是可用于测试的 org 模式文件的一部分。将其保存为 Org 模式文件,在 Emacs 中访问它并在代码块上键入 C-c C-c
。更改标题并再次评估代码块。
#+OPTIONS: toc:nil
#+TITLE: This is a very nice title, don't you think?
#+AUTHOR: A.U. Thor
* foo
bar
* Code
#+begin_src elisp :results drawer
(save-excursion
(goto-char (point-min))
(let ((case-fold-search t))
(search-forward-regexp "^#\+TITLE:")
(org-element-property :value (org-element-context (org-element-at-point)))))
#+end_src
#+RESULTS:
:results:
This is a very nice title, don't you think?
:end:
代码块转到缓冲区的开头,在一行的开头向前搜索字符串 #+TITLE:
(搜索是 case-insensitive),然后使用 org-element
库解析缓冲区,获取上下文并从中获取 :value
属性。
为了使其成为一个完整的解决方案,您必须:
让它更健壮:检查这是一个标题关键字,而不是一些偶然满足匹配的随机垃圾,尽管这不太可能;但安全总比后悔好。
将其包装在一个循环中,该循环对目录中的每个文件执行 find-file
并获取每个文件的标题和 returns 元组列表:(filename title)
,您可以轻松地使用它来创建链接。
您可以为此使用 org-element-api
,但在这种情况下,可能 easier/faster 只是使用 looking-at-p 通过正则表达式进行搜索。要获取一个目录下的所有文件,有directory-files(-recursively)
。然后最后你可以使用以下函数实现它:
(defun extract-org-directory-titles-as-list (&optional dir)
(interactive "D")
(print
(delete nil
(let ((case-fold-search t))
(mapcar (lambda (f)
(when (string-match "org$" f)
(with-temp-buffer
(insert-file-contents-literally
(concat (file-name-as-directory dir) f))
(while (and (not (looking-at-p "#\+TITLE:"))
(not (eobp)))
(forward-line))
(when (not (eobp))
(cons f (substring (thing-at-point 'line) 9 -1))))))
(directory-files dir))))))
(defun insert-directory-org-file-titles (&optional dir)
(interactive "D")
(let ((files-titles (extract-org-directory-titles-as-list dir)))
(dolist (ft files-titles)
(insert (concat "[[file:" (car ft)"][" (cdr ft) "]]\n")))))
如果您更喜欢将它作为一个 (a) 列表,就像您问的那样,那么只需使用 extract-org-directory-titles-as-list
.
我有一个目录下的 org 文件列表:
> org-file1.org
> org-file2.org
> org-file3.org
> ...
> org-fileN.org
我想提取他们的标题(使用 #+title
标签)作为链接如下:
[[file:org-file1.org][title for org file 1]]
[[file:org-file2.org][title for org file 2]]
[[file:org-file3.org][title for org file 3]]
...
[[file:org-fileN.org][title for org file N]]
如何使用 Emacs Lisp 将它们提取为列表?
下面是一些可用于单个文件以获取标题的代码。它是可用于测试的 org 模式文件的一部分。将其保存为 Org 模式文件,在 Emacs 中访问它并在代码块上键入 C-c C-c
。更改标题并再次评估代码块。
#+OPTIONS: toc:nil
#+TITLE: This is a very nice title, don't you think?
#+AUTHOR: A.U. Thor
* foo
bar
* Code
#+begin_src elisp :results drawer
(save-excursion
(goto-char (point-min))
(let ((case-fold-search t))
(search-forward-regexp "^#\+TITLE:")
(org-element-property :value (org-element-context (org-element-at-point)))))
#+end_src
#+RESULTS:
:results:
This is a very nice title, don't you think?
:end:
代码块转到缓冲区的开头,在一行的开头向前搜索字符串 #+TITLE:
(搜索是 case-insensitive),然后使用 org-element
库解析缓冲区,获取上下文并从中获取 :value
属性。
为了使其成为一个完整的解决方案,您必须:
让它更健壮:检查这是一个标题关键字,而不是一些偶然满足匹配的随机垃圾,尽管这不太可能;但安全总比后悔好。
将其包装在一个循环中,该循环对目录中的每个文件执行
find-file
并获取每个文件的标题和 returns 元组列表:(filename title)
,您可以轻松地使用它来创建链接。
您可以为此使用 org-element-api
,但在这种情况下,可能 easier/faster 只是使用 looking-at-p 通过正则表达式进行搜索。要获取一个目录下的所有文件,有directory-files(-recursively)
。然后最后你可以使用以下函数实现它:
(defun extract-org-directory-titles-as-list (&optional dir)
(interactive "D")
(print
(delete nil
(let ((case-fold-search t))
(mapcar (lambda (f)
(when (string-match "org$" f)
(with-temp-buffer
(insert-file-contents-literally
(concat (file-name-as-directory dir) f))
(while (and (not (looking-at-p "#\+TITLE:"))
(not (eobp)))
(forward-line))
(when (not (eobp))
(cons f (substring (thing-at-point 'line) 9 -1))))))
(directory-files dir))))))
(defun insert-directory-org-file-titles (&optional dir)
(interactive "D")
(let ((files-titles (extract-org-directory-titles-as-list dir)))
(dolist (ft files-titles)
(insert (concat "[[file:" (car ft)"][" (cdr ft) "]]\n")))))
如果您更喜欢将它作为一个 (a) 列表,就像您问的那样,那么只需使用 extract-org-directory-titles-as-list
.