使用 Helm 搜索 Chrome 历史记录


#1

Chrome 把历史记录保存在一个 SQLite 数据库中,用户也可以访问(Chrome 开着时,需要先拷贝一份):

~ $ cp '/Users/xcy/Library/Application Support/Google/Chrome/Profile 1/History' .
~ $ sqlite3 History 'select url, title from urls limit 2'
http://emacs-china.org/|Emacs China
https://emacs-china.org/|关于“Chrome 历史”的搜索结果 - Emacs China
~ $

我写了个 Helm 界面,用来搜索 Chrome 历史记录:

(defvar helm-chrome-history-db
  "~/Library/Application Support/Google/Chrome/Profile 1/History"
  "Chrome History SQLite Database.")

(defun helm-chrome-history-init ()
  ;; 缓存到 " *helm candidates:Chrome History*",和缓存到变量相比,省去了插入的
  ;; 时间。我的有 600 万字符,应该会一直占用 6 M 内存
  (unless (helm-candidate-buffer)
    (helm-init-candidates-in-buffer 'global
      (with-temp-buffer
        (let ((db "/tmp/History"))
          (copy-file helm-chrome-history-db db t)
          (unless (zerop (call-process "sqlite3" nil t nil db "select url, title from urls"))
            (error "sqlite3 failed: %s" (buffer-string)))
          (buffer-string))))))

(defvar helm-chrome-history-source
  (helm-build-in-buffer-source "Chrome History"
    :init #'helm-chrome-history-init
    :action (helm-make-actions
             "Browse URL"
             (lambda (x) (browse-url (car (split-string x "|"))))
             "EWW URL"
             (lambda (x) (eww (car (split-string x "|")))))))

(defun helm-chrome-history ()
  (interactive)
  (helm :sources helm-chrome-history-source
        :buffer "*Helm Chrome History*"
        :full-frame t))

#2
(require 'cl-lib)
(require 'subr-x)
(require 'pcase)

(defvar cm/counsel-ff-db-path
  (car (file-expand-wildcards "~/.mozilla/firefox/*/places.sqlite")))

(defvar cm/counsel-ff-bookmarks-cache nil)

(defun cm/counsel-ensure-ff-db ()
  (let* ((name (make-temp-name "ffdb"))
         (path (expand-file-name name temporary-file-directory)))
    (condition-case e
        (copy-file cm/counsel-ff-db-path path)
      (error "Failed to ensure firefox database: %s" e))
    path))

(defun cm/counsel-prepare-bookmarks-candidates (&optional force-update?)
  (counsel-require-program "sqlite3")
  (or
   (if force-update? nil cm/counsel-ff-bookmarks-cache)
   (let* ((db-path (cm/counsel-ensure-ff-db)))
     (with-temp-buffer
       (let ((errno (call-process
                     "sqlite3" nil (current-buffer) nil "--ascii" db-path
                     (string-join '("SELECT bm.title, p.url"
                                    "FROM moz_bookmarks AS bm INNER JOIN moz_places AS p"
                                    "WHERE bm.fk = p.id;") " ")))
             splitted)
         (if (= errno 0)
             (setq splitted
                   (mapcar
                    (lambda (it) (split-string it "\037")) ; ^_
                    (split-string
                     (string-trim
                      (buffer-substring-no-properties (point-min) (point-max)))
                     "\036"             ; ^^
                     )))
           (error "SQLite exited with error code %d" errno))
         (setq cm/counsel-ff-bookmarks-cache
               (cl-remove "" (mapcar (pcase-lambda (`(,title ,url))
                                       (when (null url) (setq url title))
                                       (list (format "%s %s"
                                                     title
                                                     (propertize url 'face 'link))
                                             url))
                                     splitted)
                          :test #'equal :key #'cadr)))))))

(defun cm/counsel-firefox-bookmarks (&optional force-update?)
  (interactive "P")
  (ivy-read "Firefox Bookmarks: " (cm/counsel-prepare-bookmarks-candidates
                                   force-update?)
            :history 'cm/counsel-firefox-bookmarks-history
            :action (lambda (it) (browse-url (cadr it)))
            :caller 'cm/counsel-firefox-bookmarks
            :require-match t))

用ivy查询火狐的历史记录。

火狐数据库里的书签,url和title居然不是放在一起的。title在moz_bookmarks表里,这个表的fk列标记了对应URL在moz_places表里的id列。


#3

花时间重构了一下,现在历史记录和书签都可以查询了。

依赖emacsql,主要是用了他的sql语句生成器


#4

Lisp 民科警告 :smiley:


#5

自 El Captain,Safari 把历史存在 ~/Library/Safari 下的 SQLite 数据库,不过在 Mojave 现在这个路径被做了特殊处理不能访问和复制。比较有趣的是通过 Finder 反而可以移动出历史文件,终端下所有对这个路径的操作都被禁止了。


#6

看见listary 了,暴露了你是windows用户的事实 :joy:


#7

我觉得listary比everything用户体验好多了,可惜不能和emacs很好的配合,另外现在不收钱各种阉割功能基本没法用 :cry:


#8

还不来用自由的浏览器? :sunglasses:


#9

Mac下还是习惯用launchbar搜


#10

Chrome 有个很像 helm 的插件,也是做类似的事