教程存檔Github
序|Preface
先來(lái)一篇有趣的簡(jiǎn)介:Emacs和Vim:神的編輯器和編輯器之神 - 51CTO.COM
為何寫(xiě)這篇教程?
作為一個(gè)徹頭徹尾的emacs新手,盡管有些薄弱的編程經(jīng)驗(yàn),但上手這么一個(gè)黑客級(jí)別的編輯器還是難免一段陣痛期。雖然網(wǎng)上有很多非常好的教程,比如這篇著名的文章,一年成為Emacs高手(像神一樣使用編輯器),雖然提供了一個(gè)很好的學(xué)習(xí)框架,但具體的學(xué)習(xí)內(nèi)容還是需要你自己尋找。這篇教程,在某種意義上可以被視為按照那個(gè)學(xué)習(xí)框架進(jìn)行的學(xué)習(xí)實(shí)踐。
在實(shí)踐過(guò)程中,我發(fā)現(xiàn)相關(guān)基礎(chǔ)知識(shí)的優(yōu)秀教程散布在互聯(lián)網(wǎng)的各個(gè)角落,缺乏一個(gè)有條理的組織,更別提有些排名靠前的教程早已過(guò)時(shí),里面提到的操作和方法已經(jīng)不適用于最新版的emacs。
雖然emacs可以作為一個(gè)簡(jiǎn)單的文本編輯器開(kāi)箱即用,但陡峭的學(xué)習(xí)曲線主要體現(xiàn)在讓它發(fā)揮最大功效的個(gè)性化定制之中。這篇教程整理了我在配置emacs過(guò)程中學(xué)到的知識(shí),方便新手循序漸進(jìn)的學(xué)習(xí)。建議你將它作為一個(gè)有內(nèi)在結(jié)構(gòu)的課程來(lái)對(duì)待。整個(gè)教程大約會(huì)花掉你18個(gè)小時(shí)。
誰(shuí)該閱讀這篇教程?
我學(xué)習(xí)emacs的初衷是為了做日程管理,記筆記,并且寫(xiě)研究論文。我的學(xué)習(xí)和研究經(jīng)常涉及到各種編程語(yǔ)言,特別是各種統(tǒng)計(jì)軟件,比如R,SAS,Stata,Matlab等,當(dāng)然還有Python。雖然R和Python都支持“文學(xué)編程”模式[1],但如果想將多種語(yǔ)言整合進(jìn)一個(gè)文檔的話(huà),emacs的org-babel模式無(wú)疑是第一選擇。而既然是想寫(xiě)研究論文,對(duì)于Latex的支持必不可少。所以,我配置的emacs會(huì)以方便“文學(xué)編程”,多格式導(dǎo)出(主要是Latex和html)以及各種文檔模板為重點(diǎn),主要圍繞emacs的兩個(gè)插件org和auctex來(lái)展開(kāi),可能還會(huì)涉及到知識(shí)整理,以及同Evernote互動(dòng)的內(nèi)容。另外,許多配置步驟在Unix系統(tǒng)下會(huì)方便很多,但很不幸,我使用的是windows。
所以,如果你是emacs小白,但有一點(diǎn)編程經(jīng)驗(yàn),有同我類(lèi)似的需求,并且也使用windows,那么這篇文章就是為你量身定制的。歡迎閱讀!
為什么不直接使用高手寫(xiě)好的配置?
這個(gè)教程本身就借鑒了許多高手的配置。我堅(jiān)信“授人以魚(yú)不如授人以漁”的格言。我相信我對(duì)你最大的幫助是這篇教程本身,而不是那些配置文檔。希望作為新手的你,在閱讀完這篇教程后,能獲得足夠的信心和動(dòng)力來(lái)打造一個(gè)獨(dú)屬于你的emacs。
如何學(xué)習(xí)這篇教程?
請(qǐng)注意我使用了“學(xué)習(xí)”而不是“閱讀”。這意味著你需要自己動(dòng)手,實(shí)踐那些優(yōu)秀教程提到的操作。自己寫(xiě)一些代碼,而不是單純的復(fù)制粘帖。
凡是附在“參考”后的文章,盡管大部分是英語(yǔ)文章,都請(qǐng)你仔細(xì)閱讀。當(dāng)然,你可以先瀏覽我寫(xiě)在后面的筆記和總結(jié),來(lái)獲得一個(gè)初步理解。你甚至可以只閱讀我的總結(jié)來(lái)基本理解我要談的事情,這看上去會(huì)節(jié)省你大量的時(shí)間,但其實(shí)你在不知不覺(jué)中錯(cuò)過(guò)了很多我沒(méi)提及但對(duì)你很重要的細(xì)節(jié)。No pain, no gain...如果你堅(jiān)持不讀參考文章,請(qǐng)至少記得它們的標(biāo)題。等你遇到問(wèn)題時(shí),至少知道該用什么樣的關(guān)鍵詞來(lái)搜索答案。
附在“延伸閱讀”后的文章都很有價(jià)值,有助于你深入理解前文提到的概念。加了“必讀”標(biāo)簽的請(qǐng)優(yōu)先閱讀。標(biāo)簽"TD"代表文章中出現(xiàn)了很多我還沒(méi)提及的技術(shù)細(xì)節(jié)(Technique details),需要更多的背景知識(shí)。所以,如果你在閱讀中感到困惑,可以先跳過(guò),等學(xué)習(xí)完整個(gè)教程后再來(lái)閱讀。因此,TD還有一層TODO的意味……
在閱讀我給出的文章時(shí),你可能希望完成一個(gè)“知識(shí)閉環(huán)”后再回來(lái)繼續(xù)學(xué)習(xí)。所謂“知識(shí)閉環(huán)”,就是持續(xù)了解閱讀過(guò)程中遇到的新概念,直到不再遇到新的概念為止。顯然,這會(huì)耗費(fèi)大量的精力,而且你的疑問(wèn)通常會(huì)在后續(xù)的教程中得到解決。我在撰寫(xiě)這個(gè)教程時(shí),并沒(méi)假定你完成了“知識(shí)閉環(huán)”后再繼續(xù)學(xué)習(xí),所以,建議你只對(duì)最大的疑惑做擴(kuò)展閱讀,比如選擇性的瀏覽文章中包含的超鏈接。
下載安裝|Download and Installation
官網(wǎng):http://ftp.gnu.org/gnu/emacs/windows/
打開(kāi)網(wǎng)頁(yè)后,頂部是一段關(guān)于如何安裝的說(shuō)明文檔。
總結(jié):
- 不需要安裝,解壓縮到某個(gè)路徑就可以了
- 為了方便全局調(diào)用,請(qǐng)?zhí)砑觔in路徑到環(huán)境變量(比如我的,
C:\emacs\bin)。你可能需要先了解下環(huán)境變量和命令行的基本知識(shí)。搜索關(guān)鍵詞“windows環(huán)境變量PATH”,“啟動(dòng)cmd” - 測(cè)試下,在cmd里,輸入
emacs -nw[2],以終端模式來(lái)運(yùn)行emacs;只輸入emacs,以GUI模式來(lái)運(yùn)行 - 文檔介紹了bin目錄下各個(gè)exe文件的功能,也介紹了怎樣完全卸載,直接刪除就好
- 解壓縮完成后,可以運(yùn)行
bin\addpm.exe,這樣會(huì)自動(dòng)生成配置文件.emac和目錄.emacs.d,并且在啟動(dòng)菜單里添加應(yīng)用程序快捷方式。另外,官方文檔里說(shuō)還會(huì)添加注冊(cè)表的相關(guān)條目。不過(guò)在我的電腦上,注冊(cè)表并未新增相應(yīng)條目 - 可以在桌面上新建一個(gè)快捷方式(shortcut),位置(location)填入
emacs的安裝路徑\bin\runemacs.exe --debug-init。加了flag--debug-init,是為了方便調(diào)試(debug)配置文件。不推薦為emacs.exe建立快捷方式,因?yàn)闀?huì)額外啟動(dòng)一個(gè)命令行窗口。
請(qǐng)選擇24以上的版本
延伸閱讀: FAQ 3.2
其他版本
個(gè)人推薦
- 64 bit version
http://sourceforge.net/projects/emacsbinw64/
本人使用的版本,后面的配置都是基于這個(gè)版本
版本號(hào):24.4.91
下面這兩個(gè)版本可以省去大部分配置的麻煩事。不過(guò)多勞多得,請(qǐng)自行選擇
- All-in-one Emacs Binary by Vincent Goulet
http://vgoulet.act.ulaval.ca/en/emacs/ - An Emacs Starter Kit for the Social Sciences by Kieran Healy
http://kieranhealy.org/resources/emacs-starter-kit/
基本操作
打開(kāi)emacs,同時(shí)按下Ctrl和h,然后鍵入t,閱讀新手教程,熟悉界面,基本術(shù)語(yǔ)和操作。
請(qǐng)不要跳過(guò)這一步!(但不要求熟練掌握)
本文后面的部分已經(jīng)假定你閱讀了這個(gè)教程,所以默認(rèn)遵循emacs的術(shù)語(yǔ)規(guī)范。
C代表Ctrl鍵。M代表Alt鍵。RET代表Enter鍵(回車(chē)鍵)。C-x代表同時(shí)按下Ctrl和x。C-x d RET代表先同時(shí)按下Ctrl和x,再按下d,最后再按下RET。我在后文的按鍵描述中,會(huì)經(jīng)常省略最后一步的回車(chē)操作。另外,請(qǐng)留意描述所用的英文字母的大小寫(xiě)。
Emacs里的大部分地方都支持自動(dòng)補(bǔ)全,快捷鍵是TAB。
配置篇|Configuration
編程基礎(chǔ)
你可能會(huì)奇怪,為什么配置emacs還需要編程?一般配置一個(gè)程序,不都是通過(guò)菜單欄打開(kāi)一個(gè)對(duì)話(huà)框,然后修改里面提供的選項(xiàng)么?在emacs里,的確有這么一套配置系統(tǒng),詳見(jiàn)Emacs's Customization Tutorial。但個(gè)人不推薦使用。因?yàn)?,第一,里面提供的選項(xiàng)并不完全,許多配置只能通過(guò)編程才能做到;第二,它也是通過(guò)在你的配置文件中加入一些代碼來(lái)實(shí)現(xiàn)的。
配置emacs的所有代碼構(gòu)成了一個(gè)配置文檔。Emacs的配置文檔是用elisp語(yǔ)言寫(xiě)的。elisp是lisp的一種方言。至于lisp語(yǔ)言,有人說(shuō)它是黑客的語(yǔ)言。不過(guò)你并不需要完全理解elisp才能配置emacs。至少我對(duì)elisp談不上熟練。不過(guò)我倒是看過(guò)一些lisp語(yǔ)言的入門(mén)教程,所以能夠看得懂elisp的官方幫助文檔。你可以參考Learn X in Y minutes來(lái)快速入個(gè)門(mén)。由于elisp的函數(shù)命名規(guī)則大部分都很直觀,所以只要了解了基本語(yǔ)法,大部分配置語(yǔ)句對(duì)你來(lái)說(shuō)都會(huì)變得很直白。下面列出幾個(gè)配置文檔時(shí)的常用函數(shù),只是讓你熟悉下elisp的語(yǔ)法。更多的函數(shù)會(huì)在用到時(shí)講解。
參考set
- 變量賦值。比如
(set 'a 5)相當(dāng)于a=5
參考setq
- 這個(gè)其實(shí)就是為了偷懶,在一次執(zhí)行多個(gè)賦值操作時(shí)少打幾個(gè)
'
參考let
-
let的意義在于批量執(zhí)行函數(shù)時(shí)定義共享參數(shù)??紤]下面這個(gè)使用情景,你希望連續(xù)調(diào)用函數(shù)A,B,C,它們都接受一個(gè)字符串參數(shù)s,s代表某個(gè)路徑。A負(fù)責(zé)打印字符串s,并提示接下來(lái)要利用s做什么事情;B負(fù)責(zé)切換到s指定的位置然后執(zhí)行一些操作;C負(fù)責(zé)將s加入到某個(gè)全局列表中。你當(dāng)然可以不用let,在調(diào)用函數(shù)前加上一句(set 's 一個(gè)字符串)即可。但這時(shí)定義的s會(huì)成為全局變量,進(jìn)而污染你的變量空間。
HOME
參考The Emacs Initialization File
- Emacs配置文檔常見(jiàn)的文件名有兩個(gè),
.emacs,init.el,雖然本質(zhì)上它們都是elisp腳本(像python腳本那樣)。 - 你可以用任何文本編輯器來(lái)編輯他們。個(gè)人推薦使用Notepad++,支持語(yǔ)法高亮,列編輯。Notepad++可以很方便的進(jìn)行區(qū)域注釋?zhuān)?code>Ctrl+
q,Shift+Ctrl+q),這對(duì)調(diào)試配置文檔很重要。當(dāng)然,在你熟悉emacs后,emacs也許會(huì)成為你的唯一編輯器 - 當(dāng)你在使用Notepad++編寫(xiě)自己的配置文檔時(shí),可能經(jīng)常需要執(zhí)行注釋或者反注釋某段代碼的操作。注釋時(shí)請(qǐng)用
Shift+Ctrl+q,反注釋時(shí)請(qǐng)用Ctrl+q。前者會(huì)保證在每一行代碼前都加一個(gè);,后者則是,如果本行代碼以;開(kāi)頭,就刪掉一個(gè);,如果不以;開(kāi)頭,則添加一個(gè);。容易理解,當(dāng)代碼塊中包含注釋時(shí),你肯定不希望在注釋掉代碼的同時(shí)反注釋掉那些注釋。
接下來(lái),讓我們先來(lái)了解emacs在哪里尋找配置文檔,以及會(huì)具體選擇哪種格式。
參考How Emacs Finds Your Init File,了解emacs啟動(dòng)時(shí)配置文件的加載規(guī)則
- Emacs會(huì)在系統(tǒng)中尋找一個(gè)名為HOME的變量,然后拷貝一個(gè)副本供自己使用,并在其指定的路徑下尋找配置文件
- 各個(gè)平臺(tái)的默認(rèn)HOME路徑請(qǐng)參考
HOME and Startup Directories on MS-Windows - windows平臺(tái),在cmd使用
echo %userprofile%來(lái)查看HOME[3] -
The MS-Windows System Registry介紹了emacs尋找默認(rèn)參數(shù)的路徑的先后順序
- 注意,環(huán)境變量是第一位的,如果沒(méi)有才會(huì)在注冊(cè)表中尋找。也就是說(shuō),如果環(huán)境變量和注冊(cè)表都包含HOME的話(huà),emacs會(huì)拷貝前者作為自己的副本。這通常不是一個(gè)好消息。一方面,你希望盡量按照自己的意愿來(lái)設(shè)置emacs的HOME變量;另一方面,你可能已經(jīng)為別的應(yīng)用程序創(chuàng)建了系統(tǒng)級(jí)別的HOME,以至于不得不把emacs的配置文件也放在那里
- 個(gè)人認(rèn)為,一個(gè)更合理的加載邏輯應(yīng)該是,順序檢測(cè)一系列路徑,后面檢測(cè)到的值覆蓋前面的。這樣你就可以通過(guò)創(chuàng)建注冊(cè)表的方式來(lái)避免與系統(tǒng)環(huán)境變量的沖突
- 對(duì)于windows 7/8/8.1,如果你的環(huán)境變量和注冊(cè)表里都沒(méi)有HOME,emacs會(huì)把
%userprofile%的值設(shè)置為HOME,一般是
C:\Users\your-user-name\AppData\Roaming
通常,emacs會(huì)優(yōu)先加載
.emacs,如果找不到,并且存在文件夾.emacs.d,會(huì)嘗試加載其中的init.el基于前面的介紹,一個(gè)比較好的安裝配置方案如下:
將emacs的壓縮包解壓到某個(gè)路徑
運(yùn)行bin路徑下的
runemacs.exec-x d ~ RET,編輯區(qū)域左上角的文件路徑即emacs的HOME?;蛘哝I入C-h v user-init-file并查看返回值在HOME路徑下,emacs會(huì)自動(dòng)生成
.emacs.d文件夾,如果沒(méi)有請(qǐng)自己建立-
在該文件夾下新建
init.el,輸入如下代碼
;; This file is only for windows 7/8/8.1
;; The only thing it does is to set the HOME directories for emacs,
;; then trigger the init.el in the directory specified by HOME to
;; accomplish the true initialization
;; You should put this file in the default HOME directory right after
;; emacs is installed
(setenv "HOME" "C:/emacs/") ;; you can change this dir to the place you like
(load "~/.emacs.d/init.el")
```
- 最后一行代碼中,
~代表emacs的HOME路徑。由于前面已經(jīng)重新設(shè)定HOME,所以這行代碼相當(dāng)于調(diào)用C:/emacs/.emacs.d/下的init.el。關(guān)于load命令,后面有詳細(xì)解釋 - 順便刪掉前面幾步中你見(jiàn)到的任何
.emacs文件,保證emacs利用init.el啟動(dòng)
這樣做的好處是,除了可以自定義.emacs.d所在的路徑,還可以方便的備份整個(gè)文件夾,因?yàn)椴寮ǔ?huì)被安裝到這個(gè)文件夾下。如果需要換到其他電腦甚至平臺(tái)時(shí),只需要把整個(gè)文件夾復(fù)制過(guò)去,然后類(lèi)似于上述步驟那樣,想辦法讓真正的init.el發(fā)揮作用即可。
使用init.el而不是.emacs來(lái)配置,可以保證配置文件的結(jié)構(gòu)化和模塊化,方便維護(hù)。
最后規(guī)定后文要經(jīng)常用到的幾個(gè)代指
-
~代指重定義后的emacs的HOME路徑 -
user-emacs-directory指代~\emacs.d,該路徑可以在啟動(dòng)emacs后通過(guò)C-h v user-emacs-directory來(lái)查看。 -
init.el代指user-emacs-directory下的版本,是我們要配置的版本
延伸閱讀:
- General Variables 必讀
- DotEmacsDotD
- FAQ 3.4 3.5 3.6
- The Emacs Initialization File TD
- Summary: Sequence of Actions at Startup TD
PATH
從這個(gè)章節(jié)開(kāi)始,對(duì)于提到的非emacs程序,都假定這些程序的主要可執(zhí)行文件(exe)所在路徑已經(jīng)被添加到系統(tǒng)的環(huán)境變量PATH中。 對(duì)于python,R,pandoc,cygwin等,網(wǎng)上有很多安裝并配置環(huán)境變量的教程。仍不熟悉基本操作的可以先看看“延伸閱讀”的第一篇文章。
在向init.el寫(xiě)入任何代碼之前,先打開(kāi)emacs試用一下。鍵入M-x python,如果沒(méi)報(bào)錯(cuò)的話(huà),就成功進(jìn)入了python模式。Emacs并不自帶python,那它是怎么知道去哪里調(diào)用python.exe的呢?
參考Emacs: Set Environment Variables within Emacs
原來(lái)Emacs繼承了windows的環(huán)境變量PATH。輸入M-x getenv RET PATH查看PATH[4]。
實(shí)際上,當(dāng)你在emacs中運(yùn)行shell時(shí)[5],各個(gè)指令的搜索路徑是PATH。而當(dāng)emacs自身需要尋找某個(gè)可執(zhí)行文件時(shí),比如python,搜索路徑是exec-path,而默認(rèn),在windows平臺(tái)下,emacs會(huì)直接拷貝系統(tǒng)的環(huán)境變量。也就是所說(shuō),在init.el中修改emacs的PATH副本并不會(huì)同時(shí)修改exec-path。
當(dāng)我們安裝了一些只想同emacs結(jié)合使用的軟件時(shí),如果不想修改系統(tǒng)的環(huán)境變量,可以在init.el中加入:
(setenv "PATH"
(concat
"C:/Program Files (x86)/Notepad++" ";"
(getenv "PATH")
)
)
這樣,你就可以在emacs中打開(kāi)一個(gè)shell,然后鍵入notepad++來(lái)調(diào)用它了。注意,這個(gè)修改并不會(huì)在exec-path中追加相應(yīng)的路徑。如果你希望emacs也能調(diào)用notepad++,還需要同步修改exec-path,具體方法請(qǐng)參見(jiàn)原文。
如果你像我一樣不想同步exec-path,最簡(jiǎn)單的方案就是把相關(guān)程序的安裝路徑添加到系統(tǒng)的環(huán)境變量中。
延伸閱讀:
加載
對(duì)于任何軟件,一個(gè)得心應(yīng)手的配置基本基本都要用到插件,比如Chrome。
對(duì)于emacs,新安裝的插件經(jīng)常要你自己去啟動(dòng)并配置。這是emacs上手難的重要原因之一。考慮一個(gè)最簡(jiǎn)單的安裝流程,你從網(wǎng)上下載了某個(gè)**.el文件,然后在init.el中load這個(gè)文件。是不是load那一步顯得很別扭?而功能更強(qiáng)大的插件可能由更復(fù)雜的文件結(jié)構(gòu)組成,需要你做更多的準(zhǔn)備工作才能正常使用。這個(gè)時(shí)候,一個(gè)插件管理系統(tǒng)就很必要了。24以上的版本都集成了一個(gè)插件管理器elpa,可以方便的通過(guò)M-x list-packages來(lái)安裝插件。不過(guò)別高興的太早,通過(guò)elpa安裝的插件通常仍需要你手動(dòng)來(lái)加載和配置。
注意,是加載,而不是激活?;貞浵履闶窃趺词褂肅hrome的插件系統(tǒng):安裝插件,插件的圖標(biāo)出現(xiàn)在瀏覽器地址欄的右側(cè),點(diǎn)擊插件的圖標(biāo)來(lái)使用插件(激活其功能),有的插件甚至默認(rèn)激活。這個(gè)過(guò)程中,所有加載和初始化配置的工作都由軟件自動(dòng)完成,你唯一需要做的就是選擇用不用(激活)而已。
然而,elpa要求你自己完成加載和配置的步驟。一般來(lái)說(shuō),常見(jiàn)的載入命令有,require,load,autoload等。而所謂的配置就是初始化一些參數(shù)。
emacs一般稱(chēng)“插件”為"package"或者"library"。本質(zhì)上,它們都提供一堆定義好的函數(shù),來(lái)實(shí)現(xiàn)一些操作,進(jìn)而實(shí)現(xiàn)某個(gè)功能。這里多說(shuō)幾句。在emacs中,連移動(dòng)光標(biāo)這種最底層的操作都有對(duì)應(yīng)的函數(shù)。比如,你在emacs中可以鍵入C-f來(lái)將光標(biāo)向右移動(dòng)一個(gè)字符,同時(shí)也可鍵入M-x forward-char來(lái)實(shí)現(xiàn)。任何復(fù)雜的功能,比如給文檔生成一個(gè)目錄,都可以被分解為一個(gè)個(gè)操作,或者說(shuō)調(diào)用一個(gè)個(gè)函數(shù),而這些函數(shù)順序執(zhí)行下來(lái)功能就得到了實(shí)現(xiàn)。
當(dāng)emacs想要加載某個(gè)插件時(shí),歸根到底需要定位并運(yùn)行一個(gè)(也許是一些)腳本文件,那個(gè)腳本里定義了實(shí)現(xiàn)插件功能所需的變量和函數(shù)。emacs將它們轉(zhuǎn)變?yōu)榭晒┳约菏褂玫膶?duì)象(elisp object),放到運(yùn)行環(huán)境中等待調(diào)用。而腳本自身還可以在內(nèi)部進(jìn)一步加載其他腳本。下面,來(lái)了解加載腳本的幾個(gè)語(yǔ)句,load,require,load-file,autoload。
參考Emacs Lisp's Library System: What's require, load, load-file, autoload, feature?
-
load一個(gè)位于硬盤(pán)上的文件,意味著執(zhí)行這個(gè)文件里的所有elisp語(yǔ)句,然后將執(zhí)行結(jié)果放進(jìn)emacs的運(yùn)行環(huán)境 - Feature可以理解為“特色功能”,比如,你在蘋(píng)果的App Store里查看應(yīng)用程序簡(jiǎn)介時(shí),一般都會(huì)看到一個(gè)以Features開(kāi)頭的段落。單數(shù)形式,feature,一般對(duì)應(yīng)一個(gè)插件的名字,因?yàn)橐话悴寮拿种苯颖砻魉鼘?shí)現(xiàn)的功能。復(fù)數(shù)形式,features,是一個(gè)用來(lái)存儲(chǔ)feature的列表,這個(gè)列表可以告訴emacs哪些插件經(jīng)被加載了。一般情況下,一個(gè)插件的啟動(dòng)腳本的結(jié)尾會(huì)調(diào)用
(provide '<symbol name>),將'<symbol name>加入到features中去。'<symbol name>一般就是插件的名字 -
(require '<symbol name>)會(huì)先查看features里面是否存在<symbol name>。如果存在,語(yǔ)句執(zhí)行完畢。如果不存在,基于它來(lái)猜一個(gè)文件名,或者由require的第二個(gè)參數(shù)直接指定文件名,然后load文件。注意,load完成后,require函數(shù)會(huì)再一次查看features列表中是否存在'<symbol name>,如果發(fā)現(xiàn)還是不存在,視參數(shù)<soft-flag>來(lái)決定是否報(bào)錯(cuò) -
require的意義在于避免重復(fù)加載。比如,某個(gè)插件的啟動(dòng)腳本中需要用到另一個(gè)插件提供的某個(gè)函數(shù)。那么它就會(huì)require這個(gè)插件,保證插件已被載入,然后再執(zhí)行后續(xù)語(yǔ)句。 -
load會(huì)搜索load-path,load-file需要指定文件路徑,autoload在一個(gè)函數(shù)被call后再load指定文件
延伸閱讀 Required Feature
其實(shí),連整個(gè)emacs的啟動(dòng)都可以概括為一句話(huà):加載一系列腳本。只不過(guò)這些腳本有的是內(nèi)置的(built in),有的是你安裝的插件包含的,有的是你自己寫(xiě)的。
配置emacs歸根結(jié)底是在配置各種各樣的腳本。
接下來(lái),請(qǐng)思考如下問(wèn)題。
你可以在init.el就load各種各樣的腳本,使得emacs在啟動(dòng)時(shí)就把整個(gè)使用過(guò)程中可能用到的函數(shù)一次性準(zhǔn)備好。但這樣真的好么?
參考Autoload
-
autoload告訴emacs某個(gè)地方有一個(gè)定義好的函數(shù),并且告訴emacs,先別加載,只要記住在調(diào)用這個(gè)函數(shù)時(shí)去哪里尋找它的定義即可 - 這樣做的一個(gè)好處是,避免在啟動(dòng)emacs時(shí)因?yàn)閳?zhí)行過(guò)多代碼而效率低下,比如啟動(dòng)慢,卡系統(tǒng)等。想象一下,如果你安裝了大量的有關(guān)python開(kāi)發(fā)的插件,而某次打開(kāi)emacs只是希望寫(xiě)點(diǎn)日記,你肯定不希望這些插件在啟動(dòng)時(shí)就被加載,讓你白白等上幾秒,也不希望這些插件在你做文本編輯時(shí)搶占系統(tǒng)資源(內(nèi)存,CPU時(shí)間等)。所以,一個(gè)合理的配置應(yīng)該是,當(dāng)你打開(kāi)某個(gè)python腳本,或者手動(dòng)進(jìn)入python的編輯模式時(shí),才加載那些插件
- 一個(gè)簡(jiǎn)單概括:“只注冊(cè)函數(shù)名而不定義函數(shù)本身”
前面介紹了幾種加載機(jī)制。加載的目的在于定義變量和函數(shù)以供使用。任何插件,只有先被加載才能被使用。而且通常,你都希望先加載一個(gè)插件,再來(lái)配置它??紤]如下情景。
你的插件中定義了一個(gè)變量a,默認(rèn)值是1,插件內(nèi)定義的許多函數(shù)都在內(nèi)部使用了a。你希望在自己使用這些函數(shù)時(shí),用到的a的值是2。有兩種實(shí)現(xiàn)途徑。一種是直接到插件的腳本文件中修改a的值為2。這叫做"hard coding",有很多壞處。比如,每次更新插件,都要重新修改。另一種方法是,等這個(gè)插件已經(jīng)被加載后,修改相應(yīng)的elisp object。那自然,你得先讓這個(gè)對(duì)象存在于emacs中,然后才能修改。所以要先加載,讓需要配置的變量得到定義,再去修改變量的值。
下面,讓我們來(lái)看看這些腳本文件究竟長(zhǎng)什么樣子。打開(kāi)emacs內(nèi)置插件的文件夾,emacs安裝路徑\share\emacs\24.4.91\lisp,你會(huì)看到一些子文件夾,一些后綴名為gz的壓縮文件,以及一些后綴名為elc的文件。壓縮文件中存放的其實(shí)是同名的.el文件,也就是前面一直在提的腳本。.elc是這個(gè)腳本編譯好的版本,可以加快載入速度,不適合人類(lèi)閱讀。所以,如果你想查看一個(gè)插件的源代碼,請(qǐng)查看.el文件。.el被放在壓縮包是為了避免源代碼被修改,進(jìn)而造成各種問(wèn)題。另外,加載插件時(shí),總是會(huì)優(yōu)先加載編譯好的版本,其默認(rèn)的文件擴(kuò)展名即.elc;如果不存在,才會(huì)加載.el或者其他格式的文件。
延伸閱讀
Elpa
有了前面鋪墊的基礎(chǔ)概念后,讓我們來(lái)學(xué)習(xí)使用elpa。Elpa(Emacs package system)也是一個(gè)插件,只不過(guò)它是管理插件的插件。在emacs24和更高的版本中,elpa是一個(gè)內(nèi)置插件,腳本文件package.el位于emacs安裝路徑\share\emacs\24.4.91\lisp\emacs-lisp。有些插件因?yàn)橛啥鄠€(gè)腳本構(gòu)成,會(huì)被放在一個(gè)單獨(dú)的文件夾中。初始化這個(gè)腳本的主腳本的文件名通常由插件名加上.el構(gòu)成。注意,如果你修改了一個(gè)腳本文件,并且同名.elc存在,那么必須重新編譯該腳本才能使改動(dòng)生效。
參考Emacs: How to Install Packages Using ELPA, MELPA, Marmalade
- 默認(rèn)的插件安裝路徑是
~/.emacs.d/elpa - 默認(rèn)情況下,elpa的相關(guān)函數(shù)已經(jīng)在啟動(dòng)emacs時(shí)注冊(cè)(回憶
autoload)。直接鍵入M-x list-packages即可調(diào)用 - 由于在啟動(dòng)時(shí)只是注冊(cè)函數(shù)名,所以elpa的啟動(dòng)腳本并未加載。如果你想在配置文檔中修改腳本中定義的變量,比如
package-archives,請(qǐng)先(require 'package)。該原則適用于其他插件的配置。也就是說(shuō),如果你想在init.el中修改某個(gè)插件的某個(gè)變量的值,請(qǐng)保證emacs在執(zhí)行這條修改語(yǔ)句時(shí),相關(guān)變量已經(jīng)得到定義 - 一般用來(lái)初始化該插件的主腳本的文件名都是
插件名.el
為了保證你可以自行試驗(yàn)后文的操作,現(xiàn)在請(qǐng)你到init.el中添加一段代碼:
(require 'package)
;;; Standard package repositories
;; We include the org repository for completeness, but don't normally
;; use it.
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/"))
;;; Also use Melpa for most packages
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "http://melpa-stable.milkbox.net/packages/"))
上述代碼給elpa添加了幾個(gè)額外的插件來(lái)源。不用理會(huì)其中的語(yǔ)法,反正在后面配置init.el時(shí)我會(huì)提醒你刪掉這段代碼。
需要注意,elpa智能但不傻瓜。
參考 Emacs 24 Package System Problems
- 安裝一個(gè)插件后,elpa會(huì)自動(dòng)在插件所在目錄下生成一個(gè)autoloads文件。這個(gè)文檔本意是方便你調(diào)用插件的。比如,你可以在
init.el中加入(load 某某插件-autoloads)來(lái)加載該插件 - 如果你希望用
require的方式來(lái)加載插件,并且還希望require這個(gè)autoloads文件,會(huì)出現(xiàn)一個(gè)問(wèn)題。autoloads的結(jié)尾并沒(méi)有(provide '某某插件-autoloads),所以require一定會(huì)報(bào)錯(cuò)。而且這樣做也沒(méi)什么意義。因?yàn)槟愕哪康脑谟趯⒉寮旧淼拿址诺絝eatures列表中,而不是“插件名-autoloads”。所以,請(qǐng)load而不是requireautoloads文件 - 當(dāng)然,你也可以直接加載插件的主腳本,比如
(require 'auto-complete)而不是(load 'auto-complete-autoloads)。不過(guò),這樣做有兩個(gè)壞處。第一,有些插件可能會(huì)指導(dǎo)elpa在生成autoloads文件時(shí)加入一些配置代碼。在這種情形下,有可能你通過(guò)load這個(gè)autoloads文件能成功初始化插件,而直接load或者require插件的主腳本則不能。第二,autoloads由autoload函數(shù)構(gòu)成,autoload的好處如前所述,可以輕便化emacs的啟動(dòng)
load-path
下面來(lái)談一個(gè)很重要的變量,load-path,其變量類(lèi)別是“列表”,作用范圍是“全局變量”。打開(kāi)emacs,鍵入C-h v load-path RET。如果你是在剛安裝完emacs后鍵入這個(gè)命令,得到的返回值應(yīng)該類(lèi)似這樣:
("c:/emacs/share/emacs/24.4.91/site-lisp" "c:/emacs/share/emacs/site-lisp"
此處省略若干行
中文部分是我自己加上的,告訴你我為了節(jié)省空間,刪掉了許多行。
每次使用elpa安裝插件后,這個(gè)值都會(huì)發(fā)生改變。比如,在初次使用elpa安裝完ack插件后,
load-path會(huì)變?yōu)椋?/p>
("~/.emacs.d/elpa/ack-1.3/" "c:/emacs/share/emacs/24.4.91/site-lisp" "c:/emacs/share/emacs/site-lisp"
此處省略若干行
請(qǐng)自行把~腦補(bǔ)為HOME路徑。
通過(guò)對(duì)比,不難發(fā)現(xiàn),emacs在啟動(dòng)時(shí),會(huì)將user-emacs-directory/elpa路徑下的的所有文件夾加入到load-path的頭部。由于elpa的默認(rèn)安裝路徑是~/.emacs.d/elpa,所以第一行會(huì)是~/.emacs.d/elpa/ack-1.3/。你用elpa安裝的任何插件,其所在路徑都會(huì)位于load-path頭部。我想強(qiáng)調(diào),這個(gè)位置,非常重要。
在emacs24及更高的版本中,emacs自帶了一個(gè)org插件,位于emacs安裝路徑\share\emacs\24.4.91\lisp\org,這個(gè)插件后面會(huì)詳細(xì)講解。每次啟動(dòng)emacs,這個(gè)路徑都會(huì)被添加到load-path中。在emacs中鍵入M-x org-mode會(huì)調(diào)用org插件,讓編輯區(qū)域進(jìn)入org模式。
org插件有很多相關(guān)插件。假設(shè)現(xiàn)在,你想通過(guò)elpa安裝某個(gè)相關(guān)插件,比如,bog,執(zhí)行如下操作:
- 鍵入
M-x list-packages RET,出現(xiàn)選擇編碼的提示,鍵入RET - 定位bog:鍵入
C-s Extensions for research notes in Org mode,然后鍵入C-s RET - 在emacs窗口左側(cè),點(diǎn)擊光標(biāo)所在行出現(xiàn)的小個(gè)左箭頭,然后點(diǎn)擊bog
你會(huì)在新出現(xiàn)的窗口看到語(yǔ)句Requires: org-8.0.0, dash-2.5.0,表明該插件依賴(lài)額外的兩個(gè)插件org和dash。elpa會(huì)智能的安裝所有依賴(lài)插件。注意,盡管你的emacs自帶org,elpa還是會(huì)選擇安裝自己的插件源中的版本。所以,最后load-path會(huì)變?yōu)椋?/p>
("c:/emacs/.emacs.d/elpa/bog-0.6.0/"
"c:/emacs/.emacs.d/elpa/dash-20150311.2355/"
"c:/emacs/.emacs.d/elpa/org-20150316/"
"c:/emacs/.emacs.d/lisp"
"c:/emacs/share/emacs/24.4.91/site-lisp"
此處省略若干行
"c:/emacs/share/emacs/24.4.91/lisp/org"
此處省略若干行
elpa安裝的org排在了emacs自帶org的前面。
load-path如其名字所示,告訴emacs在加載任何腳本時(shí),如果沒(méi)有指明腳本所在路徑,那么就去load-path所含的路徑中尋找。然后使用第一個(gè)找到的腳本。也就是說(shuō),此后你調(diào)用org插件時(shí),使用的都會(huì)是elpa安裝的版本,即插件的一個(gè)版本'shadow'了另一個(gè)版本。
'shadow'現(xiàn)象很常見(jiàn)。除了前面提到的'shadow'內(nèi)置插件,elpa安裝的插件的新版本會(huì)'shadow'舊版本。請(qǐng)記住一個(gè)非常有用的命令,list-load-path-shadows,它可以總結(jié)所有插件當(dāng)前的'shadow'狀態(tài)?,F(xiàn)在,請(qǐng)你自己鍵入M-x list-load-path-shadows RET,然后閱讀下返回的信息。
'shadow'之所以發(fā)生,是因?yàn)?code>load-path中包含了同一個(gè)插件多個(gè)版本的腳本路徑,哪個(gè)版本排在前面就使用哪個(gè)。
總結(jié)下,在配置插件時(shí),請(qǐng)時(shí)常反問(wèn)自己如下問(wèn)題:
- 當(dāng)我想加載一個(gè)插件時(shí),emacs知不知道它的所在路徑?
- 當(dāng)我想修改插件定義的某個(gè)參數(shù)時(shí),是否已經(jīng)加載了這個(gè)插件?
- 會(huì)不會(huì)某個(gè)已經(jīng)存在的版本,shadow了我想使用的版本?
最后,學(xué)習(xí)下修改load-path的常用操作。
- 優(yōu)先關(guān)注
add-to-list的語(yǔ)法。
延伸閱讀
牛刀小試
整套配置文件的思路參考Emacs配置文件——新手攻略。
雖說(shuō)是新手攻略,還是太簡(jiǎn)潔了些。不過(guò),請(qǐng)你大概閱讀一遍,并將作者的配置文件下載到本地,解壓,然后將emacs.d-master文件夾下的文件所有文件拷貝到你的user-emacs-directory。這會(huì)覆蓋你自己的init.el,不要緊,當(dāng)然你為了保險(xiǎn)可以備份下。下面用之前建立的專(zhuān)門(mén)用來(lái)調(diào)試配置文檔的快捷方式運(yùn)行emacs。emacs會(huì)按照init.el的指導(dǎo)自動(dòng)安裝并配置相關(guān)插件。但不知你的運(yùn)行結(jié)果怎樣,我的會(huì)報(bào)錯(cuò)。
Required feature ... was not provided
Debugger entered--Lisp error: (error "Required feature `switch-window-autoloads' was not provided")
require(switch-window-autoloads)
eval-buffer(#<buffer *load*-432260> nil "c:/emacs/.emacs.d/lisp/editing-utils/init-switch-window.el" nil t)
有了前面鋪墊的基礎(chǔ),你應(yīng)該能很好理解錯(cuò)誤的原因:應(yīng)該load一個(gè)autoloads文檔,而不是require。定位到出錯(cuò)的文檔,把(require 'switch-window-autoloads)修改為(load "switch-window-autoloads")。注意,根據(jù)require和load的語(yǔ)法規(guī)則,我把switch-window-autoloads從一個(gè)符號(hào)(Symbol)改成了一個(gè)字符串(String)。
順便檢查下同文件夾下的其他配置文檔,更正相同的錯(cuò)誤。關(guān)閉emacs再次運(yùn)行。你會(huì)發(fā)現(xiàn),后續(xù)還會(huì)在各種各樣的init文檔中出現(xiàn)同樣的錯(cuò)誤。請(qǐng)一一更正。
"Cannot open load file" ... "org-exp"
Debugger entered--Lisp error: (file-error "Cannot open load file" "no such file or directory" "org-exp-blocks")
require(org-exp)
(progn (require (quote org-exp)) (require (quote org-clock)) (require (quote org-fstree)))
(lambda nil (progn (require (quote org-exp)) (require (quote org-clock)) (require (quote org-fstree))))()
eval-after-load(org (lambda nil (progn (require (quote org-exp)) (require (quote org-clock)) (require (quote org-fstree)))))
eval-buffer(#<buffer *load*-5658> nil "c:/emacs/.emacs.d/lisp/init-org.el" nil t)
這里的quote指單引號(hào)字符'。請(qǐng)打開(kāi)文檔定位出錯(cuò)語(yǔ)句。然后Google搜索"org-exp",發(fā)現(xiàn)只有org-exp-blocks,估計(jì)"org-exp"是作者自己寫(xiě)的吧。請(qǐng)注釋或刪除(require 'org-exp)。
在讀過(guò)org-exp-blocks的幫助文檔后,你可能非常想加載這個(gè)插件。不過(guò)請(qǐng)注意,文檔中提到:
make sure that the path to org's contrib directory is in your load-path and add the following to your .emacs.
什么是"contrib directory"?檢索下本地的org插件所在文件夾,無(wú)論是elpa版本,還是內(nèi)置的,都沒(méi)有"contrib directory"。Google后發(fā)現(xiàn),這個(gè)目錄里包含了許多org用戶(hù)寫(xiě)的插件,因?yàn)椴皇莖rg官方開(kāi)發(fā)者寫(xiě)的,所以沒(méi)被包含在前面的兩個(gè)版本中。
到這里,也許你會(huì)以為org-exp-blocks也在"contrib directory"中。恭喜你,上當(dāng)了。
參考Org-mode Contributed Packages
- 請(qǐng)看"Moved to core"那一部分,很容易找到下面這句話(huà)
"Org-exp-blocks is now part of the Org core. Link to raw file." - 也就是說(shuō),現(xiàn)在不用手動(dòng)調(diào)用org-exp-blocks了。所以,你其實(shí)什么也不用做
- 不得不說(shuō),有點(diǎn)坑爹。吃一塹長(zhǎng)一智,請(qǐng)記住這個(gè)頁(yè)面,以后配置文件出現(xiàn)問(wèn)題時(shí),也許不是被'Moved to core',就是被'Obsolete'了
做完以上操作,再次啟動(dòng)emacs,應(yīng)該能順利進(jìn)入歡迎界面了。不過(guò),要知道,還是有很多未被'Moved to core'但非常有用的插件,一般只包含在org官網(wǎng)提供的beta版本中。那應(yīng)該怎樣獲取呢?
Build Org
- 想獲得官方的beta版本,需要用到工具Git。下載并安裝好。
- 用桌面上出現(xiàn)的Git快捷方式打開(kāi)Git,鍵入
pwd,記住當(dāng)前的工作路徑?;蛘吣阋部梢酝ㄟ^(guò)cd命令來(lái)切換到你想要的工作路徑 - 記住當(dāng)前的工作路徑。鍵入
git clone git://orgmode.org/org-mode.git。等待beta版本的org被下載到本地。提示:也許在你的git中,粘帖操作被綁定為鼠標(biāo)右鍵 - 將工作路徑下的org-mode文件夾重名為org-beta,拷貝到
user-emacs-directory。重命名那步?jīng)]什么特別含義,只是為了區(qū)分。如果你選擇拷貝到其他路徑,請(qǐng)自行調(diào)整后續(xù)命令 - 打開(kāi)
init-org.el,在第一行加入(add-to-list 'load-path (expand-file-name "org-beta\\lisp" user-emacs-directory)),相信你不用查閱幫助文檔也能理解expand-file-name的作用。這行代碼將org-beta的核心腳本所在路徑添加到load-path,相當(dāng)于讓beta版本'shadow'其他版本 - 你還需要把org-beta目錄下下的
org-contrib\lisp添加到load-path,因?yàn)檫@個(gè)目錄即前面所說(shuō)的"contrib directory"。在第一行下面額外添加代碼:(add-to-list 'load-path (expand-file-name "org-beta\\org-contrib\\lisp" user-emacs-directory)) - 到這步,你應(yīng)該可以正常使用emacs了。不過(guò),為了真正的“安裝”org-beta,請(qǐng)繼續(xù)執(zhí)行下述操作
- 額外下載并安裝Cygwin。參考Cygwin詳解“Cygwin在線安裝指南”一節(jié)。一定要執(zhí)行“Cygwin中模塊的各種分類(lèi)”一節(jié)提到的操作,即安裝Devel這個(gè)部分的模塊,因?yàn)橐玫狡渲械腶utomake模塊。記得安裝完后配置環(huán)境變量
- 打開(kāi)emacs,鍵入
M-x pwd,返回路徑如果不是org-beta所在的那個(gè),就切換過(guò)去。具體操作,鍵入C-x d ~ RET .emacs.d/org-mode/ RET - 切換后,再次鍵入
M-x pwd,確認(rèn)路徑正確。然后鍵入M-! make。注意,Alt和!要一起按,即同時(shí)鍵入Alt,Shift和數(shù)字鍵1。make命令源于Cygwin中的automake模塊,它會(huì)把org-beta的所有核心腳本編譯好,然后建立幫助文檔的索引 - 打開(kāi)emacs,鍵入
M-x org-version RET,返回信息中包含的路徑如果是org-beta,即表明'shadow'成功 - 前面幾步的操作也適用于編譯其他插件
現(xiàn)在,請(qǐng)你執(zhí)行如下操作:
- 刪掉
user-emacs-directory下的elpa文件夾 - 重新運(yùn)行emacs,讓emacs在更正后的配置文檔的指導(dǎo)下重新初始化
你會(huì)發(fā)現(xiàn),居然又報(bào)錯(cuò)了!出錯(cuò)語(yǔ)句是配置文檔org-magit-autoloads中的(eval-after-load "org" '(progn (org-add-link-type "magit" 'org-magit-open 'org-magit-export) (add-hook 'org-store-link-functions 'org-magit-store-link)))。我想你已經(jīng)猜到了,這一定跟使用beta版本的org有關(guān)。注釋掉init-org.el中的頭兩行代碼,讓emacs使用elpa版本的org。然后打開(kāi)emacs鍵入M-x list-packages來(lái)強(qiáng)制刷新下插件列表。最后再次刪掉elpa文件夾并運(yùn)行emacs。如果以后你想使用beta版本,記得反注釋掉頭兩行代碼。
一陣繁忙的下載后,emacs應(yīng)該能不報(bào)錯(cuò)的完成初始化。但是看看編譯記錄(complied log),發(fā)現(xiàn)有大量的warning信息。請(qǐng)把log保存下來(lái),以便以后分析。把光標(biāo)切換到complied log區(qū)域,鍵入C-x C-f,然后選擇合適的路徑和文件名,鍵入RET保存log。
后文中我會(huì)以init.log來(lái)代指這個(gè)文件。
恭喜,現(xiàn)在你已經(jīng)擁有了一個(gè)功能非常強(qiáng)大的emacs了。趕快探索下吧。
最后補(bǔ)充下我個(gè)人偏好的額外設(shè)置。
init.el
關(guān)閉煩人的警示音。禁止啟動(dòng)后的歡迎頁(yè)面。
;; Turn off sound alarms completely
(setq ring-bell-function 'ignore)
;; disable welcome page
(setq inhibit-startup-message t)
在custom-set-variables區(qū)域添加代碼,讓emacs啟動(dòng)后自動(dòng)全屏。請(qǐng)注意括號(hào)的匹配。
(custom-set-variables
其他代碼
'(initial-frame-alist (quote ((fullscreen . maximized))))
)
當(dāng)你通過(guò)emacs的自定義系統(tǒng)(本篇最開(kāi)始提到)修改emacs設(shè)置后,emacs自動(dòng)將相關(guān)代碼添加到init.el的custom-set-variables區(qū)域。這里我們直接添加代碼來(lái)實(shí)現(xiàn)功能。
安裝Emacs Speaks Statistics: ESS,使org模式下可以運(yùn)行R,SAS等(當(dāng)然,你要額外安裝這些統(tǒng)計(jì)軟件)
參考Installing ESS on your system
- 同編譯org-beta的步驟類(lèi)似。我把
ess-14.09放到user-emacs-directory,然后運(yùn)行emacs并切換工作路徑到ess-14.09,最后make - 在
init.el中添加
(add-to-list 'load-path (expand-file-name "ess-14.09" user-emacs-directory))
(load "ess-autoloads")
- 運(yùn)行emacs,鍵入
M-x R。如果能進(jìn)入R session,那么就是安裝成功 -
(load "ess-autoloads")是最小配置,如果你希望用到ess的全部功能,請(qǐng)加載ess-site.el(注意load-path)
init-org.el
開(kāi)啟org模式下的代碼高亮;導(dǎo)出代碼塊時(shí)不運(yùn)行代碼;跳過(guò)運(yùn)行代碼塊時(shí)的確認(rèn)步驟(可能有安全風(fēng)險(xiǎn))。在注釋;; Various preferences下方添加代碼
;; Various preferences
(setq
其他代碼
;; turn on the syntax highlight in the org mode
org-src-fontify-natively t
;; when exporting the org file, do not evaluate the code block if the exports header is both
org-export-babel-evaluate nil
;; skip the confirmation step when evaluate a code block
org-confirm-babel-evaluate nil)
導(dǎo)出PDF時(shí)代碼高亮使用minted,在上面的代碼塊下方添加
;; Include the latex-exporter
(require 'ox-latex)
;; Add minted to the defaults packages to include when exporting.
;; set snippet-flat to nil to exclude minted for latex preview
;; see http://orgmode.org/worg/org-tutorials/org-latex-preview.html
(add-to-list 'org-latex-packages-alist '("" "minted" nil))
;; Tell the latex export to use the minted package for source
;; code coloration.
(setq org-latex-listings 'minted)
;; Let the exporter use the -shell-escape option to let latex
;; execute external programs.
;; This obviously and can be dangerous to activate!
;; multiple compile in order to generate everything
(setq org-latex-pdf-process
'("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"bibtex %b"
"xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
參考Export org-mode code block and result with different styles
- 這段代碼要求你安裝了Latex和Python。推薦使用TeX Live和Anaconda。確保Latex安裝了minted插件,Python安裝了Pygments插件。另外請(qǐng)配置好環(huán)境變量
- Latex有時(shí)需要多次編譯才能正確導(dǎo)出所有元素。因此會(huì)出現(xiàn)三個(gè)
xelatex語(yǔ)句 -
bibtex命令可以生成.bbl文件,這個(gè)文件用來(lái)生成參考文獻(xiàn)列表。放到中間是因?yàn)?,它需要借助第一個(gè)xelatex生成的.aux文件,一個(gè)臨時(shí)輔助文件,來(lái)實(shí)現(xiàn)轉(zhuǎn)換。原理很簡(jiǎn)單。文獻(xiàn)信息存儲(chǔ)在格式為bibtex的.bib文件中。根據(jù)不同的文獻(xiàn)引用標(biāo)準(zhǔn)和具體的引用條目(由.aux提供),.bib內(nèi)的信息在經(jīng)過(guò)篩選、重組后被放入.bbl文件,用來(lái)生成最終的文獻(xiàn)引用內(nèi)容 - 因?yàn)閙inted包依賴(lài)python,所以latex在編譯時(shí)需要調(diào)用外部程序python。latex覺(jué)得這種行為存在風(fēng)險(xiǎn),默認(rèn)禁止。
-shell-escape允許latex運(yùn)行"shell command",進(jìn)而允許調(diào)用python
另外,如果你想在org模式下用RefTex來(lái)引用文獻(xiàn),有一個(gè)插件'ox-bibtex',它可以在導(dǎo)出到Latex和HTML時(shí)自動(dòng)生成參考文獻(xiàn)附錄。'ox-bibtex'在org-contrib中。所以如果要啟用這個(gè)插件,請(qǐng)配合啟用org-beta后再加載這個(gè)插件。
用這個(gè)插件導(dǎo)出Latex時(shí),如果你遵照前面的配置,應(yīng)該一切正常。HTML導(dǎo)出功能需要用到bibtex2html。許多人在使用這項(xiàng)功能時(shí)都會(huì)遇到錯(cuò)誤Executing bibtex2html failed。參考
Emacs: unifying citations between html and latex in org-mode,問(wèn)題在于不能使用臨時(shí)文件。這個(gè)問(wèn)題最終也沒(méi)得到很好解決。下面我給出一個(gè)windows8.1+texlive 2014使用環(huán)境下的解決方案,不保證其他環(huán)境也適用。
bibtex2html
其實(shí)方案很簡(jiǎn)單,安裝最新版本的bibtex2html即可,目前是1.98。這里只是給不熟悉Unix開(kāi)發(fā)環(huán)境的同學(xué)們指?jìng)€(gè)路。
- 先去下載最新的開(kāi)發(fā)者版本bibtex2html-1.98.tar.gz,解壓到本地文件夾中,比如
bibtexdir - 運(yùn)行cygwin,
cd到bibtexdir - 鍵入
./configure,等待程序運(yùn)行完畢 - 鍵入
make,等待程序運(yùn)行完畢 - 如果你希望cygwin能在內(nèi)部調(diào)用bibtex2html,再鍵入
make install,這會(huì)把bibtex2html安裝到cygwin64所在路徑\usr\local\bin - 現(xiàn)在,
bibtexdir目錄下會(huì)出現(xiàn)'bib2bib.exe','bibtex2html.exe' ,'aux2bib' - 將三個(gè)文件拷貝到系統(tǒng)環(huán)境變量PATH中的某個(gè)路徑,確保你在cmd中鍵入
bibtex2html可以調(diào)用相關(guān).exe文件 - 大功告成
init-auctex.el
使用Sumatra PDF(請(qǐng)下載并安裝)來(lái)預(yù)覽PDF。最大的好處是,可以從PDF逆向定位TEX。即你編譯完.tex文檔并調(diào)用Sumatra PDF預(yù)覽時(shí),在PDF中雙擊某個(gè)位置,emacs會(huì)自動(dòng)打開(kāi)對(duì)應(yīng)的.tex文件并定位過(guò)去。
參考Sync Emacs AUCTeX with Sumatra PDF,在(load "auctex-autoloads")下面添加
;; run latex compiler with option -shell-escape
(setq LaTeX-command-style '(("" "%(PDF)%(latex) -shell-escape %S%(PDFout)")))
;; use Sumatra PDF to preview pdf
(setq TeX-source-correlate-mode t)
(setq TeX-source-correlate-method 'synctex)
(setq TeX-view-program-list
'(("Sumatra PDF" ("\"Sumatra安裝路徑/SumatraPDF.exe\" -reuse-instance"
(mode-io-correlate " -forward-search %b %n ") " %o"))))
請(qǐng)將Sumatra安裝路徑替換為你自己的安裝路徑。并打開(kāi)Sumatra的option界面,按照參考文章的回答設(shè)置Set inverse search command line。
其他配置
參考 Moving The Ctrl Key,綁定ctrl到capslock
我采用AutoHotkey的方式,并且將腳本放到startup文件夾來(lái)實(shí)現(xiàn)開(kāi)機(jī)自啟。我的電腦上,startup的路徑:
C:\Users\xiaohang\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
初入江湖
經(jīng)過(guò)以上配置,你的emacs應(yīng)該已經(jīng)比較好用了。不過(guò)在emacs世界里,此時(shí)的你還只是個(gè)初入江湖的小蝦米。在相當(dāng)?shù)囊欢螘r(shí)間內(nèi),你會(huì)糾結(jié)于emacs復(fù)雜的按鍵組合,為千方百計(jì)也不能安裝好一個(gè)小插件而抓狂。我想說(shuō),這都是正?,F(xiàn)象。在這些痛苦中,你慢慢成長(zhǎng),從讀官方文檔開(kāi)始,一點(diǎn)點(diǎn)熟悉elisp,開(kāi)始欣賞emacs的設(shè)計(jì),甚至能自己寫(xiě)一個(gè)小插件。于是,你使用emacs越來(lái)越順手,越來(lái)越想打造一個(gè)獨(dú)屬于自己的配置,最大化你在各個(gè)場(chǎng)景下的使用效率。
而我的教程到這里也要告一段落了。我已經(jīng)把自己所知悉數(shù)傳授給了你,從這里開(kāi)始,我們處在同一個(gè)起跑線上。但我想,這套教程并不會(huì)結(jié)束,因?yàn)槲疫€有很多承諾沒(méi)同你兌現(xiàn)呢,比如分析init.log,比如講解org模式。不過(guò),相信你經(jīng)過(guò)前面的學(xué)習(xí),已經(jīng)能靠依靠自己探索emacs中的大部分事物了。而我,也會(huì)逐漸積累自己的使用心得。
我計(jì)劃如下呈現(xiàn)后續(xù)的教程:圍繞一個(gè)具體的使用情景,我會(huì)向你描述我的插件選擇,配置和操作習(xí)慣。
最后,如果你覺(jué)得這篇文章不錯(cuò),請(qǐng)點(diǎn)擊下方的喜歡按鈕,謝謝支持!
好了,朋友們,下期再見(jiàn)~