ZMonster's Blog 巧者劳而智者忧,无能者无所求,饱食而遨游,泛若不系之舟

使用elisp编写脚本

起因

我通过Github Pages有了自己的一个静态博客,并且开始正儿八经地写博客。

但我碰到了一个问题:每次我需要写博客,我要先打开emacs,按下C-x C-f,然后输入一长串路径名和文件名(org文件),然后手动输入YAML Front Matter[1]。路径名每次都是一样的,YAML Front Matter也是一样的,这都是重复性的工作,并且我又是一个很懒的人,所以我就想偷懒了。

起初是想写个shell脚本来简化步骤而已,开始写脚本后,我就想,应该把publish的步骤也通过脚本进行简化(虽然这并不是很复杂的步骤),然后我发现shell不能做到这一点,唯一的选择是elisp。

过程

用elisp写脚本?这事我听说过,但我没做过,也就是说我也是大姑娘上轿头一回了。

照例google。

基本形式没太大问题,将shell脚本Shebang[2]后面的 /bin/bash 改成 /usr/bin/emacs –script ,其他的东西嘛,随便就行不是么?(想当年某次实习招聘的时候我跟面试官说我会shell脚本,结果只会堆命令的真相还是被不留情面地揭穿了(╯‵□′)╯︵┴─┴ )

不过碰到了不少问题。

  1. 之所以用elisp,就是想简化publish么,但是在elisp script里写上的

    (org-publish-project "blog-linusp")
    

    完全不起作用。细想一下应该是shell脚本没有加载我的emacs相关配置。当时真是一筹莫展啊,后来发现其实这是一件不复杂的事情,在之前加上一句

    (load-file "~/.emacs")
    

    不过这样做太凶残了,什么auto-complete、yasnippet、slime、org2blog、metablog全被加载了(╯‵□′)╯︵┴─┴ 。

    好在我有将配置文件分类的习惯,org-mode的相关配置被我写在一个名为 org.el 的文件里,于是加载它就OK了,不过这个文件里还有引用其他的一些emacs插件,于是也都加载了——好吧至少比之前更好是吧。

  2. 如何传递参数给脚本?shell脚本接受参数的话还是懂的怎么做的,可是elisp脚本……

    照例google,然后发现Xah Lee[3]的博客上就有这个内容,原文点

  3. 运行脚本后,发现总会有一堆的Loading message,就像下面这样:

    2013-10-09-loading-message.png

    (╯‵□′)╯︵┴─┴

    经google,该问题没有太好的解决问题,凑合吧。

成果

嘛,虽然代码写得比较丑陋,至少能用,功能上达到了我的预期目标,所以代码的问题,以后再说吧。

附脚本代码

#!/usr/bin/emacs --script

(require 'calendar)
(defun blog (action &rest rst)
  (cond ((string-equal action "post")
     (if (equal rst nil)
         (print "Please input title")
       (let ((post-file (concat (format-time-string "%Y-%m-%d")
                     "-"
                     (car rst)
                     ".org")))
         (progn
           (with-temp-file (concat "~/blog/org/_posts/"
                       post-file)
         (insert (concat "#+begin_html\n"
                 "---\n"
                 "layout     : post\n"
                 "title      : \n"
                 "categories : \n"
                 "tags       : \n"
                 "excerpt    : \n"
                 "---\n"
                 "#+end_html\n")))
           (print (format "Create post file %s in post directory" post-file))
           (shell-command (concat "emacs "
                      "~/blog/org/_posts/"
                      post-file))))))
     ((string-equal action "publish")
      (progn
        (org-publish-project "blog-linusp")
        (print "Project has been published!")))
    (t (print "Action: post/publish"))))

(load-file "~/.emacs.d/site-lisp/xml-rpc.el")
(load-file "~/.emacs.d/site-lisp/wc-mode.el")
(load-file "~/.emacs.d/myplugins/org.el")

(blog (elt argv 0) (elt argv 1))

[1] YAML Front Matter是用来告诉Jekyll使用什么模板并可以附带一些其他信息的文件头

[2] Shebang是一个由'#'和'!'构成的字符串,在文件中存在Shebang的情况下,类Unix操作系统的程序载入器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数——来自维基百科

[3] Xah Lee是一位emacs大牛,emacs wiki上可是都有他的专门的页面哦