概述
我是一名电气工程师,从10年开始使用emacs,到现在已经5年多,它已经成为了电脑上必不可少的应用之一。说它是操作系统可能会有点夸张,不如说是一个整合的工作站会更加好点。
我的工作和电气自动化相关,偶尔会处理一些嵌入式或单片机的代码,或编写一些批处理的文件,所以使用的范围并非和编程太相关,说白了就是一个非程序员的应用。而且这个行业的很多软件还是运行在windows下,在mac或者linux下就歇菜了,所以这里的内容主要还是针对windows下的平台。
前期教训或经验
由于刚开始玩的时候没有太多正确的方法,而且emacs的学习曲线较其他的要陡峭,所以走了很多弯路。以下总结了一些自己的经验:
- 尽量使用terminal下的emacs。当初什么都不会,直接下载了一个windows下的emacs版本,结果遇到了3个很恼火的地方:配置中文显示麻烦,而且org mode下的表格中英文字母混排时,显示效果很差;ansi term根本无法起作用;路径还是沿用windows的风格,很多时候无法和一些cygwin的工具配合。后来就直接转到cygwin,中英文显示都很在正确,也不需要配置中文,而且可以和terminal配合。
- 使用conemu。用cygwin下的mintty感觉还是不好,就使用conemu来启动了。但默认的配色方案不多,也足够用。
- 使用zsh。如果想深入了解gnu/linux的系统,最好还是装zsh,配合oh my zsh真的很好。当然有人对这个傻瓜包感到不满,但对于我这种非程序员来说就足够了。emacs的确是有一个eshell,但还是过于简单,所以就用multi term开一个zsh,这样使用能够和emacs配合的天衣无缝。
- 使用package。一开始没注意,很多时候扩展都是使用git pull来更新,累死了,也不好管理。所以还是使用包管理会好很多。
- 需要有折腾的精神。曾经看过一个幻灯片,上面一个老外说到emacs不是目的,而是一个过程。如果需要开箱即用的配置,固然有prelude或者spacemacs之类的,但这样就少了折腾的份了。
- 放弃LaTeX。个人感觉它还是太老,很多不兼容的包和不统一的语法令人发狂。如果要折腾,还是用conTeXt为好。
- 越新的插件越好。在刚开始玩的时候,ido, helm这些补全都不满意,直到最近使用ivy才觉得补全就应该是这样子。
- 不过于迷信插件。要满足自己实际的需求,如果有些比较简单功能,能够自己写,或者是抄别人的代码稍微tweak一下就能实现的,就尽量不用插件。当然很多例子也是东抄西抄,然后自己改改就用了。在编写一些小功能的时候,发觉用得最多的是
shell-command
这条命令,配合一些命令行的工具,就可以量身定做一些实用的功能。
常用插件
- swiper: 用于查找字符,觉得比helm好用。
- projectile: 项目管理的插件,很好用,能够随意跳转到项目中的文件和文件夹。
- orgmode: 在emacs里面90%都是使用这个功能,就不多说了,笔记,待办事务,打草稿等。
- workgroup2: 用于保存虚拟桌面的插件,很好用,但貌似很久都没更新了。
- multi-term: 直接在emacs运行多个终端。
- avy: 用于跳转到文件中任意的位置。
- olivetti: 用于专心写作的模式,文字全部居中。
- hydra: 开头还是不怎么喜欢这种辅助功能的插件,但随着快捷件越来越多,
- slime: 学习lisp的利器。
orgmode文件
关于这个万能的模式说得太多了,有两点想说说。一是我将所有的东西都塞在不多的2,3个文件中,这样的做法可能看上去很怪,但看了lifehacker的一篇文章后就决定这样做了。有个老外也是使用纯文本来管理他自己的笔记和文件,但后来发现要管理的东西太多,他干脆放弃了管理,仅仅用几个文件就搞好了。开头我也使用deft插件来管理文件,但发觉太多的碎片文件要管理,现在也是使用少数的文件,如果需要查找,用emacs的标记功能,加上swiper来查找就OK了。
二是使用orgmode的literate programming,也即所谓的文学编程。在以前没有接触这个功能之前,emacs的配置文件,ledger文件,计算机编程语言例程搞到到处都是,很难管理,使用这个功能就能够将大部分的文件集中在一起。
打开二进制文件
emacs打开文件的方法,默认都是针对纯文本性质的文件,如果要打开一些二进制的文件就无力了,所以打开二进制文件的功能就非常实用,可以将emacs作为文件管理器来用。这个在xah lee的网站上说过,例子是针对windows,linux和mac的。学艺不精,当时就拿过来就用,后来才知道原来每个系统都有一个相关的命令,可以用文件默认的程序来打开。因为使用的是cygwin,直接用cygstart
就可以了。稍微修改一下代码,捆绑在C-c C-o就可以了。
(defun rw-open-in-external-app ()
"Open the current file or dired marked files in external app.
The app is chosen from your OS's preference."
(interactive)
(let* (
(ξfile-list
(if (string-equal major-mode "dired-mode")
(dired-get-marked-files)
(list (buffer-file-name))))
(ξdo-it-p (if (<= (length ξfile-list) 5)
t
(y-or-n-p "Open more than 5 files? "))))
(when ξdo-it-p
(mapc (lambda (fPath) (shell-command (format "cygstart \"%s\"" fPath))) ξfile-list))))
(define-key global-map (kbd "C-c C-o") 'rw-open-in-external-app)
事实上上面这个函数用得不多。因为经常使用的projectile,但只有一个projectile-find-file的功能,所以将这个函数也稍微修改,同样也是增加cygstart
这条命令,就可以在projectile上实现打开二进制文件的功能了。
(defun projectile-open-file-externally (&optional arg)
"Jump to a project's file using completion.
With a prefix ARG invalidates the cache first."
(interactive "P")
(projectile-maybe-invalidate-cache arg)
(let ((file (projectile-completing-read "Find file: "
(projectile-current-project-files))))
(shell-command (format "cygstart \"%s\""(expand-file-name file (projectile-project-root))))
(run-hooks 'projectile-find-file-hook)))
查英文字典
查找过一些比较旧的方法,就是在计算机上安装一个字典,然后再用emacs作为前端去查找单词。Xah Lee的方法是直接查在线字典,但我还想查找的同时,在另一个windwow显示查找的结果。以前使用w3m,但最新的emacs带有内部的eww文本浏览器,所以也改用这种方式,稍微tweak一下,绑定在f5功能键上,就可以查merriam-webster的在线字典了。
;; merriam-webster dictionary
(defvar webster-url "http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=")
(defun merriam (word)
(interactive "slook up a word in merriam-webster: ")
(let (start (point))
;;
(cond ((string= (format "%s" (current-buffer)) "*eww*")
(eww-browse-url (concat webster-url word)))
;;
((bufferp (get-buffer "*eww*"))
(progn (view-buffer-other-window (get-buffer "*eww*"))
(eww-browse-url (concat webster-url word))))
;;
(t
(progn (view-buffer-other-window (get-buffer "*scratch*"))
(eww-browse-url (concat webster-url word)))))))
(global-set-key (kbd "<f5>") 'merriam)
total commander的模仿
emacs的一个特性就是,如果你看到其他编辑器或程序有好用的地方,那么总会有相应的插件或者也可以自己写一些简单点的函数来实现,也就是它的模仿能力特别强。
以前使用过称为神器的total commander,觉得此类双面板的资源管理器很好用。当然emacs有一个sunrise commander的插件,但查看它的使用,太复杂了。想照搬该插件里面的移动及复制功能,又看不出所以然来。其实我在TC上99%用的功能就无非是将左边面板的文件,移动或者复制到左边的面板,还有就是将左右两边的面板互换一下。查看了一下elisp手册,移动或复制功能实现如下。逻辑无非就是先跳转到目标面板,将它的路径复制下来,然后跳回到源面板,再将所有标记的文件用cp
或mv
命令复制或移动到目标路径中,再更新一下显示就OK了。写得比较随意,没有dired-mode的判断,progn
也显得多余,但实用就行了。
;; total commander function
(defun total-commander-copy-files ()
"total commander copy method. Copy the marked files to the next panel."
(interactive)
(progn (switch-window)
(let ((target-directory (expand-file-name default-directory)))
(progn (switch-window)
(mapc (lambda (marked-file)
(shell-command (concat (format "cp -r \"%s\""
(file-name-nondirectory marked-file))
" "
target-directory)))
(dired-get-marked-files))
(switch-window)
(revert-buffer)))))
当然两个面板的互换的实现功能在网上早就有了,我将它捆绑在f9的功能键上面。但我想光标停在互换后新的面板上,所以在代码的最后加了(switch-window)
这一句。
;; transpose buffers
(defun transpose-buffers (arg)
(interactive "p")
(let ((selector (if (>= arg 0) 'next-window 'previous-window)))
(while (/= arg 0)
(let ((this-win (window-buffer))
(next-win (window-buffer (funcall selector))))
(set-window-buffer (selected-window) next-win)
(set-window-buffer (funcall selector) this-win)
(select-window (funcall selector)))
(setq arg (if (plusp arg) (1- arg) (1+ arg))))
(switch-window)))
(global-set-key [f9] 'transpose-buffers)
快速截屏及编辑
在编写笔记时,需要一种快速插入截屏方法,在网上也曾经说过这样一种方法,但它是基于linux下的scrot
命令的,而且我想在截屏之后马上对其进行编辑,所以稍微修改了如下的代码。截屏使用irfanview的命令,然后编辑使用picpick的命令,注意路径都是使用windows的路径方式。捆绑在快捷键C-c r
上。
;; screenshot
(defun cut ()
"Take a screenshot into a unique-named file in the current buffer file
directory and insert a link to this file."
(interactive)
(setq filename
(concat (make-temp-name "img-") ".png"))
;; (shell-command (format "boxcutter f:/cy/home/thinkT420/Notiz/img/\"%s\"" filename))
(shell-command (concat "i_view32 /capture=4 /convert=" "\"f:\\cy\\home\\thinkT420\\Notiz\\img" (format "\\%s\"" filename)))
(insert (concat "[[./img/" filename "]]"))
(shell-command (format "picpick f:/cy/home/thinkT420/Notiz/img/\"%s\"" filename))
)
(define-key org-mode-map (kbd "C-c r") 'cut)
简单的pdf文件合并
在工作中90%的时候都需要合并pdf文件,自动使用了emacs作为文件管理工具,就不想再打开工具去合并。有一个pdftk
的命令行工具,可以对pdf进行多种的操作。
;; pdf method
(defun pdf-merge ()
"Merge the marked files into a pdf file."
(interactive)
(setq filename
(concat (make-temp-name "c-") ".pdf"))
(shell-command (format "pdftk %s cat output %s"
(list-to-string (dired-get-marked-files))
filename))
(revert-buffer))
(defun list-to-string (l)
"Return a STRING which is the concatenation of the elements of L."
(if (not l)
nil
(if (stringp (car l))
(concat (file-name-nondirectory (car l)) " " (list-to-string (cdr l)))
(list-to-string (cdr l)))))
简单的压缩及解压
同理,压缩和解压在工作中很常见,但emacs自带的压缩功能并不是我想要的。所以使用7z的命令行工具,对文件进行解压或者压缩,也是绑定在hydra的功能键上。但缺点是我收到的文件很多还是rar的压缩方式,用emacs解压时出错,非要打开GUI解压才行。或者是这个功能还没有摸清楚其正确使用方法吧。
;; compress and uncompress files with 7z
(defun 7z-unzip ()
"Uncompress the marked files to a directory. The directory name is same as the zip file name without suffix."
(interactive)
(mapc (lambda (marked-file)
(shell-command (format "7z e -o\"%s\" \"%s\""
(file-name-base marked-file)
(file-name-nondirectory marked-file))))
(dired-get-marked-files))
(revert-buffer))
(defun 7z-zip ()
"Compress the marked files to a zip files. The zip file name is random."
(interactive)
(setq filename
(concat (buffer-name) ".zip"))
(mapc (lambda (marked-file)
(shell-command (format "7z a \"%s\" \"%s\""
(file-name-nondirectory filename)
(file-name-nondirectory marked-file))))
(dired-get-marked-files))
(revert-buffer))
关机,重启及睡眠
再次是懒人的道理,使用MS的psshutdown命令行功能,在emacs上直接实现这三个功能,也懒得去记一些命令行和快捷键,也不想动鼠标。然后将他们捆绑在hydra上的三个功能键上。
每月花费结算
很多文章都提到了ledger来进行个人的财务结算,但windows版本的ledger太旧了。后来找到一个克隆版的hledger,windows版本更新也快。使用文学编程的方式,在orgmode文件中增加如下代码,就可以直接将当月的花费记录下来。
#+BEGIN_SRC sh :dir ~/note
hledger balance -p "2016/06" --file finance.ledger
#+END_SRC
编写简单的幻灯片
利用pandoc,reveal.js编写一些简单,非正式的幻灯片,快捷简单。后来发现有个ox-reveal的插件,但没有用。
;; create the revealjs slideshow file
(defun org-revealjs-compile ()
(interactive)
(compile (concat "pandoc -s -i -t revealjs --self-contained" " " (file-name-nondirectory (buffer-file-name)) " " "-o" " "(file-name-sans-extension (file-name-nondirectory (buffer-file-name))) ".html" " " "-V theme=league")))
文件加密
网上推荐的方式是使用GNU GPG的方法,但过于复杂,而在一次不小心的操作中在加密的文字上再加密,之后无法恢复。其实只需要简单的ccrypt这个简单的工具,他本身也捆绑了elisp的插件,简单好用。
hydra
有些键的组合实在太难记,所以都捆绑在hydra上,这个插件还是挺好用的。
没有用emacs做的事
- 邮件:试过用mutt实现过,但本身对邮件操作不太重视,后来也没有用了。
- 多标签:因为是在cygwin下使用emacs,而且本身对标签的使用不感冒,开得多反而会混乱。
- 查看图片,pdf,听音乐:在emacs里面实现了,但太geek,作用也不大,所以后来也没用。
- 编写正式的幻灯片:考虑到大家多数还是用MS ppt,用LaTeX等写的方式没有人会改,也放弃了。