一些Emacs技巧
下面是我配置中的一些对他人可能有用的Emacs Lisp内容。 我不想把它们发表在MELPA上,因为我不想维护它们。它们可能有bug,未经过彻底的测试等问题。 如果它们适合你的需要,你可以随意挑选,但是如果它们不起作用,也不要抱怨!
编辑HTML时浏览器自动重新加载
Switching to the browser and refreshing it got old rather quickly, so I scripted it. 当我使用HTML/CSS/JS进行web编程时,我喜欢使用浏览器来快速测试我的更改。 切换到浏览器再刷新这种方法已经过时了,而且太慢,因此我编写了个脚本来完成它。
reload-browser.el
提供了一个函数来重新加载多个浏览器窗口。
第一次调用它时,它会把光标变成一个方框,要求您单击要重新加载的窗口。之后,再次调用该函数将重新加载所选择的窗口。
如果你传递一个数字前缀参数,您还可以选择多个窗口(例如,Firefox和Chrome)。
无需更复杂的设置,我就能通过快捷键来保存当前buffer并重新加载所有浏览器窗口了。
在后台,它只是简单地调用 xdotool
来完成繁重的工作。脚本基本上很直观,但Chromium需要光标定位后才能重新加载,而Firefox则不需要,脚本中必须处理这个问题。
编辑汇编语言时预览定义
最近我一直在涉猎6502汇编,浏览代码时,我经常发现需要查看光标所在标签的定义。
因此,我编写了一个用于汇编的xref后端(xrefasm.el
),这样就可以使用标准的快捷键跳转到定义并返回了。
不多对于大多数标签,我并不需要特意跳转到定义处,只需要看到标签上下几行,就可以记起它的作用。
因此我编写了 xref-posframe.el
, 另一个使用 posframe
来预览定义的包.
Posframe 允许你创建不带window decoration的一次性Emacs frame, 这要比在当前buffer内容上的overlay要更方便也更利于配置,而且速度也足够快。借助 xref-posframe
我可以一键预览定义。
再按一键,我甚至可以跳转到定义。
而且它可以在支持xref的任何地方工作,而不仅仅是在汇编语言时。
突出显示TODO关键字
This can be done by adding keywords to font lock:
这个很简单。我让评论中的 TODO:
和 FIXME:
关键字现实时使用自定义字体,这样我可以立即看到它们,知道有东西要修复。这可以通过为font lock添加关键字来实现:
(defun add-watchwords () "Add TODO: words to font-lock keywords." (font-lock-add-keywords nil '(("\(\<TODO\|\<FIXME\|\<HACK\|@.+\):" 1 font-lock-warning-face t)))) (add-hook 'prog-mode-hook #'add-watchwords)
这种方法有一个缺点:它会高亮现实编程buffer中所有出现这些单词的地方,即使在注释之外也是如此。 有一些复杂的包可以以更健壮的方式进行高亮,确保只在注释中突出显示这些词。 但我认为不值得因为这些情况而增加复杂性。对我来说,99.99%的情况下,上面的方法是有效的。当出现假阳性时,我就忽略它。
最近我使用了更多描述性的关键字,比如 @correct:
或 @optimization:
,所以我在后面添加了一个通配符来处理 "@
" 和 ":
" 之间的所有单词。即便如此,误报也不是问题。
在org文档中插入截图
我在Org上做了很多笔记。当我做一些设计可视化的东西时,我比较喜欢包含一些屏幕截图,因为它们通常更有助于表达。为了减少截屏,剪切,插入链接到Org文件的不爽之处,我写了一些Elisp来帮我:
(defun insert-screenshot (file-name) "Save screenshot to FILE-NAME and insert an Org link at point. This calls the `import' from ImageMagick to take the screenshot, and `optipng' to reduce the file size if the program is present." (interactive "FSave to file: ") ;; Get absolute path (let ((file (expand-file-name file-name))) ;; Create the directory if necessary (make-directory (file-name-directory file) 'parents) ;; Still, make sure to signal if the screenshot was in fact not created (unless (= 0 (call-process "import" nil nil nil file)) (user-error "`import' failed to create screenshot %s" file)) (if (executable-find "optipng") (start-process "optipng" nil "optipng" file)) (insert ;; A link relative to the buffer where it is inserted is more portable (format "[[file:%s]]" (file-relative-name file (file-name-directory buffer-file-name)))) (when (eq major-mode 'org-mode) (org-redisplay-inline-images))))
这段代码请求输入一个文件名,然后调用 import
来选择我想要截屏的区域并保存它,然后在光标处插入一个org格式的图像链接。
org-mode会显示内联图像,这样我就可以立即看到结果。如果安装了 optipng
,它甚至会压缩屏幕截图以节省空间。
插入、删除或更改分隔符
在Spacemacs和Vim中,有一种极好的方法可以快速地用引号、大括号和其他分隔符包裹一部分文本分。当我用会普通Emacs时,手动添加引号就很无聊了。
delimiter.el
解决了这个问题. 它非常简单: delimiter-surround
会提示你输入分隔符,并用它包裹选中的文本.
如果没有选中区域,它将包裹当前的语句。因此我只需要快速按两次键,就能引用一个单词。
某些分隔符是成对的,比如一个左大括号 "{
" 使用与其匹配的右大括号 "}
" 作为结束分隔符。
还有一个 delimiter-change
能将现有的分隔符对更改为其他内容,还有一个 delimiter-delete
这个作用看名字就知道干啥的了。
注意,这个函数不太聪明:如果您有嵌套的分隔符,它将只删除最接近光标的分隔符,所以在以下情况下(插入符用 |
标记点):
(he|re (is) a list)
执行 M-x delimiter-delete ( RET
会产生下面记i恶果:
he|re (is a list)
但我们想要的应该是删除最外层括号:
he|re (is) a list
如果你想要聪明的行为,你去别的地方找找看。
无延迟auto-revert
就在昨天,我还想研究某些简单C文件GCC的汇编输出。我打开了两个窗口:一个是C代码,另一个是汇编输出。我将后者置于 auto-revert-mode
中,这样我就能在重新编译后快速看到结果。
结果, auto-revert-mode
在我的机器上出现了一些奇怪的延迟,有时候需要几秒钟才能刷新缓冲区让我看到结果。
还不如直接在终端上运行 watch -n 0.1 cat a.s
呢。
我编写了一个小小的minor模式,它在从 inotify
获取到更改事件后就会刷新buffer,并且持续这种瞬时操作。
稍后,我检查了 auto-revert-mode
的源代码,发现它与我的minor模式大致相同,首先使用 filenotify
watcher,如果不支持filenotify或调用filenotify失败,则使用轮询。
然而,它仍然需要花几秒钟时间来刷新,而我的minor mode工作正常。
如果您遇到了与 auto-revert-mode
相同的问题,您可以尝试一下 inotify-revert.el
。