我使用Emacs编辑器连同org-mode和evil-mode主要是用于文字处理和文档。经常会有一个主题,几个不同的网站URL所属。
举个例子。我有一个关于如何安装Emacs的文本片段。
*** install emacs
emacs - I want to try org-mode. What's the shortest path from zero to typing? - Stack Overflow
https://stackoverflow.com/questions/4940680/i-want-to-try-org-mode-whats-the-shortest-path-from-zero-to-typing
Index of /gnu/emacs/windows/emacs-26
http://ftp.gnu.org/gnu/emacs/windows/emacs-26/emacs-26.3-x86_64.zip
Installation target:
file://C:\Lupo_Pensuite\MyApps\emacs
How to
file://C:\Lupo_Pensuite\MyDocs\howto.txt
是否可以选择区域,所有的URL都在我的默认网络浏览器中打开?而文件链接是在Windows资源管理器内打开的?而文本文件是用相关的编辑器打开的?
或者更好的是:emacs知道a.m.文本片段实际上是一个org模式的章节。不管光标在该章中的哪个位置,像M-x open-all-links-in-chapter这样的操作都是......打开当前章中所有提到的链接。
Prio 1: emacsorg-modeevil-mode中是否已经有类似的东西存在?
Prio 2: 有没有你知道的 elisp 函数可以实现这个用例?
环境:Windows 10下的Cygwin,emacorg模式下的evil-mode。Windows 10下的Cygwin,emacs 26.3,org-mode 9.1.9。
警告:不经意间使用了以下内容 可以 让你的机器屈服。我将在最后添加一些更具体的警告,但要小心!
下面代码的基本思想是解析一个Org模式文件的缓冲区,以获得缓冲区的解析树:通过以下方式完成。org-element-parse-buffer
. 然后我们可以使用 org-element-map
来行走解析树,并选择 只是 节点 link
我们对每一个都应用了一个函数。我们应用的函数。get-link
,通过链接节点的内容,提取类型和路径,并返回这两个内容的列表。这是目前的情况。
(defun get-link (x)
(let* ((link (cadr x))
(type (plist-get link :type))
(path (plist-get link :path)))
(if (or (string= type "http") (string= type "https"))
(list type path))))
(defun visit-all-http-links ()
(interactive)
(let* ((parse-tree (org-element-parse-buffer))
(links (org-element-map parse-tree 'link #'get-link)))
links))
注意,我只保留了 http
和 https
链接:你可能想要添加额外的类型。
这已经很好地实现了你想要的东西。事实上,如果你用上面的两个函数加载文件,你可以在下面的Org模式示例文件上尝试。
* foo
** foo 1
http://www.google.com
https://redhat.com
* bar
** bar 2
[[https://gnome.org][Gnome]] is a FLOSS project. So is Fedora: https://fedoraproject.org.
* Code
#+begin_src emacs-lisp :results value verbatim :wrap example
(visit-all-http-links)
#+end_src
#+RESULTS:
#+begin_example
(("http" "//www.google.com") ("https" "//redhat.com") ("https" "//gnome.org") ("https" "//fedoraproject.com"))
#+end_example
并评估源块 C-c C-c
,你得到的结果显示。
现在我们需要做的是将每个 (TYPE PATH)
对,然后访问它--这是代码的最终版本。
(defun get-link (x)
"Assuming x is a LINK node in an Org mode parse tree,
return a list consisting of its type (e.g. \"http\")
and its path."
(let* ((link (cadr x))
(type (plist-get link :type))
(path (plist-get link :path)))
(if (or (string= type "http") (string= type "https"))
(list type path))))
(defun format-url (x)
"Take a (TYPE PATH) list and return a proper URL. Note
the following works for http- and https-type links, but
might need modification for other types."
(format "%s:%s" (nth 0 x) (nth 1 x)))
(defun visit-all-http-links ()
(interactive)
(let* ((parse-tree (org-element-parse-buffer))
(links (org-element-map parse-tree 'link #'get-link)))
(mapcar #'browse-url (mapcar #'format-url links))))
我们添加了一个函数 format-url
,做到这一点。("http" "//example.com") --> "http://example.com"
并将其映射到链接列表上,产生一个新的URLS列表。然后我们将函数 browse-url
emacs提供的),然后我们看着浏览器将它们全部打开。
警告:如果你的文件中有成百上千的链接,那么你会在浏览器中创建成百上千的标签。
如果你的文件中有成百上千的链接 那么你将会在浏览器中创建成百上千的标签页 你是 SURE 你的机器能承受得了吗?
如果你的链接指向大的对象,那就会给你的系统带来另一种内存压力。你是否 SURE 你的机器能承受吗?
如果你的Org模式缓冲区很大,那么 org-element-parse-buffer
可以采取 长 的时间来处理它。此外,虽然有缓存机制,但由于bug,默认情况下并没有启用,所以每次执行函数时都要解析缓冲区的 再一次 从头开始。
每次执行该函数时,你都会打开 新产品 浏览器中的标签。
针对评论中的问题进行了编辑。
Q1:"visit-all-http-links可以打开文件中的所有URL。我原来的问题是,是否可以只打开当前org-mode章节中被发现的URL。"
A1:只做一个区域有点难,但也是可以的,如果你保证这个区域是语法正确的org模式(比如标题及其内容的集合)。你只需要把区域写到一个临时缓冲区,然后在临时缓冲区上做我所做的事情,而不是原来的区域.下面是使用修改后的代码。visit-url
问题2中的函数。
(defun visit-all-http-links-in-region (beg end)
(interactive "r")
(let ((s (buffer-substring beg end)))
(with-temp-buffer
(set-buffer (current-buffer))
(insert s)
(let* ((parse-tree (org-element-parse-buffer))
(links (org-element-map parse-tree 'link #'get-link)))
(mapcar #'visit-url (mapcar #'format-url links))))))
(defun visit-all-http-links ()
(interactive)
(visit-all-http-links-in-region (point-min) (point-max)))
非常小的测试.
Q2:"每次我用你的函数执行你的例子URLs时,URLs都以不同的顺序被打开--是否可以按照在org文件中找到的那个顺序打开URLs?"
A2:链接是按照它们在文件中出现的顺序确定地找到的。但是当你调用 browse-url
所有的赌注都被取消了,因为URL现在属于浏览器,它将尝试在一个单独的标签页中打开它所收到的每个URL,并且 另起炉灶 - 换句话说是异步的。你可以尝试在调用之间引入一个延迟,但不能保证。
(defun visit-url(url)
(browse-url)
(sit-for 1 t))
然后使用 visit-url
而不是 browse-url
在 visit-all-urls
.