emacs的工作环境设置

概述

我是一名电气工程师,从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手册,移动或复制功能实现如下。逻辑无非就是先跳转到目标面板,将它的路径复制下来,然后跳回到源面板,再将所有标记的文件用cpmv命令复制或移动到目标路径中,再更新一下显示就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等写的方式没有人会改,也放弃了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容