在 Emacs 中控制 Firefox 翻页、刷新、关闭页面

经常会边写代码边看网页, 在编辑器和浏览器之间不停地切换.

写了几个小函数, 让我可以在 Emacs 中控制 Firefox 进行翻页和关闭当前 tab 等操作.

1 使用方式

功能 函数名 快捷键
刷新页面 moz-reload-browser C-c m g
向下翻页 moz-page-down C-c m n
向上翻页 moz-page-up C-c m p
关闭当前页面 moz-tab-close C-c m k

2 Elisp 代码和 Firefox 插件

把以下代码放到 init.el 中:

(defun moz-send-command (command)
  "Send COMMAND to *MozRepl* process.

  If the process doesn't exist, create one."
  (comint-send-string (inferior-moz-process) command))

(defun moz-reload-browser ()
  "Refresh current page"
  (interactive)
  (moz-send-command
   "setTimeout(function(){content.document.location.reload(true);}, '500');")
  )

(defun moz-page-down ()
  "Scroll down the current window by one page."
  (interactive)
  (moz-send-command "content.window.scrollByPages(1);")
  )

(defun moz-page-up ()
  "Scroll up the current window by one page."
  (interactive)
  (moz-send-command "content.window.scrollByPages(-1);")
  )

(defun moz-tab-close ()
  "Close current tab"
  (interactive)
  (moz-send-command "content.window.close();")
  )

(global-set-key (kbd "C-c m g") 'moz-reload-browser)
(global-set-key (kbd "C-c m n") 'moz-page-down)
(global-set-key (kbd "C-c m p") 'moz-page-up)
(global-set-key (kbd "C-c m k") 'moz-tab-close)

然后:

  • Emacs 中安装 moz-repl (我是通过 el-get install moz-repl 安装的)
  • Firefox 中安装 MozRepl

3 Hack 过程

边读 Caching with Rails 边写代码, 在 Emacs 和 Firefox 中不停切换, 麻烦, 能不能在 Emacs 中控制 Firefox 翻页呢?

之前看过别人写的在 Emacs 中通过 mozrepl 来刷新 Firefox 页面的函数:

(defun moz-reload-browser ()
  (interactive)
  (comint-send-string
   (inferior-moz-process)
   "setTimeout(function(){content.document.location.reload(true);}, '500');"))

如果翻页也能用 mozrepl 控制的话, 那我想要的函数应该很容易写. 切到 Firefox, duckduckgo 搜索一下 “firefox console scroll down this page”, 扫一眼搜索结果, 感觉应该是 window.scroll.. 之类的.

F12 打开 Firebug, 切到 Console, 然后输入 window.scroll 看补全中有个非常非常可疑的 scrollByPages.

试一下, 在 console 中输入, window.scrollByPages, 返回: scrollByPages()

加个参数试试: scrollByPages(1), 往下翻了一页, 成了!

再试试负数参数: scrollByPages(-1), 这次往上翻了.

下面写函数:

(defun moz-page-down ()
  "Scroll down the current window by one page."
  (interactive)
  (comint-send-string
   (inferior-moz-process)
   "content.window.scrollByPages(1);")
  )

不好使, 直接在 Emacs 中的 MozRepl 里运行 window.scrollByPages(1); 也不成.

在自己的 init.el 里翻翻, 找到另外一个函数:

(defun moz-update (&rest ignored)
  "Update the remote mozrepl instance"
  (interactive)
  (comint-send-string (inferior-moz-process)
                      (concat "content.document.body.innerHTML="
                              (json-encode (buffer-string)) ";")))

它用 content.document 来获得 document, 我也加个试试, 在 MozRepl 里输入 content.window.scrollByPages(1);, 好使.

改写我的函数:

(defun moz-page-down ()
  "Scroll down the current window by one page."
  (interactive)
  (comint-send-string
   (inferior-moz-process)
   "content.window.scrollByPages(1);")
  )

再试, 好用了!

再写个往上翻页的:

(defun moz-page-up ()
  "Scroll up the current window by one page."
  (interactive)
  (comint-send-string
   (inferior-moz-process)
   "content.window.scrollByPages(-1);")
  )

绑定快捷键:

(global-set-key (kbd "C-c m n") 'moz-page-down)
(global-set-key (kbd "C-c m p") 'moz-page-up)

顺手写个关闭当前 tab 的函数:

(defun moz-tab-close ()
  "Close current tab"
  (interactive)
  (comint-send-string
   (inferior-moz-process)
   "content.window.close();")
  )
(global-set-key (kbd "C-c m k") 'moz-tab-close)

代码比较脏, 几个函数大体相同, 简化一下:

(defun moz-send-command (command)
  "Send COMMAND to *MozRepl* process.

If the process doesn't exist, create one."
  (comint-send-string (inferior-moz-process) command))

(defun moz-reload-browser ()
  "Refresh current page"
  (interactive)
  (moz-send-command
   "setTimeout(function(){content.document.location.reload(true);}, '500');")
  )

(defun moz-page-down ()
  "Scroll down the current window by one page."
  (interactive)
  (moz-send-command "content.window.scrollByPages(1);")
  )

(defun moz-page-up ()
  "Scroll up the current window by one page."
  (interactive)
  (moz-send-command "content.window.scrollByPages(-1);")
  )

(defun moz-tab-close ()
  "Close current tab"
  (interactive)
  (moz-send-command "content.window.close();")
  )

完成!

4 thoughts on “在 Emacs 中控制 Firefox 翻页、刷新、关闭页面

  1. Wenshan Post author

    我在 Firefox 中用 Keysnail 的一个插件,可以按 “e” 将所有的链接用字母标注出来,按相应的字母就会点击相应的链接。类似于 Emacs 里的 ace-jump。

    moz-controller 还没实现这个功能,理论上可以调用 Keysnail 的这个插件来实现

  2. Stupid ET

    就是如果你在浏览一个网页,你需要点一个链接,是需要鼠标点击吗?还是可以直接键盘操作呢?

Leave a Reply