使用浏览器书签时,有时候太多了,找起来很麻烦。最近我开始使用emacs-w3m
来存书签。默认保存到 ~/.w3m/bookmark.html
文件中。
然后我尝试了 helm-bookmarks ,它可以使用helm来帮助选择书签。
但我是 ivy
用户,平时少有使用helm。还有一个问题是我的书签中有很多中文标题,如果需要选择中文标题的书签时,还需要切换输入法。
针对中文标题这个问题,由于之前我 hack 过一下ivy,使它可以支持拼音首字母搜索,可以参考一下 我的配置 。所以我只需要使用ivy帮助我选择书签就可以了。
首先需要解析我的书签文件,使用 libxml-parse-html-region
可以解析文件,
返回一个 DOM object
。还需要 dom.el 来解析 DOM object
。不过据说
Emacs 25
已经内置了 dom.el
了。如果使用 Emacs 24
的同学可能需要自行下载一下。
思路很简单,把所有的 a
标签全部解析出来,做出来一个 ((name1 url1) (name2 url2) ...)
这样格式的列表。使用 ivy-read
来选择一个 name
,最后根据 name
找到对应的 url
。
代码如下:
;;; use `ivy' to use w3m-bookmarks
(require 'dom)
;;; where your bookmark file located
(setq peng-bookmark-file "~/.w3m/bookmark.html")
(defun peng-ivy-get-bookmarks ()
"use `ivy-read' to select bookmark and return its url
"
(let* ((dom (with-temp-buffer
(insert-file-contents peng-bookmark-file)
(libxml-parse-html-region (point-min)
(point-max))))
(a (dom-by-tag dom 'a))
(mylist (mapcar 'peng-parse-dom-tag-to-personal-format a))
(name (ivy-read "Jump to bookmarks:" (mapcar 'car mylist)))
;; todo: I need to find `name' in mylist, if find, break the
;; loop. But now, I just use `mapcar' to deal with every
;; element in mylist and get `final-result' by removing all
;; nil element in the list `result'. It's very ugly code!
(result (mapcar #'(lambda (data)
(if (string= (car data)
name)
(cdr data)
nil))
mylist))
(final-result (caar (remove nil result))))
final-result))
(defun peng-parse-dom-tag-to-personal-format (dom)
"parse a tag to `(name url) format'"
(let ((url (dom-attr dom 'href))
(name (dom-text dom)))
(list name url)))
最后,写几个 interactive
的函数来选择用不同的浏览器打开:
(defun peng-bookmarks-firefox ()
(interactive)
(let ((url (peng-ivy-get-bookmarks)))
(browse-url-firefox url)))
(defun peng-bookmarks-chrome ()
(interactive)
(let ((url (peng-ivy-get-bookmarks)))
(browse-url-chromium url)))
(defun peng-bookmarks-w3m ()
(interactive)
(let ((url (peng-ivy-get-bookmarks)))
(w3m-goto-url-new-session url)))
在函数 peng-ivy-get-bookmarks
中,得到标题名 title
后,从 ((name1 url1) (name2 url2) ...)
列表中找对应的url时,我写得很丑:用map返回一个 (nil nil (URL) nil ...)
这样的列表,然后又用 remove
把所有的
nil
去掉。最后剩下的就是需要的 url
。其实应该是循环 mylist
,找到对应的 name
后就退出的。但我不知道怎么写。至少现在是可以工作了。
最后,我尝试了把我 firefox
的书签导出到html中,使用上面的函数也可以工作。只需要把 peng-bookmark-file
改成对应的html文件就好。