GitHub Spacemacs Rocks 作者 zilongshanren 编者 li-xinyang, lsytj0413
在这一å£ä¸æˆ‘们计划用 21 天å¦ä¹ Emacs ä»¥åŠ Spacemacs 的使用。从基础安装开始到å¯ä»¥ è¿ç”¨åˆ°å·¥ä½œç”Ÿäº§çŽ¯èŠ‚ä¸ã€‚为了确ä¿å¦ä¹ è´¨é‡ï¼Œè¯·åŠ¡å¿…å®Œæˆå’Œç†è§£è®¡åˆ’ä¸çš„æ¯ä¸€é¡¹å¦ä¹ 任务。
视频地å€å¦‚下
说在最å‰é¢
å¦‚æžœä½ ç¬¬ä¸€æ¬¡å¬è¯´ Emacs ä½ å¯ä»¥åœ¨æ€§æ„Ÿçš„ Emacs(Emacs is Sexyï¼‰ä¸€æ–‡ä¸æ‰¾åˆ°ä½¿ç”¨å®ƒçš„ç† ç”±ï¼æˆ‘ç›¸ä¿¡ä½ ä¸€å®šä¼šè¢«å®ƒçš„å¼ºå¤§æ‰€å¸å¼•。
å¦‚æžœä½ è¿˜æ²¡æœ‰å®‰è£… Emacs å¯ä»¥åœ¨ Mac OS X å®‰è£…é“¾æŽ¥ä»¥åŠ Window 安装链接找到它。本文 我们使用的为 Emacs 25.0.x Pretest 版本,一些é…置在 Emacs 24 ä¸å¯èƒ½å¹¶ä¸é€‚用。
在开始本教程之å‰è¯·åŠ¡å¿…å…ˆå®Œæˆ Emacs æä¾›çš„å®˜æ–¹æ•™ç¨‹ï¼ˆå®Œæˆæ—¶é—´å¤§çº¦ 30 分钟),它å¯
以通过使用 C-h t
ï¼ˆåŒæ—¶æŒ‰ä½ Ctrl 与 h é”®ï¼ŒæŽ¥ç€æŒ‰ t é”® t
在这里代表 tutorial)
在 Emacs ä¸ç›´æŽ¥å°†å…¶æ‰“开。
Emacs Lisp 是 Emacs 所用的编程è¯è¨€ï¼Œä½ å¯ä»¥åœ¨é˜…读这篇教程(Learn X in Y Minutes) åŽå¾ˆå¿«åœ°äº†è§£å®ƒçš„基础用法。
å› ä¸º Control 键在 Emacs 䏿žä¸ºå¸¸ç”¨ï¼Œæ‰€ä»¥ä¸ºäº†æ›´æ–¹ä¾¿åœ°ä½¿ç”¨ Emacs 的键ä½ä¿®æ”¹ï¼Œéœ€è¦ 对其åšå‡ºä¿®æ”¹ã€‚建议将大写é”定键(Caps Lock)替æ¢ä¸º Control 键。这里是一个å¯ä»¥å‚考 的把大写é”定键替æ¢ä¸º Control 键的教程:移动 Control é”® (Moving The Ctrl Key)。如 果这个的教程ä¸é€‚ç”¨äºŽä½ çš„æ“作系统,请自行æœç´¢å…¶å®ƒçš„修改方å¼ã€‚
常è§ç¬¦å·æ‰€ä»£è¡¨çš„æ„ä¹‰å¦‚ä¸‹
- M(eta),在 Mac 下为 Option 键
- s(uper),在 Mac 环境下为左 Command 键
- S(Shift)
- C(trl)
å…‰æ ‡çš„ç§»åŠ¨æ˜¯ç¼–è¾‘å™¨ä¸æœ€å¸¸ç”¨çš„æ“ä½œæ‰€ä»¥å¿…é¡»ç†ŸçŸ¥ã€‚
C-f
为å‰ç§»ä¸€ä¸ªå—符,f
代表 forward。C-b
为åŽç§»ä¸€ä¸ªå—符,b
代表 backward。C-p
为上移至å‰ä¸€è¡Œï¼Œp
代表 previous。C-n
为上移至下一行,n
代表 next。C-a
为移至行首,a
代表 ahead。C-e
为移至行尾,e
代表 end。
常用的文件æ“作快æ·é”®ç»„åˆä¹Ÿå¿…须熟记。
C-x C-f
ä¸ºæ‰“å¼€ç›®æ ‡æ–‡ä»¶ï¼Œf
代表 find/fileC-x C-s
为ä¿å˜å½“å‰ç¼“冲区(Buffer),s
代表 save
C-x
是 Emacs 的快æ·é”®ä¸å¸¸ç”¨çš„å‰ç¼€å‘½ä»¤ã€‚这些å‰ç¼€å‘½ä»¤å¸¸å¸¸ä»£è¡¨äº†ä¸€ç³»åˆ—有关è”的指
令,å分é‡è¦ï¼Œè¯·ç‰¹åˆ«ç‰¢è®°ã€‚其它常è§çš„还有 C-c
, C-h
。打æ–组åˆé”®ä¸º C-g
,它
ç”¨äºŽç»ˆç«¯å–æ¶ˆä¹‹å‰çš„æŒ‡ä»¤ã€‚å¿«æ·é”®å°±æ˜¯ç”¨é¢„先绑定好的方å¼å‘Šè¯‰ Emacs 去执行指定的命令。
(之åŽä¼šä»‹ç»åˆ°æ›´å¤šæœ‰å…³ç»‘定的内容)
Emacs 功能强大,但是部分功能默认情况下并未开å¯ã€‚下é¢å°±æœ‰å‡ 个例å,
编辑器内显示行å·å¯ä½¿ç”¨ M-x linum-mode
æ¥å¼€å¯ã€‚
获å–帮助
Emacs 是一个富文档编辑器(Self document, extensible editor)而下é¢çš„ä¸‰ç§æ–¹æ³•åœ¨å¦ ä¹ Emacs 的过程ä¸ä¹Ÿéžå¸¸é‡è¦ã€‚他们分别是,
C-h k
寻找快æ·é”®çš„帮助信æ¯C-h v
寻找å˜é‡çš„帮助信æ¯C-h f
寻找函数的帮助信æ¯
请务必完æˆè¿™ç¯‡æ•™ç¨‹ï¼ˆLearn X in Y Minutes)æ¥äº†è§£ Elisp 的使用(阅读时间大约 15 åˆ†é’Ÿï¼‰ï¼Œä½ ä¹Ÿå¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°å®ƒçš„䏿–‡ç‰ˆã€‚Emacs Lisp 为一个函数å¼çš„è¯è¨€ï¼Œæ‰€ä»¥å®ƒå…¨éƒ¨ 功能都是由函数æ¥å®žçŽ°çš„ã€‚
下é¢ä¸ºä¸€äº›ç®€å•的例å
;; 2 + 2
(+ 2 2)
;; 2 + 3 * 4
(+ 2 (* 3 4))
;; 定义å˜é‡
(setq name "username")
(message name) ; -> "username"
;; 定义函数
(defun func ()
(message "Hello, %s" name))
;; 执行函数
(func) ; -> Hello, username
;; 设置快æ·é”®
(global-set-key (kbd "<f1>") 'func)
;; 使函数å¯ç›´æŽ¥è¢«è°ƒç”¨å¯æ·»åŠ (interactive)
(defun func ()
(interactive)
(message "Hello, %s" name))
Emacs çš„é…置文件默认ä¿å˜åœ¨ ~/.emacs.d/init.el
文件ä¸ã€‚(如果其ä¸å˜åœ¨å¯è‡ªè¡Œåˆ›å»ºï¼Œ
é…置文件也å¯ä¿å˜åœ¨ ~/.emacs
文件ä¸ï¼Œä»–们之间的区别我们会在åŽé¢åšè®¨è®ºï¼‰
**注æ„:** 如果希望把é…置放在 ~/.emacs.d/init.el
文件ä¸ï¼Œé‚£ä¹ˆéœ€è¦æ‰‹å·¥åˆ 除
~/.emacs
文件。
在开始é…置之å‰è®©æˆ‘们先æ¥åŒºåˆ« Emacs ä¸ Major Mode 与 Minor Mode 的区别。Major
Mode é€šå¸¸æ˜¯å®šä¹‰å¯¹äºŽä¸€ç§æ–‡ä»¶ç±»åž‹ç¼–è¾‘çš„æ ¸å¿ƒè§„åˆ™ï¼Œä¾‹å¦‚è¯æ³•高亮ã€ç¼©è¿›ã€å¿«æ·é”®ç»‘定ç‰ã€‚
而 Minor Mode 是除去 Major Mode 所æä¾›çš„æ ¸å¿ƒåŠŸèƒ½ä»¥å¤–çš„é¢å¤–编辑功能(辅助功能)。
例如在下é¢çš„é…ç½®æ–‡ä»¶ä¸ tool-bar-mode
与 linum-mode
ç‰å‡ä¸º Minor Mode*。
ç®€å•æ¥è¯´å°±æ˜¯ï¼Œä¸€ç§æ–‡ä»¶ç±»åž‹åŒæ—¶åªèƒ½å˜åœ¨ä¸€ç§ Major Mode 但是它å¯ä»¥åŒæ—¶æ¿€æ´»ä¸€ç§æˆ–多
ç§ Minor Modeã€‚å¦‚æžœä½ å¸Œæœ›çŸ¥é“当å‰çš„æ¨¡å¼ä¿¡æ¯ï¼Œå¯ä»¥ä½¿ç”¨ C-h m
æ¥æ˜¾ç¤ºå½“剿‰€æœ‰å¼€å¯
的全部 Minor Mode 的信æ¯ã€‚
简å•的编辑器自定义
䏋颿˜¯ä¸€äº›ç®€å•的编辑器é…置信æ¯ï¼Œä½ 需è¦åšçš„å°±æ˜¯å°†å…¶å†™å…¥ä½ çš„é…置文件ä¸
( ~/.emacs.d/init.el
)å³å¯ã€‚
;; å…³é—工具æ ,tool-bar-mode å³ä¸ºä¸€ä¸ª Minor Mode
(tool-bar-mode -1)
;; 关闿–‡ä»¶æ»‘动控件
(scroll-bar-mode -1)
;; 显示行å·
(global-linum-mode 1)
;; æ›´æ”¹å…‰æ ‡çš„æ ·å¼ï¼ˆä¸èƒ½ç”Ÿæ•ˆï¼Œè§£å†³æ–¹æ¡ˆè§ç¬¬äºŒé›†ï¼‰
(setq cursor-type 'bar)
;; å…³é—å¯åŠ¨å¸®åŠ©ç”»é¢
(setq inhibit-splash-screen 1)
;; å…³é—缩进 (第二天ä¸è¢«å޻除)
;; (electric-indent-mode -1)
;; 更改显示å—ä½“å¤§å° 16pt
;; http://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs
(set-face-attribute 'default nil :height 160)
;; 快速打开é…置文件
(defun open-init-file()
(interactive)
(find-file "~/.emacs.d/init.el"))
;; 这一行代ç ,将函数 open-init-file 绑定到 <f2> 键上
(global-set-key (kbd "<f2>") 'open-init-file)
åœ¨æ¯æ¬¡ç¼–辑é…置文件åŽï¼Œåˆšåˆšåšçš„修改并ä¸ä¼šç«‹åˆ»ç”Ÿæ•ˆã€‚è¿™æ—¶ä½ éœ€è¦é‡å¯ç¼–è¾‘å™¨æˆ–è€…é‡æ–°åŠ
è½½é…ç½®æ–‡ä»¶ã€‚é‡æ–°åŠ è½½é…ç½®æ–‡ä»¶ä½ éœ€è¦åœ¨å½“å‰é…置文件ä¸ä½¿ç”¨ M-x load-file
åŒå‡»ä¸¤æ¬¡
回车确认默认文件å,或者使用 M-x eval-buffer
去执行当å‰ç¼“冲区的所有 Lisp 命令。
ä½ ä¹Ÿå¯ä»¥ä½¿ç”¨ C-x C-e
æ¥æ‰§è¡ŒæŸä¸€è¡Œçš„ Lisp 代ç 。这些å¯ä½¿åˆšåˆšä¿®æ”¹çš„é…置文件生效。
å½“ç„¶ä½ ä¹Ÿå¯ä»¥å°†è¿™äº›å‡½æ•°ç»‘定为快æ·é”®ã€‚
使用默认的æ’件管ç†ç³»ç»Ÿï¼ˆå¯åœ¨èœå•æ Options > Manage Emacs Packages
䏿‰¾åˆ°ï¼‰å®‰
装 Company æ’件,他是一个用于代ç 补全的æ’件。它的åå—ä»£è¡¨è¡¥å…¨ä¸€åˆ‡çš„æ„æ€ï¼ˆ Comp
lete Any thingï¼‰ã€‚å› ä¸ºé»˜è®¤çš„æ’件管ç†ç³»ç»Ÿæä¾›çš„æ’ä»¶å分有é™ï¼Œæ‰€ä»¥æˆ‘们会在之åŽçš„
å‡ å¤©ä¸ç»§ç»å°†å…¶å¼ºåŒ–。
使用的下é¢çš„é…置将 Company-mode 在全局模å¼ä¸‹æ¿€æ´»
; å¼€å¯å…¨å±€ Company 补全
(global-company-mode 1)
简å•çš„ Org-mode 使用,它å¯ä»¥åˆ—出æçº²ï¼Œå¹¶æ–¹ä¾¿åœ°ä½¿ç”¨ tab
é”®æ¥å¯¹å…¶è¿›è¡Œå±•开与关é—。
C-c C-t
å¯ä»¥å°†ä¸€ä¸ªæ¡ç›®è½¬æ¢æˆä¸€æ¡å¾…办事件。
* ä¸ºä¸€çº§æ ‡é¢˜
** ä¸ºäºŒçº§æ ‡é¢˜
*** ä¸ºä¸‰çº§æ ‡é¢˜å¹¶ä»¥æ¤ç±»æŽ¨
视频地å€å¦‚下
说在最å‰é¢
å¦‚æžœä½ æƒ³æ·±å…¥å¦ä¹ Emacs Lisp å¯ä»¥é˜…读 GNU æä¾›çš„ An Introduction to Programming
in Emacs Lisp 。(也å¯ä»¥ M-x info
ç„¶åŽé€‰æ‹© Emacs Lisp Intro)
我们先解决å‰ä¸€å¤©ä¸é‡åˆ°çš„一些问题。首先是在对象是一个缓冲区局部å˜é‡ï¼ˆBuffer-local
variable)的时候,比如这里的 cursor-type
,我们需è¦åŒºåˆ† setq
与
setq-default
: setq
设置当å‰ç¼“冲区(Buffer)ä¸çš„å˜é‡å€¼ï¼Œ setq-default
设
置的为全局的å˜é‡çš„值(具体内容å¯ä»¥åœ¨ StackOverflow æ‰¾åˆ°ï¼‰ã€‚ä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å,用于
è®¾ç½®å…‰æ ‡æ ·å¼çš„æ–¹æ³•。
(setq-default cursor-type 'bar)
今天我们需è¦å°†ç¬¬ä¸€å¤©å…³é—的自动缩进 (electric-indent-mode
) 从é…置文件ä¸åŽ»é™¤ï¼Œå®ƒ
是 Emacs 24.4 ä¸åŠ å…¥çš„æ–°ç‰¹æ€§ï¼Œä½ å¯ä»¥åœ¨è¿™ç¯‡æ–‡ç« 䏿‰¾åˆ°æ›´å¤šå…³äºŽå®ƒçš„内容。我们之å‰å…³
é—å®ƒæ˜¯å› ä¸ºï¼Œå®ƒå˜åœ¨ä¸ç†æƒ³çš„缩进效果(在 Emacs Lisp ä¸ç”¨åˆ†å·åšæ³¨é‡Šæ—¶
fancy-comment
ä¼šé€ æˆå¾ˆè¿œçš„缩进,其实解决方法是使用 Emacs Lisp 推è的两个分å·è€Œ
䏿˜¯ä¸€ä¸ª ;;
ï¼Œè¿™æ ·å°±å¯ä»¥é¿å…这个问题。于是我们也就将其从é…置文件ä¸åˆ 除)
å› ä¸ºé€šå¸¸æˆ‘ä»¬çš„é…置文件以åŠé¡¹ç›®æ–‡ä»¶å‡ä½¿ç”¨ç‰ˆæœ¬æŽ§åˆ¶ç³»ç»Ÿï¼Œæ‰€ä»¥è‡ªåŠ¨ç”Ÿæˆçš„备份文件就显
得有些多余。我们还å¯ä»¥ç¦æ¢ Emacs 自动生æˆå¤‡ä»½æ–‡ä»¶ï¼Œä¾‹å¦‚ init.el~
。( ~
为åŽ
缀的文件为自动生æˆçš„备份文件)我们å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„æ–¹æ³•将其关é—。
(setq make-backup-files nil)
关于分å±çš„ä½¿ç”¨ï¼Œå¦‚æžœä½ å·²ç»è¯»è¿‡ Emacs è‡ªå¸¦çš„æ•™ç¨‹ï¼ŒçŽ°åœ¨ä½ åº”è¯¥å·²ç»æŽŒæ¡äº†åŸºæœ¬çš„åˆ†å± æ“作方法了。关于分å±çš„æ›´å¤šå†…å®¹ä½ å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
C-x 1
ä»…ä¿ç•™å½“å‰çª—å£C-x 2
将当å‰çª—å£åˆ†åˆ°ä¸Šè¾¹C-x 3
将当å‰çª—å£åˆ†åˆ°å³è¾¹
使用下é¢çš„é…ç½®æ¥åŠ å…¥æœ€è¿‘æ‰“å¼€è¿‡æ–‡ä»¶çš„é€‰é¡¹è®©æˆ‘ä»¬æ›´å¿«æ·çš„在图形界é¢çš„èœå•䏿‰“开最近 编辑过的文件。
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-menu-item 10)
;; 这个快æ·é”®ç»‘定å¯ä»¥ç”¨ä¹‹åŽçš„æ’ä»¶ counsel 代替
;; (global-set-key (kbd "C-x C-r") 'recentf-open-files)
require
çš„æ„æ€ä¸ºä»Žæ–‡ä»¶ä¸åŠ è½½ç‰¹æ€§ï¼Œä½ å¯ä»¥åœ¨æ€å“¥çš„网站读到关于 Emacs Lisp 库系统
çš„æ›´å¤šå†…å®¹ï¼Œæ–‡ç« åœ¨è¿™é‡Œã€‚
使用下é¢çš„é…ç½®æ–‡ä»¶å°†åˆ é™¤åŠŸèƒ½é…ç½®æˆä¸Žå…¶ä»–图形界é¢çš„编辑器相åŒï¼Œå³å½“ä½ é€‰ä¸ä¸€æ®µæ–‡å— 之åŽè¾“入一个å—ç¬¦ä¼šæ›¿æ¢æŽ‰ä½ é€‰ä¸éƒ¨åˆ†çš„æ–‡å—。
(delete-selection-mode 1)
下é¢çš„这些函数å¯ä»¥è®©ä½ 找到ä¸åŒå‡½æ•°ï¼Œå˜é‡ä»¥åŠå¿«æ·é”®æ‰€å®šä¹‰çš„æ–‡ä»¶ä½ç½®ã€‚å› ä¸ºéžå¸¸å¸¸ç”¨ 所以我们建议将其设置为与查找文档类似的快æ·é”®ï¼ˆå¦‚下所示),
find-function
(C-h C-f
)find-variable
(C-h C-v
)find-function-on-key
(C-h C-k
)
在我们进入下一个部分之间让我们æ¥çœ‹çœ‹ä½¿ç”¨ ~/.emacs.d/init.el
与 ~/.emacs
的区
别(更多关于他们区别的讨论å¯åœ¨è¿™é‡Œæ‰¾åˆ°ï¼‰ã€‚ç®€å•æ¥è¯´è¯·ä½¿ç”¨å‰è€…ï¼Œå› ä¸ºå®ƒæœ‰ä¸‹é¢çš„两个
优点,
- 它å¯ä»¥æ›´å¥½å°†æ‰€æœ‰ Emacs 相关的文件整åˆåœ¨ä¸€ä¸ªç›®å½•内(干净的
HOME
,网盘备份ç‰ä¼˜ç‚¹ï¼‰ - 更好的版本控制
é…ç½®æ’ä»¶æº
åœ¨è¿›è¡Œç¾ŽåŒ–ä¹‹å‰æˆ‘们需è¦é…ç½®æ’ä»¶çš„æºï¼ˆé»˜è®¤çš„æºéžå¸¸æœ‰é™ï¼‰ï¼Œæœ€å¸¸ä½¿ç”¨çš„æ˜¯ MELPA
(Milkypostman’s Emacs Lisp Package Archive)。它有éžå¸¸å¤šçš„æ’ä»¶ï¼ˆ3000 多个æ’件)。
一个æ’件下载的次数多并ä¸èƒ½è¯´æ˜Žå®ƒéžå¸¸æœ‰ç”¨ï¼Œä¹Ÿè®¸è¿™ä¸ªæ’件是其他的æ’ä»¶çš„ä¾èµ–。在这里
ä½ å¯ä»¥æ‰¾åˆ°å…¶å®‰è£…ä½¿ç”¨æ–¹æ³•ã€‚æ·»åŠ æºåŽï¼Œæˆ‘们就å¯ä»¥ä½¿ç”¨ M-x package-list-packages
æ¥æŸ¥çœ‹æ‰€æœ‰ MELPA 上的æ’件了。在表å•ä¸å¯ä»¥ä½¿ç”¨ I
æ¥æ ‡è®°å®‰è£… D
æ¥æ ‡è®°åˆ 除,
U
æ¥æ›´æ–°ï¼Œå¹¶ç”¨ X
æ¥ç¡®è®¤ã€‚
ä½ å¯ä»¥ç›´æŽ¥å°†ä¸‹é¢çš„代ç å¤åˆ¶åˆ°ä½ çš„é…置文件顶端,从而直接使用 Melpa 作为æ’ä»¶çš„æºã€‚
ä½ å¯ä»¥å°†ä½ 需è¦çš„æ’ä»¶åå—写在 my/packages
ä¸ï¼ŒEmacs 在å¯åŠ¨æ—¶ä¼šè‡ªåŠ¨ä¸‹è½½æœªè¢«å®‰è£…
çš„æ’件。
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(setq package-archives '(("gnu" . "http://elpa.emacs-china.org/gnu/")
("melpa" . "http://elpa.emacs-china.org/melpa/"))))
;; æ³¨æ„ elpa.emacs-china.org 是 Emacs China 䏿–‡ç¤¾åŒºåœ¨å›½å†…æå»ºçš„一个 ELPA 镜åƒ
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
hungry-delete
swiper
counsel
smartparens
;; --- Major Mode ---
js2-mode
;; --- Minor Mode ---
nodejs-repl
exec-path-from-shell
;; --- Themes ---
monokai-theme
;; solarized-theme
) "Default packages")
(setq package-selected-packages my/packages)
(defun my/packages-installed-p ()
(loop for pkg in my/packages
when (not (package-installed-p pkg)) do (return nil)
finally (return t)))
(unless (my/packages-installed-p)
(message "%s" "Refreshing package database...")
(package-refresh-contents)
(dolist (pkg my/packages)
(when (not (package-installed-p pkg))
(package-install pkg))))
;; Find Executable Path on OS X
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
关于上é¢è¿™æ®µé…ç½®ä»£ç æœ‰å‡ 个知识点,首先就是这段é…置文件ä¸ç”¨åˆ°äº† loop for ... in
,它æ¥è‡ª cl
å³ Common Lisp 扩展。 for
, in
, collect
å‡ä¸º cl-loop
ä¸çš„
ä¿ç•™å…³é”®å—ã€‚ä¸‹é¢æ˜¯ä¸€äº›ç®€å•çš„ cl-loop
的使用示例:
;; é历æ¯ä¸€ä¸ªç¼“冲区(Buffer)
(cl-loop for buf in (buffer-list)
collect (buffer-file-name buf))
;; 寻找 729 çš„å¹³æ–¹æ ¹ï¼ˆè®¾ç½®æœ€å¤§ä¸º 100 ä¸ºäº†é˜²æ¢æ— é™å¾ªçŽ¯ï¼‰
(cl-loop for x from 1 to 100
for y = (* x x)
until (>= y 729)
finally return (list x (= y 729)))
ä½ å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°æ›´å¤šå…³äºŽå¾ªçŽ¯çš„ä½¿ç”¨è¯´æ˜Žã€‚
其次就是它使用到了 quote
, 它其实就是我们之å‰å¸¸å¸¸è§åˆ°çš„ '
(å•引å·ï¼‰çš„完全体。
å› ä¸ºå®ƒåœ¨ Lisp ä¸å分常用,所以就æä¾›äº†ç®€å†™çš„æ–¹æ³•。
;; 下é¢ä¸¤è¡Œçš„æ•ˆæžœå®Œå…¨ç›¸åŒçš„
(quote foo)
'foo
quote
çš„æ„æ€æ˜¯ä¸è¦æ‰§è¡ŒåŽé¢çš„内容,返回它原本的内容(具体请å‚考下é¢çš„例å)
(print '(+ 1 1)) ;; -> (+ 1 1)
(print (+ 1 1)) ;; -> 2
更多关于 quote
的内容å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ï¼Œæˆ–者在这里找到 StackOverflow 上对于它的讨论。
è¿™æ ·æˆ‘ä»¬å°±å¯ä»¥åŒºåˆ†ä¸‹é¢ä¸‰è¡Œä»£ç 的区别,
;; 第一ç§
(setq package-selected-packages my/packages)
;; 第二ç§
(setq package-selected-packages 'my/packages)
;; 第三ç§
(setq package-selected-packages (quote my/packages))
第一ç§è®¾ç½®æ˜¯åœ¨ç¼“冲区ä¸è®¾ç½®ä¸€ä¸ªå为 package-selected-packages
çš„å˜é‡ï¼Œå°†å…¶çš„值
设定为 my/packages
å˜é‡çš„值。第二ç§å’Œç¬¬ä¸‰ç§å…¶å®žæ˜¯å®Œå…¨ç›¸åŒçš„,将一个å为
package-selected-packages
çš„å˜é‡è®¾ç½®ä¸º my/packages
。
我们å¯ä»¥ç”¨ä¸‹é¢ä»£ç å°† Emacs 设置为开å¯é»˜è®¤å…¨å±ï¼Œ
(setq initial-frame-alist (quote ((fullscreen . maximized))))
我们也å¯ä»¥å¯ç”¨è‡ªåŠ¨æ‹¬å·åŒ¹é…(Highlight Matching Parenthesis),éšåŽä¼šä»‹ç»æ’ä»¶æ¥å¢ž 强这个匹é…çš„åŠŸèƒ½ã€‚ä½ å¯ä»¥å F438 œ¨è¿™é‡Œè¯»åˆ°å…³äºŽé’©å的更多信æ¯ã€‚
(add-hook 'emacs-lisp-mode-hook 'show-paren-mode)
高亮当å‰è¡Œï¼Œå½“文本内容很多时å¯ä»¥å¾ˆå®¹æ˜“æ‰¾åˆ°å…‰æ ‡çš„ä½ç½®ã€‚
(global-hl-line-mode 1)
安装主题
(add-to-list 'my/packages 'monokai-theme)
ç„¶åŽä½¿ç”¨ä¸‹é¢çš„é…ç½®ä½¿å…¶æ¯æ¬¡æ‰“å¼€ç¼–è¾‘å™¨æ—¶åŠ è½½ä¸»é¢˜ï¼Œ
(load-theme 'monokai 1)
æŽ¨èæ’ä»¶
- company
- hungry-delete
- Smex (å¦‚æžœä½ ä½¿ç”¨ Counsel æ¥å¢žå¼ºä½ çš„
M-x
,那么就ä¸éœ€è¦å†å®‰è£… Smex 了) - Swiper & Counsel
- smartparens
使用 M-x customize-group
åŽé€‰æ‹©å¯¹åº”çš„æ’ä»¶å称,å¯ä»¥è¿›å…¥å¯è§†åŒ–选项区对指定的æ’
ä»¶åšè‡ªå®šä¹‰è®¾ç½®ã€‚当选择 Save for future session åŽï¼Œåˆšåˆšåšçš„设计就会被ä¿å˜åœ¨ä½ çš„
é…置文件( init.el
)ä¸ã€‚关于å„个æ’件的安装与使用方法通常都å¯ä»¥åœ¨å…¶å®˜æ–¹é¡µé¢æ‰¾
到(GitHub Pages 或者是项目仓库ä¸çš„ README 文件)。我们强烈建议大家在安装这些æ’
ä»¶åŽé˜…è¯»ä½¿ç”¨æ–¹æ³•æ¥æ›´å¥½çš„å°†å®ƒä»¬ä½¿ç”¨åˆ°ä½ çš„æ—¥å¸¸å·¥ä½œå½“ä¸ä½¿æ•ˆçŽ‡æœ€å¤§åŒ–ã€‚
Emacs æä¾›çš„默认 JavaScript Major Mode 并䏿˜¯éžå¸¸å¥½ç”¨ã€‚所以我们å¯ä»¥å°†é»˜è®¤çš„æ¨¡å¼ æ›¿æ¢æˆ js2-mode 一个比默认模å¼å¥½ç”¨çš„ Major Mode。我们å¯ä»¥é€šè¿‡ MELPA æ¥ä¸‹è½½å®ƒï¼Œç„¶ åŽç”¨ä¸‹é¢çš„代ç 将其å¯ç”¨ã€‚
(setq auto-mode-alist
(append
'(("\\.js\\'" . js2-mode))
auto-mode-alist))
ä½ å¯ä»¥åœ¨è¿™é‡Œï¼ˆHow Emacs Chooses a Major Mode)找到 Emacs 是如何选择何时该选用何 ç§ Major Mode 的方法。
在这里我们需è¦çŸ¥é“ auto-mode-alist
的作用,这个å˜é‡æ˜¯ä¸€ä¸ª AssociationList,它
使用æ£åˆ™è¡¨è¾¾å¼ï¼ˆREGEXP)的规则æ¥åŒ¹é…ä¸åŒç±»åž‹æ–‡ä»¶åº”使用的 Major Mode。 䏋颿˜¯å‡ 个
æ£åˆ™è¡¨è¾¾å¼åŒ¹é…的例å,
(("\\`/tmp/fol/" . text-mode)
("\\.texinfo\\'" . texinfo-mode)
("\\.texi\\'" . texinfo-mode)
("\\.el\\'" . emacs-lisp-mode)
("\\.c\\'" . c-mode)
("\\.h\\'" . c-mode)
…)
䏋颿˜¯å¦‚ä½•æ·»åŠ æ–°çš„æ¨¡å¼ä¸Žå¯¹åº”文件类型的例å(与我们é…ç½® js2-mode
时相似的例å),
(setq auto-mode-alist
(append
;; File name (within directory) starts with a dot.
'(("/\\.[^/]*\\'" . fundamental-mode)
;; File name has no dot.
("/[^\\./]*\\'" . fundamental-mode)
;; File name ends in ‘.C’.
("\\.C\\'" . c++-mode))
auto-mode-alist))
在 js2-mode
模å¼ä¸ä¼šæä¾›
- è¯æ³•高亮
- è¯æ³•检查器(Linter)
执行缓冲区的代ç å¯ä»¥ä½¿ç”¨ nodejs-repl
æ’件,它需è¦ä½ 的机器上已ç»å®‰è£…了 NodeJS。
然而在 Mac OS X 上å¯èƒ½ä¼šå‡ºçŽ°æ‰¾ä¸åˆ° NodeJS 坿‰§è¡Œæ–‡ä»¶çš„问题,è¦è§£å†³è¿™ä¸ªé—®é¢˜ä½ 需è¦
安装å¦å¤–一个 exec-path-from-shell
çš„æ’件并将其å¯ç”¨ã€‚
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
有了 nodejs-repl
我们就å¯ä»¥æ–¹ä¾¿çš„æµ‹è¯•å’Œå¼€å‘æˆ‘们的 JavaScript 代ç äº†ï¼ˆä½ å¯ä»¥åœ¨
这里找到更多关于它的使用方法)。
在 Org-mode ä¸ä½ å¯ä»¥ç›´æŽ¥å¼€å¯æ–°çš„缓冲区(Buffer)直接用相应的 Major Mode æ¥ç¼–辑代
ç å—内的内容。在代ç å—ä¸ä½¿ç”¨ C-c '
会直接打开对应模å¼çš„缓冲区(ä¸ä»…é™äºŽ Lisp)。
è¿™æ ·å°±ä½¿åœ¨ Org-mode ä¸ç¼–辑代ç å˜çš„å分方便快æ·ã€‚
使用 <s
ç„¶åŽ Tab å¯ä»¥ç›´æŽ¥æ’入代ç å—的代ç 片段(Snippet),更多类似的代ç 片段
(Org-mode Easy Templates)å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
#+BEGIN_SRC emacs-lisp ;; Your code goes here ;; ä½ çš„ä»£ç 写在这里 #+END_SRC
æ·»åŠ Org-mode æ–‡æœ¬å†…è¯æ³•高亮
(require 'org)
(setq org-src-fontify-natively t)
在 Org-mode ä¸é‡ç½®æœ‰åºåˆ—表åºå·å¯ä»¥ç›´æŽ¥ä½¿ç”¨ M-<RET> 。
Agenda 的使用
;; 设置默认 Org Agenda 文件目录
(setq org-agenda-files '("~/org"))
;; 设置 org-agenda 打开快æ·é”®
(global-set-key (kbd "C-c a") 'org-agenda)
ä½ åªéœ€å°†ä½ çš„ *.org
æ–‡ä»¶æ”¾å…¥ä¸Šé¢æ‰€æŒ‡å®šçš„æ–‡ä»¶å¤¹ä¸å°±å¯ä»¥å¼€å§‹ä½¿ç”¨ Agenda
模å¼äº†ã€‚
C-c C-s
选择想è¦å¼€å§‹çš„æ—¶é—´C-c C-d
选择想è¦ç»“æŸçš„æ—¶é—´C-c a
å¯ä»¥æ‰“å¼€ Agenda 模å¼èœå•并选择ä¸åŒçš„å¯è§†æ–¹å¼ï¼ˆr
)
视频地å€å¦‚下
å°†ä¸åŒçš„é…ç½®ä»£ç æ”¾ç½®åˆ°ä¸åŒçš„æ–‡ä»¶ä¸ï¼Œä½¿å…¶æ¨¡å—化,这让我们的åŽç»ç»´æŠ¤å˜å¾—æ›´åŠ ç®€å•。
䏋颿˜¯æˆ‘们现在的 ~/.emacs.d/
目录ä¸çš„æ ·å,
├── auto-save-list # 自动生æˆçš„ä¿å˜æ•°æ® ├── elpa # 下载的æ’件目录 ├── init.el # 我们的é…置文件 └── recentf # 最近访问的文件列表
通常我们åªä¿å˜é…置文件和对其进行版本控制,其他的æ’ä»¶å‡ä¸ºåœ¨ç¬¬ä¸€æ¬¡ä½¿ç”¨ç¼–辑器时å†é€š è¿‡ç½‘ç»œé‡æ–°ä¸‹è½½ï¼Œå½“ç„¶ä½ ä¹Ÿå¯ä»¥é€‰æ‹©å°†å…¨éƒ¨é…置文件进行版本控制æ¥ä¿è¯è‡ªå·±æ—¶åˆ»æ‹¥æœ‰æœ€ç¨³ 定的生产环境。
Elisp ä¸å¹¶æ²¡æœ‰å‘½å空间(Namespace),æ¢å¥è¯è¯´å°±æ˜¯æ‰€æœ‰çš„å˜é‡å‡ä¸ºå…¨å±€å˜é‡ï¼Œæ‰€ä»¥å…¶ 命忖¹æ³•å°±å˜çš„éžå¸¸é‡è¦ã€‚䏋颿˜¯ä¸€ä¸ªç®€å•的命å规则,
#自定义å˜é‡å¯ä»¥ä½¿ç”¨è‡ªå·±çš„åå—ä½œä¸ºå‘½åæ–¹å¼ï¼ˆå¯ä»¥æ˜¯å˜é‡å或者函数å) my/XXXX #模å¼å‘½å规则 ModeName-mode #模å¼å†…çš„å˜é‡åˆ™å¯ä»¥ä½¿ç”¨ ModeName-VariableName
éµå®ˆä¸Šé¢çš„命å规则å¯ä»¥æœ€å¤§ç¨‹åº¦çš„å‡å°‘命å冲çªå‘生的å¯èƒ½æ€§ã€‚
现在我们想将原本混åˆåœ¨ä¸€èµ·çš„é…置文件分为下é¢çš„å‡ ä¸ªæ¨¡å—(æ¯ä¸€ä¸ªæ¨¡å—ä¸ºä¸€ä¸ªç‹¬ç«‹çš„é… ç½®æ–‡ä»¶å¹¶å°†å…¶ä¿å˜åœ¨æŒ‡å®šçš„å目录ä¸ï¼‰ï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯
init-packages.el # æ’ä»¶ç®¡ç† init-ui.el # 视觉层é…ç½® init-better-defaults.el # 增强内置功能 init-keybindings.el # å¿«æ·é”®ç»‘定 init-org.el # Org 模å¼ç›¸å…³çš„全部设定 custome.el # å˜æ”¾ä½¿ç”¨ç¼–辑器接å£äº§ç”Ÿçš„é…置信æ¯
下é¢ä¸ºå°†é…置文件进行模å—化åŽçš„目录结构,
├── init.el └── lisp ├── custom.el ├── init-better-defaults.el ├── init-helper.el ├── init-keybindings.el ├── init-packages.el ├── init-ui.el └── init-org.el
使用模å—化é…置就å¯ä»¥è®©æˆ‘们在之åŽçš„é…ç½®ä¸è¿…速的定ä½ä¸Žæ›´æ”¹é…置内容,让整个过程å˜å¾— 更有æ¡ç†ä¹Ÿæ›´åŠ é«˜æ•ˆã€‚
和之å‰ä¸€æ · init.el
是é…置文件的入å£ï¼ŒçŽ°åœ¨å®ƒä¾¿æˆä¸ºäº†æ‰€æœ‰æ¨¡å—é…置文件的入å£ï¼Œæ‰€
以è¦ä½¿ç”¨è¿™äº›æ¨¡å—时,我们需è¦åœ¨å…¶ä¸å¼•用需è¦åŠ è½½çš„æ¨¡å—。下é¢ä»¥ init-packages.el
(æ¤é…ç½®ä¸ºæ·»åŠ æ’件的模å—) 为例,详细说明如何模å—化以åŠåº”用的方法。
䏋颿˜¯åœ¨æ¨¡å—化é…置之å‰ï¼Œæˆ‘们所使用的é…置文件 ~/.emacs.d/init.el
çš„æ ·å,我们将
所有的é…置代ç 都放置在了åŒä¸€ä¸ªæ–‡ä»¶ä¸ï¼ˆå¦‚下所示)
下é¢ä¸º ~/.emacs.d/init.el
文件的内容
;; __ __ __ ___
;; |__) /\ / ` |__/ /\ / _` |__
;; | /~~\ \__, | \ /~~\ \__> |___
;; __ ___ ___ ___
;; |\/| /\ |\ | /\ / _` |__ |\/| |__ |\ | |
;; | | /~~\ | \| /~~\ \__> |___ | | |___ | \| |
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(setq package-archives '(("gnu" . "http://elpa.emacs-china.org/gnu/")
("melpa" . "http://elpa.emacs-china.org/melpa/"))))
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
smooth-scrolling
hungry-delete
swiper
counsel
smartparens
;; --- Major Mode ---
js2-mode
markdown-mode
;; --- Minor Mode ---
;; Quick Note Taking
deft
;; JavaScript REPL
nodejs-repl
;; Find OS X Executable Helper Package
;; ...
之å‰ä¸ºäº†æ›´å¥½çš„区分ä¸åŒçš„区域我使用的方法是使用 ASCII Art ç„¶åŽå†ä»¥å…³é”®å—æ¥åšæœç´¢
è·³è½¬ï¼Œä½†æ˜¯è¿™æ ·å†ç¼–辑工程ä¸ä¾æ—§å分缓慢和麻烦。于是我们现在è¦å°†é…置文件全部模å—化,
把ä¸åŒéƒ¨åˆ†çš„é…ç½®ä»£ç æ”¾ç½®åœ¨ä¸åŒçš„é…置文件ä¸ï¼Œå¹¶åœ¨å…¥å£æ–‡ä»¶ï¼ˆ ~/.emacs.d/init.el
)ä¸ä¾æ¬¡å¼•用ä¸ç”¨çš„æ¨¡å—。
下é¢ä¸º ~/.emacs.d/lisp/init-packages.el
模å—ä¸çš„代ç
;; __ __ __ ___
;; |__) /\ / ` |__/ /\ / _` |__
;; | /~~\ \__, | \ /~~\ \__> |___
;; __ ___ ___ ___
;; |\/| /\ |\ | /\ / _` |__ |\/| |__ |\ | |
;; | | /~~\ | \| /~~\ \__> |___ | | |___ | \| |
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(setq package-archives '(("gnu" . "http://elpa.emacs-china.org/gnu/")
("melpa" . "http://elpa.emacs-china.org/melpa/"))))
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
smooth-scrolling
hungry-delete
swiper
counsel
smartparens
popwin
;; --- Major Mode ---
js2-mode
markdown-mode
;; ...
;; 文件末尾
(provide 'init-packages)
下é¢ä¸º ~/.emacs.d/init.el
入壿–‡ä»¶ä¸çš„代ç
(package-initialize)
(add-to-list 'load-path "~/.emacs.d/lisp/")
;; Package Management
;; -----------------------------------------------------------------
(require 'init-packages)
模å—化è¦åšçš„其实éžå¸¸ç®€å•,我们è¦åšçš„其实就是把æŸä¸€ä¸ªæ›´æ”¹ç¼–辑器æŸå®šéƒ¨åˆ†ï¼ˆä¾‹å¦‚,æ’
件管ç†ï¼Œæ˜¾ç¤ºå±‚,快æ·é”®ç»‘定ç‰ï¼‰çš„é…置代ç 写入一个独立的文件ä¸å¹¶åœ¨æœ«å°¾ä¸ºå…¶æ·»åŠ
(provide 'modul-name)
(这里我们的模å—å为 init-packages
)使其å¯ä»¥åœ¨å…¥å£æ–‡ä»¶
ä¸è¢«è°ƒç”¨ï¼Œç„¶åŽå†åœ¨å…¥å£æ–‡ä»¶ä¸å°†å…¶å¼•用既å¯ã€‚
è¿™é‡Œéœ€è¦æ³¨æ„的是,我们需è¦åœ¨å…¥å£æ–‡ä»¶ä¸æ·»åŠ (add-to-list 'load-path
"~/.emacs.d/lisp/")
è¿™å¯ä»¥è®© Emacs 找到需è¦åŠ è½½çš„æ¨¡å—æ‰€å¤„çš„ä½ç½®ã€‚
更多模å—化的é…置文件å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
åœ¨è¿™ä¸€èŠ‚æˆ‘ä»¬å°†è¯¦ç»†ä»‹ç» Major Mode 与 Minor Mode 去区别。æ¯ä¸€ä¸ªæ–‡ä»¶ç±»åž‹éƒ½å¯¹åº”一个
Major Mode,它æä¾›è¯æ³•高亮以åŠç¼©è¿›ç‰åŸºæœ¬çš„编辑支æŒåŠŸèƒ½ï¼Œç„¶åŽè€Œ Minor Mode 则æä¾›
其余的增强性的功能(例如 linum-mode
)。
在 Emacs ä¸ï¼ŒMajor Mode åˆåˆ†ä¸ºä¸‰ç§ï¼Œ
text-mode
,用于编辑文本文件special-mode
,特殊模å¼ï¼ˆå¾ˆå°‘è§ï¼‰prog-mode
,所有的编程è¯è¨€çš„父模å¼
在æ¯ä¸€ä¸ªæ¨¡å¼ï¼ˆmode)ä¸å®ƒçš„å称与å„个å˜é‡è¿˜æœ‰å‡½æ•°éƒ½æ˜¯æœ‰ç‰¹å®šçš„命å规则,比如所有的
模å¼éƒ½è¢«å‘½å为 ModeName-mode
ï¼Œé‡Œé¢æ‰€è®¾ç½®çš„å¿«æ·é”®åˆ™ä¸º ModeName-mode-key-map
,而所有的钩å则会被命å为 ModeName-mode-hook
。
æ³¨æ˜Žï¼šä¸ºäº†ä¿æŒé˜…读的完整性,部分第三天的关于默认编辑器优化的内容被移至第四天。
视频地å€å¦‚下
在这一部分我们首先需è¦çŸ¥é“的是什么是 features
。在 Emacs 䏿¯ä¸€ä¸ª feature
都
是一个 Elisp 符å·ï¼Œç”¨äºŽä»£è¡¨ä¸€ä¸ª Lisp æ’件(Package)。
当一个æ’件调用 (provide 'symbol_name)
函数时,Emacs 就会将这个符å·åŠ å…¥åˆ°
features
的列表ä¸åŽ»ã€‚ä½ å¯ä»¥åœ¨è¿™é‡Œè¯»åˆ°æ›´å¤šå…³äºŽ feature 的内容。
æŽ¥ç€æˆ‘们需è¦å¼„明白的是 load-file
, load
, require
, autoload
之间的区别。
(他们之间区别的链接已ç»å†å‰é¢è´´è¿‡äº†ï¼Œä½ 也å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ä¹‹å‰åŒæ ·çš„链接)
ç®€å•æ¥è¯´ï¼Œ load-file
用于打开æŸä¸€ä¸ªæŒ‡å®šçš„æ–‡ä»¶ï¼Œç”¨äºŽå½“ä½ ä¸æƒ³è®© Emacs æ¥åŽ»å†³å®šåŠ
è½½æŸä¸ªé…置文件时( .el
或者 .elc
文件)。
load
æœç´¢ load-path
ä¸çš„è·¯å¾„å¹¶æ‰“å¼€ç¬¬ä¸€ä¸ªæ‰€æ‰¾åˆ°çš„åŒ¹é…æ–‡ä»¶åçš„æ–‡ä»¶ã€‚æ¤æ–¹æ³•用于
ä½ é¢„å…ˆä¸çŸ¥é“文件路径的时候。
require
åŠ è½½è¿˜æœªè¢«åŠ è½½çš„æ’件。首先它会查看å˜é‡ features
䏿˜¯å¦å˜åœ¨æ‰€è¦åŠ è½½çš„
符å·å¦‚æžœä¸å˜åœ¨åˆ™ä½¿ç”¨ä¸Šé¢æåˆ°çš„ load
将其载入。(有点类似于其他编程è¯è¨€ä¸çš„
import
)
autoload
ç”¨äºŽä»…åœ¨å‡½æ•°è°ƒç”¨æ—¶åŠ è½½æ–‡ä»¶ï¼Œä½¿ç”¨æ¤æ–¹æ³•å¯ä»¥å¤§å¤§èŠ‚çœç¼–辑器的å¯åŠ¨æ—¶é—´ã€‚
在这一节我们会é…ç½®æˆ‘ä»¬çš„ç¼–è¾‘å™¨ä½¿å…¶æœ‰æ›´å¥½çš„ä½¿ç”¨ä½“éªŒã€‚æ•´ä¸ªè¿‡ç¨‹å°±å¦‚åŒæç§¯æœ¨ä¸€èˆ¬ï¼Œå°† æ›´å¥½çš„ä½“éªŒå»ºç«‹åœ¨å·²æœ‰çš„åŠŸèƒ½åŸºç¡€ä¹‹ä¸Šã€‚è¿™æ ·çš„ä¼˜åŒ–ä½¿æ•´ä¸ªè¿‡ç¨‹å˜å¾—更高效,也更有趣。
下é¢çš„代ç å¯ä»¥æ˜¯ Emacs è‡ªåŠ¨åŠ è½½å¤–éƒ¨ä¿®æ”¹è¿‡çš„æ–‡ä»¶ã€‚
(global-auto-revert-mode 1)
使用下é¢çš„代ç å¯ä»¥å…³é—自己生产的ä¿å˜æ–‡ä»¶ï¼ˆä¹‹å‰æˆ‘们已ç»å…³é—过了 Emacs 自动生产的 备份文件了,现在是关é—自动ä¿å˜æ–‡ä»¶ï¼‰ã€‚
(setq auto-save-default nil)
å¦‚æžœä½ å‘çŽ°ä½ åœ¨ä½¿ç”¨ä¸å‘çŽ°äº†é‚£äº›ç¼–è¾‘è¡Œä¸ºä¸Žä½ é¢„æœŸçš„ä¸ç›¸ç¬¦æ—¶ï¼Œä½ å¯ä»¥é€šè¿‡æœç´¢å¼•擎去寻 找解决方案然åŽå°†å…¶åŠ å…¥ä½ çš„é…ç½®ä¸å¹¶æ‰“é€ ä¸€ä¸ªçœŸæ£å±žäºŽä½ 的神器ï¼
popwin
æ’ä»¶å¯ä»¥è‡ªåŠ¨å°†å…‰æ ‡ç§»åŠ¨åˆ°ï¼Œæ–°åˆ›å»ºçš„çª—å£ä¸ã€‚使用下é¢çš„代ç 将其å¯ç”¨ï¼Œ
(require 'popwin)
(popwin-mode 1)
ä¹Ÿè®¸ä½ å¹¶ä¸å–œæ¬¢å¬åˆ°é”™è¯¯æ—¶çš„“哔哔â€çš„è¦å‘Šæç¤ºéŸ³ï¼Œä½¿ç”¨ä¸‹é¢çš„代ç ä½ å¯ä»¥å…³é— Emacs ä¸çš„è¦å‘ŠéŸ³ï¼Œ
(setq ring-bell-function 'ignore)
æ¯ä¸€æ¬¡å½“ Emacs 需è¦ä¸Žä½ 确认æŸä¸ªå‘½ä»¤æ—¶éœ€è¦è¾“å…¥ (yes or no)
比较麻烦,所有我们å¯
以使用下é¢çš„代ç ,设置一个别å将其简化为åªè¾“å…¥ (y or n)
。
(fset 'yes-or-no-p 'y-or-n-p)
indent-region
å¯ä»¥å¸®æˆ‘们釿–°ç¼©è¿›æ‰€é€‰åŒºåŸŸçš„代ç ,但是æ¯ä¸€æ¬¡éƒ½é€‰ä¸å分麻烦。使用
下é¢çš„代ç å¯ä»¥ä¸€æ¬¡é‡æ–°ç¼©è¿›å…¨éƒ¨ç¼“冲区的代ç 。(之åŽä¹Ÿä¼šä»‹ç»æ›´å¥½ç”¨çš„ï¼Œä»£ç æ ¼å¼ç¾ŽåŒ–
çš„æ’件)
(defun indent-buffer()
(interactive)
(indent-region (point-min) (point-max)))
(defun indent-region-or-buffer()
(interactive)
(save-excursion
(if (region-active-p)
(progn
(indent-region (region-beginning) (region-end))
(message "Indent selected region."))
(progn
(indent-buffer)
(message "Indent buffer.")))))
ç„¶åŽå†å°†å…¶ç”¨ä¸‹é¢çš„代ç 将其绑定为快æ·é”®ï¼Œç¬¬ä¸€ä¸ª \
用于将紧跟的 \
进行逃脱(escape)。
(global-set-key (kbd "C-M-\\") 'indent-region-or-buffer)
使用下é¢çš„ä»£ç æˆ‘们å¯ä»¥å¼€å¯ abbrev
模å¼å¹¶å®šä¹‰ä¸€ä¸ªç¼©å†™è¡¨ï¼Œæ¯å½“我们输入下é¢çš„缩写
å¹¶ä»¥ç©ºæ ¼ç»“æŸæ—¶ï¼ŒEmacs 就会将其自动展开æˆä¸ºæˆ‘们所需è¦çš„å—符串。
(setq-default abbrev-mode t)
(define-abbrev-table 'global-abbrev-table '(
;; Shifu
("8zl" "zilongshanren")
;; Tudi
("8lxy" "lixinyang")
))
上é¢çš„缩写å‰ä½¿ç”¨çš„ 8
也类似于命å空间的作用,使其ä¸ä¼šä¸Žæˆ‘们所常用的å—符串冲çªã€‚
Company æœ‰æ—¶å€™è¡¥å…¨åŠŸèƒ½å¹¶ä¸æ˜¯éžå¸¸ç†æƒ³ï¼Œè¿™æ—¶å°±å¯ä»¥ä½¿ç”¨ Hippie Expand æ¥å®Œæˆè¡¥å…¨ã€‚ Company Mode 补全效果ä¸ç†æƒ³çš„åŽŸå› æ˜¯åœ¨ä¸åŒçš„区域ä¸ä¼šä½¿ç”¨ä¸åŒçš„åŽç«¯å‡½æ•°æ¥å®Œæˆè¡¥å…¨ï¼Œ 但是当åŽç«¯è¡¥å…¨å‡½æ•°ä¸èƒ½è¢«æ¿€æ´»æ—¶ï¼Œåˆ™è¡¥å…¨å°±ä¸ä¼šè¢«æ¿€æ´»ã€‚
我们å¯ä»¥å°†ä¸‹é¢çš„代ç åŠ å…¥åˆ°æˆ‘ä»¬çš„é…置文件ä¸ï¼Œæ¥å¢žå¼º Hippie Expand 的功能,
(setq hippie-expand-try-function-list '(try-expand-debbrev
try-expand-debbrev-all-buffers
try-expand-debbrev-from-kill
try-complete-file-name-partially
try-complete-file-name
try-expand-all-abbrevs
try-expand-list
try-expand-line
try-complete-lisp-symbol-partially
try-complete-lisp-symbol))
ç„¶åŽå°†å…¶ç»‘定为快æ·é”®ï¼Œä½¿æˆ‘们å¯ä»¥æ›´æ–¹ä¾¿çš„使用它。
(global-set-key (kbd "s-/") 'hippie-expand)
Dired Mode 是一个强大的模å¼å®ƒèƒ½è®©æˆ‘们完æˆå’Œæ–‡ä»¶ç®¡ç†ç›¸å…³çš„æ‰€æœ‰æ“作。
使用 C-x d
å°±å¯ä»¥è¿›å…¥ Dired Mode,这个模å¼ç±»ä¼¼äºŽå›¾å½¢ç•Œé¢ç³»ç»Ÿä¸çš„资æºç®¡ç†å™¨ã€‚ä½
å¯ä»¥åœ¨å…¶ä¸æŸ¥çœ‹æ–‡ä»¶å’Œç›®å½•的详细信æ¯ï¼Œå¯¹ä»–们进行å„ç§æ“作,甚至å¤åˆ¶ç²˜è´´ç¼“冲区ä¸çš„内
å®¹ã€‚ä¸‹é¢æ˜¯ä¸€äº›å¸¸ç”¨çš„æ“ä½œï¼ˆä¸‹é¢çš„æ‰€æœ‰é”®å‡éœ€åœ¨ Dired Mode 下使用),
+
创建目录g
刷新目录C
æ‹·è´D
åˆ é™¤R
é‡å‘½åd
æ ‡è®°åˆ é™¤u
å–æ¶ˆæ ‡è®°x
æ‰§è¡Œæ‰€æœ‰çš„æ ‡è®°
è¿™é‡Œæœ‰å‡ ç‚¹å¯ä»¥ä¼˜åŒ–çš„åœ°æ–¹ã€‚ç¬¬ä¸€æ˜¯åˆ é™¤ç›®å½•çš„æ—¶å€™ Emacs 会询问是å¦é€’å½’åˆ é™¤æˆ–æ‹·è´ï¼Œ 这也有些麻烦我们å¯ä»¥ç”¨ä¸‹é¢çš„é…ç½®å°†å…¶è®¾å®šä¸ºé»˜è®¤é€’å½’åˆ é™¤ç›®å½•ï¼ˆå‡ºäºŽå®‰å…¨åŽŸå› çš„è€ƒè™‘ï¼Œ ä¹Ÿè®¸ä½ éœ€è¦ä¿æŒæ¤è¡Œä¸ºã€‚所有文ä¸çš„é…置请务必按需é…置)。
(setq dired-recursive-deletes 'always)
(setq dired-recursive-copies 'always)
第二是,æ¯ä¸€æ¬¡ä½ è¿›å…¥ä¸€ä¸ªå›žè½¦è¿›å…¥ä¸€ä¸ªæ–°çš„ç›®å½•ä¸æ˜¯ï¼Œä¸€ä¸ªæ–°çš„缓冲区就会被建立。这使 得我们的缓冲区列表ä¸å……æ»¡äº†å¤§é‡æ²¡æœ‰å®žé™…æ„义的记录。我们å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„代ç ,让 Emacs é‡ç”¨å”¯ä¸€çš„一个缓冲区作为 Dired Mode 显示专用缓冲区。
(put 'dired-find-alternate-file 'disabled nil)
;; ä¸»åŠ¨åŠ è½½ Dired Mode
;; (require 'dired)
;; (defined-key dired-mode-map (kbd "RET") 'dired-find-alternate-file)
;; å»¶è¿ŸåŠ è½½
(with-eval-after-load 'dired
(define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file))
ä½¿ç”¨å»¶è¿ŸåŠ è½½å¯ä»¥ä½¿ç¼–è¾‘å™¨åŠ è½½é€Ÿåº¦æœ‰æ‰€æå‡ã€‚
å¯ç”¨ dired-x
å¯ä»¥è®©æ¯ä¸€æ¬¡è¿›å…¥ Dired æ¨¡å¼æ—¶ï¼Œä½¿ç”¨æ–°çš„å¿«æ·é”® C-x C-j
å°±å¯ä»¥è¿›
入当剿–‡ä»¶å¤¹çš„æ‰€åœ¨çš„路径。
(require 'dired-x)
使用 (setq dired-dwin-target 1)
则å¯ä»¥ä½¿å½“一个窗å£ï¼ˆframe)ä¸å˜åœ¨ä¸¤ä¸ªåˆ†å±
(window)时,将å¦ä¸€ä¸ªåˆ†å±è‡ªåŠ¨è®¾ç½®æˆæ‹·è´åœ°å€çš„ç›®æ ‡ã€‚
最åŽå¦‚æžœä½ æ˜¯ Mac OS X 的用户,å¯ä»¥å®‰è£… reveal-in-osx-finder
这个æ’ä»¶ï¼ˆä½ å¯ä»¥åœ¨
这里找到它),它å¯ä»¥å°†ä»»æ„文件直接在 Finder 䏿‰“å¼€ã€‚ä½ æƒ³å®‰è£…è¿™ä¸ªæ’ä»¶ï¼Œå°†å…¶æ·»åŠ è‡³
第二天的æ’件列表ä¸å³å¯ï¼Œä¸‹æ¬¡å¯åЍ Emacs æ—¶ï¼Œå®ƒå°±ä¼šè‡ªåŠ¨å¸®ä½ å®Œæˆä¸‹è½½ã€‚
Org-mode 下的文å¦ç¼–ç¨‹å°†é¢ è¦†ä½ å¯¹äºŽ Emacs çš„çœ‹æ³•ã€‚å› ä¸ºæˆ‘ä»¬ä¹Ÿå¯ä»¥ä½¿ç”¨ Org æ¥ç®¡ç† Emacs çš„é…置文件(笔者和他的师傅其实更倾å‘于模å—管ç†é…置文件)。
ä½ éœ€è¦å°†ä¸‹é¢çš„ä»£ç æ”¾å…¥é…ç½®å…¥å£æ–‡ä»¶ï¼ˆ init.el
)ä¸ï¼Œ
(package-initialize)
(require 'org-install)
(require 'ob-tangle)
(org-babel-load-file (expand-file-name "org-file-name.org" user-emacs-directory))
ä¹‹åŽæˆ‘们需è¦åšçš„ä»…ä»…åªæ˜¯å°†æ‰€æœ‰çš„é…置文件放入 Org 模å¼ä¸çš„代ç å—å³å¯ï¼Œå¹¶ä½¿ç”¨ç›®å½•
结构æ¥è¡¨è¿°ä½ çš„é…ç½®æ–‡ä»¶å†æŠŠå®ƒä¿å˜åœ¨ä¸Žå…¥å£æ–‡ä»¶ç›¸åŒçš„目录ä¸å³å¯ï¼ˆæ–‡ä»¶å为
org-file-name.org
)。Emacs 会æå–å…¶ä¸çš„é…ç½®å¹¶ä½¿å…¶ç”Ÿæ•ˆã€‚è¿™æ ·åšçš„好处是å¯ä»¥ä½¿è‡ª
己和他人更直观的,ç†è§£ä½ çš„é…置文件或者代ç 。
视频地å€å¦‚下
照例我们先修å¤ä¸€äº›çŽ°åœ¨å˜åœ¨çš„å°é—®é¢˜ã€‚首先是自动é…对的å°é—®é¢˜ï¼Œåœ¨ Emacs Lisp 䏿ˆ‘们
有时候åªéœ€è¦ä¸€ä¸ª '
但是 Emacs 很好心的帮我们åšäº†è¡¥å…¨ï¼Œä½†è¿™å¹¶ä¸æ˜¯æˆ‘们需è¦çš„。我
们å¯ä»¥é€šè¿‡ä¸‹é¢çš„ä»£ç æ¥è®©ä½¿ Emacs Lisp 在 Emacs ä¸çš„编辑å˜å¾—更方便(å¯ä»¥å°†å…¶æ·»åŠ
至 init-default.el
é…置文件ä¸ï¼‰ã€‚
(sp-local-pair 'emacs-lisp-mode "'" nil :actions nil)
(sp-local-pair 'lisp-interaction-mode "'" nil :actions nil)
;; 也å¯ä»¥æŠŠä¸Šé¢ä¸¤å¥åˆèµ·æ¥
(sp-local-pair '(emacs-lisp-mode lisp-interaction-mode) "'" nil :actions nil)
åœ¨æ·»åŠ é…置代ç åŽé‡å¯ Emacs ä½¿å…¶ç”Ÿæ•ˆã€‚å½“ç„¶è¿™ä¸ªæ–¹æ³•ä½ ä¹Ÿå¯ä»¥è¿ç”¨åœ¨å…¶ä»–çš„å„个 Major Mode ä¸ï¼Œå¦‚æžœä½ ä¸æƒ³ Emacs 对æŸäº›ç¬¦å·è¿›è¡Œç±»ä¼¼çš„自动匹é…补全。
show-paren-mode
å¯ä»¥ä½¿é¼ æ ‡åœ¨æ‹¬å·ä¸Šæ˜¯é«˜äº®å…¶æ‰€åŒ¹é…çš„å¦ä¸€åŠæ‹¬å·ï¼Œç„¶è€Œæˆ‘们想è¦å…‰æ ‡
在括å·å†…时就高亮包å«å†…容的两个括å·ï¼Œä½¿ç”¨ä¸‹é¢çš„代ç å°±å¯ä»¥åšåˆ°è¿™ä¸€ç‚¹ã€‚
(define-advice show-paren-function (:around (fn) fix-show-paren-function)
"Highlight enclosing parens."
(cond ((looking-at-p "\\s(") (funcall fn))
(t (save-excursion
(ignore-errors (backward-up-list))
(funcall fn)))))
Lisp çš„å®ï¼ˆMacro)类似于 C++ ä¸çš„æ¨¡æ¿ï¼Œå¹¶å¯ä»¥ç”Ÿäº§æ–°çš„代ç ï¼ˆä½ å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°æ›´å¤š 关于å®çš„讨论)。使用它,我们å¯ä»¥å¢žå¼ºæŸä¸ªå‡½æ•°çš„功能而ä¸åŽ»æ›´æ”¹è¿™ä¸ªå‡½æ•°çš„ä»£ç 。
还有一个å°é—®é¢˜å°±æ˜¯è§£å†³åœ¨ä¸åŒç³»ç»Ÿä¸çš„æ¢è¡Œç¬¦ï¼Œä¾‹å¦‚åœ¨ DOS 系统下的 \r(^M)
æ¢è¡Œç¬¦ï¼Œ
这让我们有时候在 Unix 系统ä¸å¾ˆæ˜¯å¤´ç–¼ï¼Œå› 为它的å˜åœ¨ä¼šä½¿ç‰ˆæœ¬æŽ§åˆ¶è¯¯ä»¥ä¸ºæ•´è¡Œçš„代ç 都
è¢«ä¿®æ”¹è¿‡è€Œé€ æˆä¸å¿…è¦çš„éº»çƒ¦ã€‚ï¼ˆä½ å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°æ›´å¤šå…³äºŽ \r(^M)
的信æ¯ï¼‰
æˆ‘ä»¬ç”¨ä¸¤ç§æ–¹å¼æ¥å¤„ç†è¿™ä¸ªé—®é¢˜ï¼Œéšè—这个æ¢è¡Œç¬¦æˆ–è€…å°†å…¶åˆ é™¤ã€‚é¦–å…ˆä¸‹é¢æ˜¯éšè—的方法,
(defun hidden-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(interactive)
(unless buffer-display-table
(setq buffer-display-table (make-display-table)))
(aset buffer-display-table ?\^M []))
使用下é¢çš„代ç 则å¯ä»¥å®šä¹‰å‡½æ•°å°†æ¤æ¢è¡Œç¬¦åˆ 除,
(defun remove-dos-eol ()
"Replace DOS eolns CR LF with Unix eolns CR"
(interactive)
(goto-char (point-min))
(while (search-forward "\r" nil t) (replace-match "")))
Emacs 自带的 HTML Mode 使用起æ¥å¹¶ä¸æ˜¯é‚£ä¹ˆçš„æ–¹ä¾¿ï¼Œè€Œ web-mode 则是一个éžå¸¸å¸¸ç”¨ä¹Ÿ 很强大的用于编辑å‰ç«¯ä»£ç çš„ Major Modeï¼ˆä½ å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°æ›´å¤šå…³äºŽå®ƒçš„ä¿¡æ¯ï¼‰ã€‚
首先我们需è¦å®‰è£…它,照例我们需è¦å°†å…¶æ·»åŠ è‡³æˆ‘ä»¬çš„æ’件列表ä¸åŽ»ã€‚
(defvar xinyang/packages '(
;; ä½ å…¶ä»–çš„æ’件在这里
web-mode
) "Default packages")
在安装完æˆåŽæˆ‘们就å¯ä»¥å¼€å§‹é…置它了,首先我们需è¦åšçš„æ˜¯å°†æ‰€æœ‰çš„ *.html
文件都使
用 web-mode æ¥æ‰“开。
(setq auto-mode-alist
(append
'(("\\.js\\'" . js2-mode))
'(("\\.html\\'" . web-mode))
auto-mode-alist))
è¿™æ ·æ‰€æœ‰çš„ HTML 代ç 在 Emacs ä¸å°±ä¼šä¹‹é—´å¯ç”¨ web-mode 而éžé»˜è®¤çš„ HTML Mode äº†ã€‚ä½ å¯ä»¥é˜…读它的文档æ¥å¦ä¹ 更多 web-mode 详细的使用方法。
例如使用 M-;
å°±å¯ä»¥æ³¨é‡Šå½“å‰è¡Œä»£ç 或选ä¸è¡Œçš„代ç 。
æŽ¥ä¸‹æ¥æˆ‘们æ¥åšæ›´å¤šç»†èŠ‚çš„é…置,首先是缩å‡çš„大å°çš„è®¾ç½®ã€‚å› ä¸º web-mode 支æŒåœ¨ HTML 文件ä¸å˜åœ¨å¤šè¯è¨€ï¼Œæ‰€ä»¥æˆ‘们å¯ä»¥å¯¹ä¸åŒçš„è¯è¨€çš„缩å‡åšå‡ºè®¾ç½®ã€‚下é¢çš„代ç 用于设置åˆå§‹ 的代ç 缩进,
(defun my-web-mode-indent-setup ()
(setq web-mode-markup-indent-offset 2) ; web-mode, html tag in html file
(setq web-mode-css-indent-offset 2) ; web-mode, css in html file
(setq web-mode-code-indent-offset 2) ; web-mode, js code in html file
)
(add-hook 'web-mode-hook 'my-web-mode-indent-setup)
下é¢çš„函数å¯ä»¥ç”¨äºŽåœ¨ä¸¤ä¸ªç©ºæ ¼å’Œå››ä¸ªç©ºæ ¼ä¹‹é—´è¿›è¡Œåˆ‡æ¢ï¼Œ
(defun my-toggle-web-indent ()
(interactive)
;; web development
(if (or (eq major-mode 'js-mode) (eq major-mode 'js2-mode))
(progn
(setq js-indent-level (if (= js-indent-level 2) 4 2))
(setq js2-basic-offset (if (= js2-basic-offset 2) 4 2))))
(if (eq major-mode 'web-mode)
(progn (setq web-mode-markup-indent-offset (if (= web-mode-markup-indent-offset 2) 4 2))
(setq web-mode-css-indent-offset (if (= web-mode-css-indent-offset 2) 4 2))
(setq web-mode-code-indent-offset (if (= web-mode-code-indent-offset 2) 4 2))))
(if (eq major-mode 'css-mode)
(setq css-indent-offset (if (= css-indent-offset 2) 4 2)))
(setq indent-tabs-mode nil))
(global-set-key (kbd "C-c t i") 'my-toggle-web-indent)
js2-refactor æ˜¯ä¸€ä¸ªç”¨äºŽé‡æž„ JavaScript çš„æ’件,它是一个 Minor Modeï¼Œä½ å¯ä»¥åœ¨ GitHub 找到更多关于这个æ’件的信æ¯ã€‚
我们使用刚刚所æåˆ°çš„æ–¹æ³•æ¥å®‰è£… js2-refactor æ’件。
在安装完æˆåŽï¼Œæ·»åŠ ä¸€ä¸ªé’©å(Hook):
(add-hook 'js2-mode-hook #'js2-refactor-mode)
(js2r-add-keybindings-with-prefix "C-c C-m")
我们å¯ä»¥ä½¿ç”¨ C-c C-m
ç„¶åŽè¾“入功能å‰ç¼€ï¼Œä¾‹å¦‚ em
是 extract-method çš„å‰ç¼€ã€‚æ›´
多的功能和使用方法也å¯ä»¥åœ¨ä¸Šé¢ç»™å‡ºçš„é“¾æŽ¥ä¸æ‰¾åˆ°ï¼Œæ‰€æœ‰çš„å‰ç¼€ä¹Ÿå¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
下é¢çš„代ç 用于é…ç½® Occur Mode 使其默认æœç´¢å½“å‰è¢«é€‰ä¸çš„æˆ–è€…åœ¨å…‰æ ‡ä¸‹çš„å—符串:
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(let ((sym (thing-at-point 'symbol)))
(when (stringp sym)
(regexp-quote sym))))
regexp-history)
(call-interactively 'occur))
(global-set-key (kbd "M-s o") 'occur-dwim)
dwim
是按我说的åšçš„缩写(Do what I mean)。
Occur å¯ä»¥ç”¨äºŽæ˜¾ç¤ºå˜é‡æˆ–函数的定义,我们å¯ä»¥é€šè¿‡ popwin çš„ customize-group 将定
义显示设置为å³è¾¹è€Œä¸æ˜¯é»˜è®¤çš„底部( customize-group > popwin > Popup Window
Position
设置为 right),也å¯ä»¥åœ¨è¿™é‡Œå¯¹å…¶å®½åº¦è¿›è¡Œè°ƒèŠ‚ã€‚
Occur 与普通的æœç´¢æ¨¡å¼ä¸åŒçš„æ˜¯ï¼Œå®ƒå¯ä»¥ä½¿ç”¨ Occur-Edit Mode (在弹出的窗å£ä¸æŒ‰ e
进入编辑模å¼) 对æœç´¢åˆ°çš„结果进行之间的编辑。
imenu å¯ä»¥æ˜¾ç¤ºå½“剿‰€æœ‰ç¼“冲区的列表,下é¢çš„é…ç½®å¯ä»¥è®©å…¶æ‹¥æœ‰æ›´ç²¾ç¡®çš„跳转,
(defun js2-imenu-make-index ()
(interactive)
(save-excursion
;; (setq imenu-generic-expression '((nil "describe\\(\"\\(.+\\)\"" 1)))
(imenu--generic-function '(("describe" "\\s-*describe\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("it" "\\s-*it\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("test" "\\s-*test\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("before" "\\s-*before\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("after" "\\s-*after\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("Function" "function[ \t]+\\([a-zA-Z0-9_$.]+\\)[ \t]*(" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*=[ \t]*function[ \t]*(" 1)
("Function" "^var[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*=[ \t]*function[ \t]*(" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*()[ \t]*{" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*:[ \t]*function[ \t]*(" 1)
("Task" "[. \t]task([ \t]*['\"]\\([^'\"]+\\)" 1)))))
(add-hook 'js2-mode-hook
(lambda ()
(setq imenu-create-index-function 'js2-imenu-make-index)))
(global-set-key (kbd "M-s i") 'counsel-imenu)
ä½¿ç”¨åŒæ ·çš„æ–¹æ³•å°† expand-region æ·»åŠ è‡³æˆ‘ä»¬çš„æ’件列表ä¸ï¼Œé‡å¯ Emacs 安装æ’件。
å†ä¸ºå…¶ç»‘定一个快æ·é”®ï¼Œ
(global-set-key (kbd "C-=") 'er/expand-region)
使用这个æ’ä»¶å¯ä»¥ä½¿æˆ‘们更方便的选ä¸ä¸€ä¸ªåŒºåŸŸã€‚(更多使用方法和文档å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ï¼‰
iedit 是一个å¯ä»¥åŒæ—¶ç¼–辑多个区域的æ’件,它类似 Sublime Text ä¸çš„å¤šå…‰æ ‡ç¼–è¾‘ã€‚å®ƒçš„ GitHub 仓库在这里。
我们将其绑定快æ·é”®ä»¥ä¾¿æ›´å¿«æ·çš„使用这个模å¼ï¼ˆ C-;
为默认快æ·é”®ï¼‰ï¼Œ
(global-set-key (kbd "M-s e") 'iedit-mode)
我们å¯ä»¥ä½¿ç”¨ Customized-group æ¥æ›´æ”¹å…¶é«˜äº®çš„背景色,将 highlight
改为 region
。
使用 C-c C-e
å¯ä»¥å°† Org-mode æ–‡æ¡£å¯¼å‡ºä¸ºä½ éœ€è¦çš„æ ¼å¼ï¼Œä¾‹å¦‚ HTML 或者 PDF 文件。
ä½ çŽ°åœ¨çœ‹åˆ°çš„è¿™æœ¬æ•™ç¨‹å°±æ˜¯ç”± Org-mode 所导出生æˆçš„。
视频地å€å¦‚下
åœ¨å¼€å§‹å‰æˆ‘ä»¬éœ€è¦æ³¨æ„çš„æ˜¯ä¹‹å‰æ¨¡å—化的é…置文件 init-keybindings.el
应该放在所有
调用模å—的最åŽé¢ï¼Œå› 为也许在设置快æ·é”®æ—¶æŸäº›å‡½æ•°è¿˜æœªè¢«åŠ è½½ã€‚
我们å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„é…ç½®æ¥åœ¨ Company-mode ä¸ä½¿ç”¨ C-n
与 C-p
æ¥é€‰æ‹©è¡¥å…¨é¡¹ï¼Œ
(with-eval-after-load 'company
(define-key company-active-map (kbd "M-n") nil)
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous))
在å¦ä¹ 代ç ç‰‡æ®µå’Œè¯æ³•检查器(Linter)之å‰ï¼Œæˆ‘们先æ¥å¦ä¹ 一下如何使用 Org-mode æ¥åš å¦ä¹ 笔记和安排工作时间。我们用下é¢çš„é…ç½®ä»£ç æ¥è®¾ç½®ä¸€ä¸ªæ¨¡æ¿ï¼ˆå…¶ä¸è®¾ç½®äº†å¾…办事项的 优先级还有触å‘键),
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/.emacs.d/gtd.org" "工作安排")
"* TODO [#B] %?\n %i\n"
:empty-lines 1)))
我们也å¯ä»¥ä¸ºå…¶ç»‘定一个快æ·é”®ï¼Œ
(global-set-key (kbd "C-c r") 'org-capture)
这个功能除了å¯ä»¥è®°å½•待办事项还有其他许许多多的功能例如获å–将当剿µè§ˆå™¨ä¸çš„ URL(下é¢çš„例ååªåœ¨ Mac OS X 平尿œ‰æ•ˆï¼‰ã€‚
(defun YOUR_NAME/retrieve-chrome-current-tab-url()
"Get the URL of the active tab of the first window"
(interactive)
(let ((result (do-applescript
(concat
"set frontmostApplication to path to frontmost application\n"
"tell application \"Google Chrome\"\n"
" set theUrl to get URL of active tab of first window\n"
" set theResult to (get theUrl) \n"
"end tell\n"
"activate application (frontmostApplication as text)\n"
"set links to {}\n"
"copy theResult to the end of links\n"
"return links as string\n"))))
(format "%s" (s-chop-suffix "\"" (s-chop-prefix "\"" result)))))
更多有关 Org-capture 的内容å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
Org-pomodoro 是一个番茄时间工作法的æ’件(更多关于这个工作法的信æ¯å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ï¼‰ã€‚
它的 GitHub 地å€åœ¨è¿™é‡Œã€‚在 (require 'org-pomodoro)
åŽå¯ä»¥é€šè¿‡ Customize-group
æ¥å¯¹å…¶è¿›è¡Œè®¾ç½®ï¼ŒåŒ…括ä¸åŒä¼‘æ¯ç§ç±»çš„æ—¶é•¿ã€‚
å› ä¸ºæ¯æ¬¡ä¿å˜ä¸æ–‡çš„æ—¶å€™éƒ½éœ€è¦é€‰æ‹©è§£ç ,我们å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„é…置将文本解ç 设置默认为 UTF-8,
(set-language-environment "UTF-8")
当 org-mode ä¸èƒ½ç”Ÿæ•ˆæ—¶ï¼Œæˆ‘们需è¦å°†ä¸Ž Org 相关的é…置放置于 with-eval-after-load
ä¸ï¼Œ
(with-eval-after-load 'org
;; Org 模å¼ç›¸å…³è®¾å®š
)
C-x C-q
å°±å¯ä»¥ç›´æŽ¥åœ¨ Dired Mode ä¸è¿›è¡Œç¼–辑,使用之å‰å¦çš„ iedit-mode 和区域选择
å°±å¯ä»¥ç›´æŽ¥å¯¹å¤šä¸ªæ–‡ä»¶è¿›è¡Œé‡å‘½å编辑了。
全局æœç´¢åœ¨æˆ‘ä»¬çš„ç¼–è¾‘å·¥ä½œä¸æ˜¯ä¸å¯ç¼ºå°‘的,今天我们介ç»çš„æ˜¯ ag。它是éžå¸¸å¿«é€Ÿçš„命令 行æœç´¢å·¥å…·ï¼Œå®ƒæ˜¯ Linux 的所有æœç´¢å·¥å…·ä¸æœ€å¿«çš„。
ag > pt > ack > grep
在使用 ag 剿ˆ‘们需è¦è¿›è¡Œå®‰è£…ï¼Œä¸‹é¢æ˜¯ Mac OS X 与 Ubuntu 下的安装方法,
# Mac OS X 通过 Homebrew 安装 brew install the_silver_searcher # Ubuntu 下安装 apt-get install silversearcher-ag # Windows 下通过 msys2 安装(确ä¿åœ¨ path ä¸ï¼‰ pacman -S mingw-w64-i686-ag # 32 ä½ç”µè„‘ pacman -S mingw-w64-x86_64-ag # 64 ä½ç”µè„‘
安装好 ag åŽæˆ‘们就å¯ä»¥å®‰è£… helm-ag æ’件了。(它的 GitHub 仓库地å€åœ¨è¿™é‡Œï¼‰åœ¨å®‰è£… 完æˆåŽå¯ä»¥ä¸ºå…¶è®¾ç½®å¿«æ·é”®ï¼Œ
(global-set-key (kbd "C-c p s") 'helm-do-ag-project-root)
使用这个æ’ä»¶æˆ‘ä»¬åŒæ ·å¯ä»¥åœ¨ç¼“冲区对æœç´¢åˆ°çš„ç»“æžœè¿›è¡Œç›´æŽ¥çš„ä¿®æ”¹ï¼Œè¿™æ ·å°±å¯ä»¥åšåˆ°å¿«é€Ÿ çš„æœç´¢ä¸Žæ›¿æ¢ã€‚
è¯æ³•检查器å¯ä»¥åœ¨å¼€å‘动æ€è¯è¨€ï¼ˆInterpreted/Dynamic Programming Language)时æžå¤§çš„ æé«˜ä½ çš„å¼€å‘æ•ˆçŽ‡ï¼Œå®ƒä¼šå®žæ—¶çš„æ£€æŸ¥ä½ çš„ä»£ç 并将奿³•错误(Syntax Errorï¼‰ä¸Žé™æ€è¯ä¹‰ (Static Semantic Error)错误进行高亮与æç¤ºã€‚
æˆ‘ä»¬åœ¨è¿™é‡Œä½¿ç”¨çš„ä¾‹åæ˜¯ JavaScript çš„è¯æ³•检查器 eslint 它的安装方法å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
åœ¨å®‰è£…å¥½è¯æ³•检查器åŽå°±å¯ä»¥å®‰è£… flycheck çš„æ’件了,它的 GitHub 的地å€åœ¨è¿™é‡Œã€‚
使用下é¢çš„代ç å¯ä»¥å°† flycheck-mode 在特定模å¼ä¸‹æ¿€æ´»ï¼ˆä¸‹é¢çš„例åå°±æ˜¯åªæœ‰åœ¨æ‰“å¼€ JavaScript æ—¶æ‰ä¼šæ¿€æ´»è¯æ³•检查器),
(add-hook 'js2-mode-hook 'flycheck-mode)
使用 flycheck-verify-setup
å¯ä»¥è¿›è¡Œè¯æ³•检查器的选择。
eslint 检查器的é…置也å¯ä»¥ä½¿ç”¨é¡¹ç›®ç›®å½•下的 .eslintrc
æ¥è¿›è¡Œé…置,更多é…置方法å¯
以在这里找到。
yasnippet
是一个代ç å—补全的æ’件(GitHub 地å€ï¼‰ã€‚使用下é¢çš„é…置文件将其在所有
的编程è¯è¨€çš„æ¨¡å¼ä¸æ¿€æ´»ã€‚
(yas-reload-all)
(add-hook 'prog-mode-hook #'yas-minor-mode)
自定义代ç å—的方法å¯ä»¥åœ¨ä¸Šé¢æä¾›çš„é“¾æŽ¥ä¸æ‰¾åˆ°ã€‚
auto-yasnippet 也是一个éžå¸¸å¥½ç”¨ä»£ç å—补全æ’件。安装并未其设置快æ·é”®ï¼Œ
(global-set-key (kbd "H-w") #'aya-create)
(global-set-key (kbd "H-y") #'aya-expand)
简å•的使用方法就是使用 ~
æ¥å®šä¹‰æ¨¡æ¿ï¼Œç„¶åŽè°ƒç”¨ aya-create
å†ä½¿ç”¨ aya-expand
æ¥ä½¿ç”¨æ¨¡æ¿ã€‚
视频地å€å¦‚下,
开始之剿ˆ‘们先将 C-w
æ¥ä½¿å…¶å¯ä»¥å‘åŽåˆ 除一个å•è¯ï¼Œè¿™æ ·å°±å¯ä»¥ä¸Ž Shell ä¸çš„å¿«æ·é”®æ“ä½œåŒæ¥ã€‚
(global-set-key (kbd "C-w") 'backward-kill-word)
å¦‚æžœä½ ä¸æ˜¯ Vim çš„ç”¨æˆ·ï¼Œä½ å¯ä»¥é€‰æ‹©è·³è¿‡è¿™ä¸€å¤©çš„å†…å®¹ã€‚ä½†æ˜¯æˆ‘ä»¬å¼ºçƒˆå»ºè®®ä½ èŠ±ä¸€äº›æ—¶é—´ æ¥å¦ä¹ 基本的 Vim æ“作,å³ä½¿ Emacs æ˜¯ä½ çš„æœ€çˆ± Vim 的快æ·é”®ä¹Ÿåœ¨ä¸€å®šç¨‹åº¦ä¼šå¢žåŠ ä½ çš„ 编辑效率。基础的 Vim æ“作å¯ä»¥åœ¨è¿™é‡Œå¦ä¼šã€‚
Evil 模å¼ä¸çš„ State 就相当与 Vim ä¸çš„æ¨¡å¼ï¼Œå¸¸ç”¨çš„æ¨¡å¼æœ‰ä¸‹é¢å‡ ç§ï¼ˆåŽé¢å¯¹äºŽäº†ç›¸åº” çš„ Emacs ä¸çš„ State),
- Normal Mode -> Normal State
- Insert Mode -> Insert State
- Visual Mode -> Visual State
- Motion Mode -> Motion State
还有一个 Emacs ä¸çš„ç‰¹æ®ŠçŠ¶æ€æ˜¯ Emacs State。
照例我们需è¦å°† Evil æ’ä»¶æ·»åŠ è‡³æˆ‘ä»¬çš„æ’ä»¶åˆ—è¡¨ä¸æ¥å®Œæˆå®‰è£…。在é‡å¯ Emacs 完æˆå®‰è£… åŽå¯ä»¥æ·»åР䏋é¢çš„代ç 将其激活。
(evil-mode 1)
在激活 Evil 模å¼åŽå°±å¯ä»¥ï¼Œåœ¨ Emacs ä¸ä½¿ç”¨ Vim 的快æ·é”®äº†ã€‚æœ‰ä¸€ç‚¹éœ€è¦æ³¨æ„ C-u
在 Emacs 䏿œ‰ç‰¹æ®Šçš„功所(Universal args)以能我们å¯ä»¥é€šè¿‡ä½¿ç”¨ customize-group
æ¥å¯¹ Evil 模å¼è¿›è¡Œä¿®æ”¹ï¼Œå°† Evil Want C U Scroll
设置为开å¯ã€‚
下é¢çš„代ç å¯ä»¥å°† insert state map
ä¸çš„å¿«æ·é”®æ¸…空,使其å¯ä»¥å›žé€€ï¼ˆFallback)到
Emacs State ä¸ï¼Œè¿™æ ·æˆ‘们之å‰çš„ Emacs State 里é¢å®šä¹‰çš„ C-w
ç‰å¿«æ·é”®å°±ä¸ä¼šè¢«
evil insert minor mode state
所覆盖,
(setcdr evil-insert-state-map nil)
(define-key evil-insert-state-map [escape] 'evil-normal-state)
è¿™æ ·ä½ å°±å¯ä»¥ä½¿ç”¨ Evil æ¥åœ¨ Emacs ä¸å®Œæˆç™¾åˆ†ä¹‹å…«å作用的快æ·é”®æ“作了。
完整的 Evil Mode çš„ PDF 版本的æ“作指å—å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ï¼Œå»ºè®®ä»Ž Vim 转 Emacs 的用户 多次阅读æ¥å®Œæ•´çš„æŽŒæ¡è¿™ä¸ªæ¨¡å¼çš„使用方法。
在 Emacs ä¸ä½¿ç”¨ Leader Key å¯ä»¥é€šè¿‡ evil-leader æ¥å®žçŽ°ã€‚ä½ éœ€è¦åšçš„就是在安装åŽå°†å…¶æ¿€æ´»å³å¯ã€‚
æç¤º: æ ¹æ®cofi/evil-leader çš„è¯´æ˜Žï¼Œä½ åº”è¯¥åœ¨æ¿€æ´» evil-mode 之å‰å°±æ¿€æ´» global-evil-leader-mode,å¦åˆ™ evil-leader åœ¨å‡ ä¸ªåˆå§‹ç¼“冲区(scratch, Message,…)上将ä¸ç”Ÿæ•ˆã€‚
(global-evil-leader-mode)
Leader Key å¯ä»¥é€šè¿‡ customize-group æ¥è¿›è¡Œè®¾ç½®ï¼ˆEvil Leader/Leaderï¼‰ã€‚å› ä¸ºä¹‹åŽæˆ‘
们会转移至 Spacemacs 所以我们å¯ä»¥å°†å…¶è®¾ç½®ä¸ºç©ºæ ¼é”® SPC
。
在通过下é¢çš„é…ç½®æ¥è®¾ç½®ç®€å•çš„ç»“åˆ Leader Key å¿«æ·é”®ç»„åˆï¼ˆæˆ‘们使用ä¸åŒçš„键讲ä¸åŒçš„
功能分组,例如我们使用 f
é”®æ¥åšå…³äºŽæ–‡ä»¶çš„æ“ä½œï¼Œä½¿ç”¨ b
é”®æ¥åšå…³äºŽç¼“冲区
(Buffer)的æ“作),
(evil-leader/set-key
"ff" 'find-file
"bb" 'switch-to-buffer
"0" 'select-window-0
"1" 'select-window-1
"2" 'select-window-2
"3" 'select-window-3
"w/" 'split-window-right
"w-" 'split-window-below
":" 'counsel-M-x
"wM" 'delete-other-windows
)
注æ„上é¢çª—å£è·³è½¬ç›¸å…³çš„è®¾ç½®éœ€è¦ window-numbering å®‰è£…åŽæ–¹å¯ç”Ÿæ•ˆã€‚
这个æ’ä»¶å¯ä»¥è®©æˆ‘们快速的使用 Leader Key 与数å—é”®çš„ç»„åˆæ¥åœ¨å¤šä¸ªçª—å£ä¹‹é—´è¿›è¡Œè·³è½¬ã€‚ 它的 GitHub 地å€å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚
下载安装åŽé€šè¿‡ä¸‹é¢çš„代ç å¯ä»¥å°†å…¶æ¿€æ´»ï¼Œ
(window-numbering-mode 1)
Evil-surround 是一个 Vim 上éžå¸¸å¸¸ç”¨çš„æ’ä»¶æ”¹å†™çš„ï¼Œä½¿ç”¨å®ƒå¯ä»¥å¿«é€Ÿçš„将选ä¸åŒºåŸŸè¿›è¡Œ 匹é…çš„æ“作,例如选ä¸åŒºåŸŸä¸¤è¾¹åŒæ—¶è¿›è¡Œæ·»åŠ æˆ–ä¿®æ”¹æ‹¬å·ï¼Œå¼•å·ç‰æ“作。
下载安装åŽä½¿ç”¨ä¸‹é¢çš„代ç 将其激活,
(require 'evil-surround)
(global-evil-surround-mode)
简å•çš„ä½¿ç”¨æ–¹æ³•å°±æ˜¯åœ¨é€‰ä¸æ‰€é€‰åŒºåŸŸåŽï¼Œä½¿ç”¨ S(
æ¥å°†é€‰ä¸åŒºåŸŸåŒ…括在括å·ä¹‹ä¸ã€‚如果想
å°†æ‹¬å·æ”¹å˜æˆ "
å¯ä»¥åœ¨é€‰ä¸åŽä½¿ç”¨ cs("
è¿™æ˜¯ä¸€ä¸ªå¿«é€Ÿæ·»åŠ ä¸Žå–æ¶ˆæ³¨é‡Šçš„æ’ä»¶ï¼Œå®ƒçš„ GitHub 地å€åœ¨è¿™é‡Œã€‚
使用下é¢ä»£ç å¯ä»¥å°†å…¶æ¿€æ´»ï¼Œ
(evilnc-default-hotkeys)
使用下é¢çš„代ç 将其与 Evil 模å¼è¿›è¡Œç»‘定,这里我们选择使用 ,/
作为快æ·é”®ã€‚
(define-key evil-normal-state-map (kbd ",/") 'evilnc-comment-or-uncomment-lines)
(define-key evil-visual-state-map (kbd ",/") 'evilnc-comment-or-uncomment-lines)
which-key å¯ä»¥æ˜¾ç¤ºå½“å‰ç»„åˆé”®ä¸‹æ‰€æœ‰å¯ä»¥ä½¿ç”¨çš„全部组åˆé”®çš„选项。使用这个æ’ä»¶å¯ä»¥å¾ˆ 好的解决快æ·é”®å¤ªå¤šçš„é—®é¢˜ï¼Œæˆ‘ä»¬æ— éœ€åœ¨è®°å¿†ä»»ä½•å¿«æ·é”®ï¼Œè€Œæ˜¯æ ¹æ®è‡ªå·±çš„需求使用ä¸åŒåˆ† 组的快æ·é”®åŽå†åœ¨å…¶ä¸åŽ»éœ€æ‰¾è‡ªå·±éœ€è¦çš„功能。
在下载åŽå¯ä»¥ä½¿ç”¨ä¸‹é¢çš„代ç 进行激活,
(which-key-mode 1)
C-c a
ä¸å¯ä»¥æ ¹æ®æç¤ºä½¿ç”¨ s
æ¥è¿›è¡Œå…³é”®å—所æœã€‚使用 t
则å¯ä»¥è¿›è¡Œä»£åŠžäº‹é¡¹çš„æœç´¢ã€‚
视频地å€å¦‚下:
什么是 Cask:
Cask 是一个 Emacs Lisp 的项目管ç†å·¥å…·.
Cask 的地å€: Cask
å¯ä»¥ä½¿ç”¨å¦‚下命令安装 Cask:
curl -fsSL https://raw.githubusercontent.com/cask/cask/master/go | python
å®‰è£…è¿‡ç¨‹ä¸ Cask 将会进行 Bootstrap, 安装一些包到~/.emacs.d 目录ä¸.
安装完æˆä¹‹åŽéœ€è¦å°† Cask çš„å¯æ‰§è¡Œæ–‡ä»¶ç›®å½•åŠ å…¥åˆ° PATH ä¸.
å¯ä»¥çœ‹åˆ°, Cask 的安装过程在 ~/.emacs.d 䏿–°å»ºäº†ä¸€ä¸ª .Cask 目录.
安装 Pallet: Pallet 是一个基于 Cask 的包管ç†å·¥å…·, å¯ä»¥ä½¿ç”¨ Emacs 的包安装方å¼å®‰è£….
ç„¶åŽä½¿ç”¨ä»¥ä¸‹ä»£ç å¯ç”¨ Pallet:
(pallet-mode)
(pallet-init) ; 在.emacs.d ä¸ç”Ÿæˆä¸€ä¸ª Cask 文件, 写入æºä¸ŽçŽ°æœ‰åŒ…
(pallet-install) ; å°† elpa ä¸çš„ package æ‹·è´åˆ°.Cask/<you version>/elpa 目录ä¸
ç„¶åŽåœ¨é…置文件ä¸åР入以䏋代ç (åœ¨å…¶ä»–åŒ…åŠ è½½ä¹‹å‰) :
(require 'cask "<path-to-cask>/cask.el")
(cask-initialize) ; 类似于 package-initialize
(require 'pallet)
(pallet-mode t) ; 激活 pallet, 在安装包时将 Cask 文件写入相应信æ¯
具体使用方å¼è§æ–‡æ¡£: Pallet
- 使用 Cask 文件ä¿å˜åŒ…的信æ¯, å¯ä»¥é€šè¿‡ Cask install 自动安装
- 当有多个版本的 Emacs æ—¶, å°†å„版本的包å•ç‹¬å˜æ”¾
解决方案: å°† Gnu çš„æºåŠ å…¥æºåˆ—表ä¸, 示例代ç 如下(åŠ å…¥ Cask 文件)
(source "gnu" "http://elpa.zilongshanren.com/gnu/")
define-advice 是一个 Emacs25 ä¸åŠ å…¥çš„å®, 在 Emacs24 ä¸ä¸èƒ½ä½¿ç”¨, å¯ä»¥ä½¿ç”¨ defadvice 代替:
(defadvice show-paren-function (around fix-show-paren-function activate)
(cond ((looking-at-p "\\s(") ad-do-it)
(t (save-excursion
(ignore-errors (backward-up-list))
ad-do-it)))
)
而且使用 defadvice 相比 define-advice 还有一个优点:
使用 define-advice 定义的代ç , 当在 Normal æ¨¡å¼æ—¶å…‰æ ‡ä¸¤è¾¹çš„æ‹¬å·ä¸ä¼šé«˜äº®, 而使用 defadvice å¯ä»¥.
视频地å€å¦‚下:
这次主è¦ä»‹ç» Emacs Lisp ä¸çš„å®(Macro)ä»¥åŠ Use-package æ’ä»¶.
宿˜¯ä¸€ç§å¯ä»¥ç”Ÿæˆä»£ç 的代ç . 类比与 C è¯è¨€ä¸çš„å®ä»¥åŠ C++ä¸çš„æ¨¡æ¿. 先看一个简å•的例å:
(defmacro inc (var)
(list 'setq var (list '1+ var)))
(setq my-var 1)
(setq my-var (+ 1 my-var))
(macroexpand '(inc my-var))
以上这个å®çš„作用是将å˜é‡çš„值+1. 执行以上代ç 之åŽ, my-var 的结果为 2.
å¯ä»¥ä½¿ç”¨ macroexpand 获得å®å±•开的结果, 如以上代ç 结果为:
(setq my-var (1+ my-var))
我们也å¯ä»¥ä½¿ç”¨å‡½æ•°æ¥å®žçŽ°ç›¸åŒçš„功能, 但 Macro 与函数有以下两个区别:
- å®çš„傿•°å¹¶ä¸ä¼šè¢«é©¬ä¸Šæ±‚值, 解释器会先展开å®, å®å±•开之åŽè§£é‡Šå™¨æ‰ä¼šæ‰§è¡Œå®å±•开的 结果; è€Œå‡½æ•°çš„å‚æ•°ä¼šé©¬ä¸Šæ±‚值
- å®çš„æ‰§è¡Œç»“果是一个表达å¼, 该表达å¼ä¼šç«‹å³è¢«è§£é‡Šå™¨æ‰§è¡Œ; 而函数的结果是一个值
backquote 是指å引å·(`), å³é”®ç›˜ä¸Šæ•°å— 1 左边的键.
当在 Emacs 输入 backquote 时会æ’入两个å引å·, å¯ä»¥ä½¿ç”¨ä»¥ä¸‹ä»£ç å…³é—这个功能:
(sp-local-pair 'emacs-lisp-mode "`" nil :actions nil)
å…ˆçœ‹ä»¥ä¸‹ä¾‹åæ¥ä½“ä¼š backquote 的作用:
(defun my-print (number)
(message "This is a number: %d" number))
(my-print 2) ; 1. output= This is a number: 2
(my-print (+ 2 3)) ; 2. output= This is a number: 5
(quote (+ 1 1))
;; return a list= (+ 1 1)
(defmacro my-print-2 (number)
`(message "This is a number: %d" ,number))
(my-print-2 2) ; 3. output= This is a number: 2
(my-print-2 (+ 2 3)) ; 4. output= This is a number: 5
(setq my-var 2)
(inc my-var)
(defmacro inc2 (var1 var2)
(list 'progn (list 'inc var1) (list 'inc var2)))
(macroexpand '(inc2 my-var my-var))
(macroexpand-all '(inc2 my-var my-var))
quote 的作用是返回åŽé¢çš„表达å¼, ä¸å¯¹è¡¨è¾¾å¼è¿›è¡Œæ±‚值. 所以以下代ç :
(quote (+ 1 1))
;; return a list= (+ 1 1)
å¹¶æ²¡æœ‰å¯¹è¡¨è¾¾å¼ (+ 1 1) 进行求值返回 2, 而是返回一个 list.
backquote 的作用与 quote 相似, åŒæ ·ä¸å¯¹åŽé¢çš„è¡¨è¾¾å¼æ±‚值, 但是当 backquote 在å®ä¸ 与逗å·(,)一起使用时, 用逗å·ä¿®é¥°çš„å˜é‡å°†è¿›è¡Œæ±‚值.
例如以下代ç :
(defmacro my-print-2 (number)
`(message "This is a number: %d" ,number))
(pp (macroexpand '(my-print-2 (+ 2 3))))
(my-print-2 (+ 2 3))
当输出 message 且 number ä¸å¸¦é€—å·æ—¶, my-print-2 的执行将æç¤ºé”™è¯¯. å› ä¸ºå®ä¸å¯¹å‚ 数进行求值, 所以以上å®å±•开相当于:
(message "This is a number:" number)
å› ä¸ºæˆ‘ä»¬æ²¡æœ‰å®šä¹‰ number å˜é‡, 所以执行出错.
è€Œå¦‚æžœåŠ å…¥é€—å·, 则在å®å±•开时会对å˜é‡ number 进行求值, 展开结果为:
(message "This is a number: %d" (+ 2 3))
在调试å®çš„过程ä¸, å¯ä»¥ä½¿ç”¨ macroexpand å’Œ macroexpand-all 获å–å®å±•开的结果.
关于 backquote 的更多讨论, å¯ä»¥è§ä»¥ä¸‹åœ°å€: lisp ä¸çš„`与,是怎么用的?
使用å®å¯ä»¥å‡å°‘é‡å¤çš„代ç , ä»¥ä¸‹æ˜¯ä¸€ä¸ªä½¿ç”¨å®æ¥å®šä¹‰å‡½æ•°çš„例å:
(defun prelude-search (query-url prompt)
"Open the search url constructed with the QUERY-URL.
PROMPT sets the `read-string prompt."
(browse-url
(concat query-url
(url-hexify-string
(if mark-active
(buffer-substring (region-beginning) (region-end))
(read-string prompt))))))
(defmacro prelude-install-search-engine (search-engine-name search-engine-url search-engine-prompt) ; #1
"Given some information regarding a search engine, install the interactive command to search through them"
`(defun ,(intern (format "prelude-%s" search-engine-name)) () ; #2
,(format "Search %s with a query or region if any." search-engine-name) ; #3
(interactive)
(prelude-search ,search-engine-url ,search-engine-prompt))) ; #4
(prelude-install-search-engine "google" "http://www.google.com/search?q=" "Google: ") ; #5
(prelude-install-search-engine "youtube" "http://www.youtube.com/results?search_query=" "Search YouTube: ")
(prelude-install-search-engine "github" "https://github.com/search?q=" "Search GitHub: ")
(prelude-install-search-engine "duckduckgo" "https://duckduckgo.com/?t=lm&q=" "Search DuckDuckGo: ")
下é¢å¯¹ä»¥ä¸Šä»£ç 进行讲解:
第#1 行, 通过 prelude-install-search-engine å®šä¹‰äº†ä¸€ä¸ªéœ€è¦ 3 ä¸ªå‚æ•°çš„å®, 这个 å®çš„作用是生æˆä¸€ä¸ªå‡½æ•°.
第#2 行, 通过 intern 生æˆä¸€ä¸ªç¬¦å·ä½œä¸ºå‡½æ•°å, å称为 *prelude-xxx* , å…¶ä¸ xxx ä¸ºç¬¬ä¸€ä¸ªå‚æ•°çš„值.
第#3 行, 生æˆäº†è¿™ä¸ªå‡½æ•°çš„æè¿°.
第#4 行, 调用 prelude-search 函数进行æœç´¢å¤„ç†.
第#5 行, 调用这个å®å®šä¹‰äº†ä¸€ä¸ªå为 *prelude-google* 的函数.
从以上代ç å¯ä»¥çŸ¥é“, 我们利用å®ç”Ÿæˆäº†ï¼”个åç§°ä¸åŒçš„函数, é¿å…了手动编写函数的问题 (å› ä¸ºè¿™ï¼”ä¸ªå‡½æ•°çš„ä»£ç éžå¸¸ç›¸ä¼¼, æ ¹æ® DRY 原则应该尽é‡é¿å…åšè¿™ç§é‡å¤å·¥ä½œ).
关于å®çš„æ›´å¤šå†…容, å¯ä»¥é˜…读 Paul Graham 的著作 《On Lisp》
Use-package 是一个å®, å®ƒèƒ½è®©ä½ å°†ä¸€ä¸ªåŒ…çš„ require 和它的相关的åˆå§‹åŒ–ç‰é…置组织 在一起, é¿å…对åŒä¸€ä¸ªåŒ…çš„é…ç½®ä»£ç æ•£è½åœ¨ä¸åŒçš„æ–‡ä»¶ä¸.
Use-package 的更多信æ¯å‚è§ä»¥ä¸‹åœ°å€: Use-package
在 Emacs ä¸, 当我们è¦å¼•入一个包时, 通常会使用以下代ç :
(require 'package-name)
但是当 package-name ä¸åœ¨ load-path 䏿—¶, 以上代ç 会抛出错误. 使用 Use-package å¯ä»¥é¿å…:
(use-package package-name)
以上代ç 展开的结果如下:
(if
(not
(require 'package-name nil 't))
(ignore
(message
(format "Cannot load %s" 'package-name))))
å¯ä»¥çœ‹åˆ°, Use-package 使用 ignore æ¥é¿å…抛出错误, è¿™æ ·å½“æŸä¸ªåŒ…ä¸å˜åœ¨æ—¶, eamcs 也能够æ£å¸¸å¯åЍ.
当我们引入æŸä¸ªåŒ…æ—¶, 有å¯èƒ½éœ€è¦å®šä¹‰ä¸€äº›ä¸Žè¿™ä¸ªåŒ…相关的å˜é‡, 使用 Use-package 实 现这个需求如下:
(use-package package-name
:init
(setq my-var1 "xxx")
:config
(progn
(setq my-var2 "xxx")
(setq my-var3 "xxx")
)
)
在上例ä¸, init åŽçš„代ç 在包的 require 之剿‰§è¡Œ, 如果这段代ç 出错则跳过包的 require.
config åŽçš„代ç 在包的 require ä¹‹åŽæ‰§è¡Œ.
init 与 config 之åŽåªèƒ½æŽ¥å•个表达å¼è¯å¥, å¦‚æžœéœ€è¦æ‰§è¡Œå¤šä¸ªè¯å¥, å¯ä»¥ç”¨ progn .
使用 require 时会引入这个包, ä½†æ˜¯å½“ä½ çš„åŒ…å¾ˆå¤šæ—¶ä¼šå½±å“å¯åŠ¨é€Ÿåº¦. 而使用 autoload 则å¯ä»¥åœ¨çœŸæ£éœ€è¦è¿™ä¸ªåŒ…æ—¶å† require, æé«˜å¯åŠ¨é€Ÿåº¦, é¿å…æ— è°“çš„ require.
使用 Use-package å¯ä»¥è½»æ¾çš„实现这个功能:
(use-package package-name
:commands
(global-company-mode)
:defer t
)
使用 commands å¯ä»¥è®© package å»¶è¿ŸåŠ è½½, 如以上代ç ä¼šé¦–å…ˆåˆ¤æ– package çš„ç¬¦å·æ˜¯å¦ å˜åœ¨, 如果å˜åœ¨åˆ™åœ¨ package-name çš„è·¯å¾„ä¸‹åŠ è½½. defer 也å¯ä»¥è®© package-name è¿›è¡Œå»¶è¿ŸåŠ è½½.
在之å‰çš„代ç ä¸, 如果我们需è¦ç»‘定一个键, 需è¦ä½¿ç”¨ global-key-bind 或 define-key 实现, 而使用*Use-package* 实现更简å•:
(use-package color-moccur
:commands (isearch-moccur isearch-all)
:bind (("M-s O" . moccur)
:map isearch-mode-map
("M-o" . isearch-moccur)
("M-O" . isearch-moccur-all))
:init
(setq isearch-lazy-highlight t)
:config
(use-package moccur-edit))
- Use-package 能让相关的é…置更为集ä¸, é¿å…é…置分散带æ¥çš„维护困难
- Use-package 有完善的错误处ç†, 使é…ç½®ä»£ç æ›´ä¸ºå¥å£®
- Spacemacs 也大é‡ä½¿ç”¨äº† Use-package
视频地å€å¦‚下:
内容概è¦:
- 给出 Cask å’Œ Use-package 的简å•示例
- è¯¦ç»†ä»‹ç» Company-mode 的工作原ç†, å„ç§ backend åŠå…¶ç”¨æ³•
扩展阅读:
有些时候我们将一个 Package å‡çº§åˆ°æœ€æ–°çš„版本(例如 github 上最新的 commit), 而该版本å¯èƒ½ä¼šå˜åœ¨ä¸€äº› BUG, 这就会导致我们的é…ç½®ä¸èƒ½ä½¿ç”¨.
如果我们使用 stable 版本的 Package(例如使用 github 上最新的 release), å°±å¯ä»¥å°½é‡åœ°å‡å°‘å› ä¸ºå‡çº§åŒ…之åŽçš„ BUG 导致é…ç½®ä¸å¯ç”¨çš„æƒ…况.
å¦ä¸€ç§è§£å†³æ–¹å¼æ˜¯ä½¿ç”¨ Cask 进行包管ç†, 举例如下:
é¦–å…ˆæˆ‘ä»¬æ·»åŠ ä¸€ä¸ªåŒ…, 例如我们编辑 Cask 文件, æ·»åŠ monokai-theme :
(depends-on "monokai-theme"
:git "https://github.com/oneKelvinSmith/monokai-emacs/releases"
:ref "02c5f5d")
ç„¶åŽå¯åЍ emacs, 但是出现了 BUG. 这时我们å¯ä»¥ç›´æŽ¥å°† ref 的值修改为最新的 commit, Cask å³ä¼šæ›´æ–°è¿™ä¸ªåŒ…, 而ä¸ç”¨ç‰å¾… melpa 对包进行更新.
如果我们å¯ç”¨ exec-path-from-shell , 在 emacs å¯åŠ¨æ—¶å¯èƒ½ä¼šæç¤º PATH å˜é‡é‡å¤å®šä¹‰, 解决方案如下:
(use-package exec-path-from-shell
:ensure t
:if (and (eq system-type 'darwin) (display-graphic-p))
:config
(progn
(when (string-match-p "/zsh$" (getenv "SHELL"))
;; Use a non-interactive login shell. A login shell, because my
;; environment variables are mostly set in `.zprofile'.
(setq exec-path-from-shell-arguments '("-l")))
(exec-path-from-shell-initialize)
)
)
;; (use-package monokai-theme
;; :ensure t)
å…¶ä¸ if åå¥å¯ä»¥ç¡®å®šå¯ç”¨ Package çš„æ¡ä»¶, 在 config åå¥ä¸å‘ exec-path-from-shell-arguments å³å¯æ¶ˆé™¤è¿™ä¸ªè¦å‘Š.
ensure å奿¥ç¡®ä¿ Package 被安装. 如果è¦ä½¿ç”¨ stable 版, åˆ™æ·»åŠ ä»¥ä¸‹åå¥:
:pin melpa-stable
Company-mode 需è¦é…åˆåŽç«¯ä½¿ç”¨, 所有的 backend 都ä¿å˜åœ¨ company-backends 这个å˜é‡ä¸, 例如在我的环境ä¸è¯¥å˜é‡å€¼å¦‚下:
(company-capf
(company-dabbrev-code company-gtags company-etags company-keywords)
company-files
company-dabbrev
)
*company-backends*å˜é‡çš„值是一个列表, å…¶ä¸çš„æ¯ä¸€é¡¹éƒ½æ˜¯ä¸€ä¸ªåŽç«¯æˆ– Group Backend.
Company-mode ä¼šä¾æ¬¡è°ƒç”¨è¯¥å˜é‡ä¸çš„ backend, 并判æ–该 backend 是å¦åˆé€‚å½“å‰ Buffer, 直到找到一个åˆé€‚的补全åŽç«¯.
在进行补全项选择的时候, 我们也å¯ä»¥åœ¨ mode-line ä¸çœ‹åˆ°æ˜¯ä½¿ç”¨çš„哪一个åŽç«¯.
- company-dabbrev: 将当剿‰“开的所有 buffer ä¸çš„关键å—作为补全显示(默认ä¸ä½¿ç”¨ scratch buffer).
- company-files: 补全路径.
如果在补全过程ä¸å–消了补全, 也å¯ä»¥ä½¿ç”¨å‘½ä»¤å†æ¬¡å¼€å¯è¡¥å…¨. 例如 company-files 补全方å¼å°±å¯ä»¥ä½¿ç”¨ company-files 函数开å¯.
在输入英文时å¯ä»¥ä½¿ç”¨ company-ispell 进行输入æç¤º.
有时在编写 Python 代ç 的时候补全ä¸èƒ½å·¥ä½œ, 这时我们å¯ä»¥å…ˆæŸ¥çœ‹ company-backends 的值, 查看是å¦éœ€è¦å®‰è£… company-anaconda 用于补全.
在 Mac 系统ä¸, 如果 anaconda-mode 的安装过程出现错误, å¯ä»¥å‚照以下解决方案: Mac 上é¢ç¼–辑 python 的时候安装 anaconda-mode 出错
ç„¶åŽç¡®ä¿åœ¨ company-backends 䏿œ‰ company-anaconda 这个åŽç«¯å³å¯. å¯ä»¥ä½¿ç”¨å¦‚下代ç :
(add-hook 'python-mode-hook
(lambda ()
(set (make-local-variable 'company-backends) '(company-anaconda))))
以上代ç 在 python-mode 被激活时设置 company-backends çš„å˜é‡å€¼ä¸º (company-anaconda), 则在编辑 python ä»£ç æ—¶å°±å¯ä»¥ä½¿ç”¨ anaconda-mode 进行补全.
在 emacs 䏿œ‰ä¸¤ç§è¡¥å…¨æ–¹å¼:
- 如 company-files ç‰, æ ¹æ®å…³é”®å—ç‰è¿›è¡Œè¡¥å…¨, åªéœ€è¦ emacs 自己进行一些处ç†å³å¯å¾—到补全数æ®;
- 如 company-anaconda ç‰, 需è¦ä½¿ç”¨å®¢æˆ·ç«¯-æœåŠ¡ç«¯æ¨¡å¼, 补全åŽç«¯éœ€è¦æœåŠ¡ç«¯çš„é…åˆæ‰èƒ½å¾—到补全数æ®.
在进行编程时, 一般使用第二ç§è¡¥å…¨åŽç«¯, 例如 编写 python 代ç 使用 company-anaconda, 编写 C/C++代ç 使用 company-ycmd, 编写 javascript 代ç 使用 company-tern.
上述示例代ç å¼€å¯ company-anaconda 时有一个缺点, 比如当我们在 python 的注释时没法使用补全, å› ä¸ºè¡¥å…¨åŽç«¯åªæœ‰ company-anaconda, 在注释时ä¸å·¥ä½œ. 我们å¯ä»¥å°† dabbrev åŠ å…¥åŽç«¯åˆ—表:
(add-hook 'python-mode-hook
(lambda ()
(set (make-local-variable 'company-backends) '(company-anaconda company-dabbrev))))
当 company-anaconda ä¸åˆé€‚时使用 company-dabbrev 进行补全, å³å¯æ»¡è¶³ä¸Šè¿°éœ€æ±‚.
company-dabbrev-code: 类似于 company-dabbrev, 但是 dabbrev 对代ç 和注释都进行补全, dabbrev-code åªè¡¥å…¨ä»£ç .
å‡è®¾æˆ‘们的é…置代ç 如下:
(add-hook 'python-mode-hook
(lambda ()
(set (make-local-variable 'company-backends) '((company-anaconda company-dabbrev-code)
company-dabbrev)))
)
如果我们在注释ä¸å‡ºçŽ°äº† xxx 这个å—符串, 在编写 python ä»£ç æ—¶ xxx ä¸ä¼šå‡ºçŽ°åœ¨è¡¥å…¨é€‰é¡¹ä¸. å› ä¸ºåœ¨æ¤æ—¶ä¼šå…ˆåŒ¹é…到 company-anaconda, å¹¶ä¸ä¼šè¿›å…¥ company-dabbrev. è€Œå› ä¸º company-anaconda 是一个 Group Backend, 所以 company-dabbrev-code 的补全数æ®ä¼šå‡ºçŽ°åœ¨è¡¥å…¨åˆ—è¡¨ä¸.
å› ä¸ºè§†é¢‘æ—¶é—´å…³ç³», 大家å¯ä»¥åŽ»é˜…è¯»ä»¥ä¸‹æ–‡ç« :
Writing the Simplest Emacs company-mode Backend
实现方å¼ç®€å•介ç»å¦‚下:
- 定义一个补全数æ®åˆ—表
- 定义一个补全函数, 返回对应输入的补全数æ®
更多的内容å¯ä»¥æŸ¥çœ‹è¯¥æ–‡æ¡£, åŒæ—¶åœ¨ç½‘页å³ä¾§çš„é“¾æŽ¥ä¸æœ‰æ›´å¤šçš„详细内容.
视频地å€å¦‚下:
ä»Žä»Šå¤©çš„å†…å®¹å¼€å§‹ä»‹ç» Spacemacs. 地å€: Spacemacs
今天的内容包括:
- 如何安装 Spacemacs
- 一些简å•çš„é…ç½®, ä»¥åŠ package 管ç†
- 管ç†è‡ªå·±çš„é…ç½®
安装 Spacemacs éžå¸¸ç®€å•, åªéœ€è¦å°† github 上的仓库克隆å³å¯, 峿‰§è¡Œä»¥ä¸‹å‘½ä»¤(如有必è¦å¯ä»¥å…ˆå¤‡ä»½ä»¥å‰çš„é…ç½®):
cd ~
mv .emacs.d .emacs.d.bak
mv .emacs .emacs.bak
git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d
在克隆完æˆåŽç›´æŽ¥è¿è¡Œ Emacs. 在第一次使用 Spacemacs 时需è¦ä¸‹è½½ä¸€äº› Package, ç„¶åŽåœ¨ Bootstrap 完æˆä¹‹åŽä½ 需è¦è¿›è¡Œå¦‚下一些é…ç½®:
- 使用哪ç§ç¼–辑方å¼, 包括 vim æ–¹å¼(默认) ä»¥åŠ emacs æ–¹å¼.
- ä½¿ç”¨å“ªç§ Spacemacs distribution. åŒ…æ‹¬æ ‡å‡†ç‰ˆ(默认)以åŠåŸºç¡€ç‰ˆ. åŒºåˆ«åœ¨äºŽæ ‡å‡†ç‰ˆåŒ…å«éžå¸¸å¤šçš„功能, 而基础版åªåŒ…嫿 ¸å¿ƒåŠŸèƒ½.
在完æˆä»¥ä¸Šä¸¤ä¸ªé…置之åŽ, 就会在 HOME 目录生æˆä¸€ä¸ª ~/.spacemacs é…置文件. ç„¶åŽ Spacemacs 会进行进一æ¥çš„åˆå§‹åŒ–, 下载更多的需è¦çš„ Package. å¦‚æžœä½ éœ€è¦ä½¿ç”¨ emacs-china çš„é…ç½®æº, æ¤æ—¶å¯ä»¥ç»ˆæ¢ emacs, ç„¶åŽåœ¨~/.spacemacs ä¸çš„ dotspacemacs/user-init 函数ä¸åР入以䏋代ç :
(setq configuration-layer--elpa-archives
'(("melpa-cn" . "http://elpa.zilongshanren.com/melpa/")
("org-cn" . "http://elpa.zilongshanren.com/org/")
("gnu-cn" . "http://elpa.zilongshanren.com/gnu/")))
釿–°å¯åЍ emacs, ç‰å¾… Spacemacs 完æˆå®‰è£…å³å¯.
å¦‚æžœä½ éœ€è¦æ›´æ–¹ä¾¿çš„管ç†ä½ 自己的é…ç½®, å¯ä»¥åˆ›å»º ~/.spacemacs.d 目录, ç„¶åŽå°† ~/.spacemacs 文件移动到该目录ä¸å¹¶é‡å‘½å为 init.el.
在 Spacemacs ä¸çš„æ“ä½œæ–¹å¼å¦‚下:
- 按下 SPC f j 打开 dired 目录
- 按下按键 + , 创建 ~/.spacemacs.d 目录
- å°†å…‰æ ‡ç§»åŠ¨åˆ° .spacemacs 文件上, 按下 R, 将该文件移动到 .spacemacs.d 目录ä¸
- 进入 .spacemacs.d 目录, å°†å…‰æ ‡ç§»åŠ¨åˆ° .spacemacs 文件上, 按下 R, 将该文件é‡å‘½å为 init.el
- 按下 qq 退出 dired
ç„¶åŽå¯åЍ emacs å³å¯.
ä½¿ç”¨è¿™ç§æ–¹å¼ç®¡ç†é…ç½®, ä½ å¯ä»¥å°†è‡ªå·±çš„é…置集ä¸åˆ° ~/.spacemacs.d 目录ä¸, 更容易进行统一管ç†. ä½ ä¹Ÿå¯ä»¥å°†è‡ªå·±çš„é…ç½® push 到 github 上.
åœ¨å®‰è£…å®Œæˆ Spacemacs 之åŽ, 按下 SPC f e d 打开 ~/.spacemacs 文件, 修改 dotspacemacs-configuration-layers å˜é‡çš„值, å°† auto-completion, better-defaults, emacs-lisp, git, markdown, org, spell-checking, syntax-checking ç‰ layer åŠ å…¥åˆ—è¡¨.
ç„¶åŽé€€å‡º emacs å†é‡å¯, 或者按下 SPC f e R 安装需è¦çš„ package.
在 dotspacemacs/init 函数ä¸, å°† dotspacemacs-fullscreen-at-startup å˜é‡è®¾ç½®ä¸º t å³å¯. 代ç 如下:
;; If non nil the frame is maximized when Emacs starts up.
;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil.
;; (default nil) (Emacs 24.4+ only)
dotspacemacs-maximized-at-startup t
å°† ivy åŠ å…¥ dotspacemacs-configuration-layers 列表ä¸. 按下 CTRL s 使用 swiper å¯ä»¥è¿›è¡Œæœç´¢.
按下 SPC h SPC å³ä¼šå¼¹å‡ºä¸€ä¸ªä¿¡æ¯çª—å£, å¯ä»¥ä»Žçª—å£ä¸é€‰æ‹©å…·ä½“çš„ layer 或者其他信æ¯è¿›è¡ŒæŸ¥çœ‹.
åªéœ€è¦å°†éœ€è¦åˆ 除的 package åç§°åŠ å…¥åˆ° dotspacemacs-excluded-packages å˜é‡ä¸, 在下一次å¯åЍ emacs æ—¶å³ä¼šåˆ 除该 package. 示例代ç 如下:
;; A list of packages and/or extensions that will not be install and loaded.
dotspacemacs-excluded-packages '(vi-tilde-fringe)
在 Spacemacs ä¸å®‰è£… package 时最好ä¸è¦ä½¿ç”¨ package-install, å› ä¸ºè¿™æ ·å®‰è£…çš„ package 会在下一次å¯åŠ¨æ—¶è¢«åˆ é™¤.
Spacemacs æä¾›äº†ä¸€ä¸ªæ–¹å¼, ä½ åªéœ€å°†éœ€è¦å®‰è£…çš„ package åŠ å…¥åˆ° dotspacemacs-additional-package å˜é‡ä¸å³å¯, 示例代ç 如下:
;; List of additional packages that will be installed without being
;; wrapped in a layer. If you need some configuration for these
;; packages, then consider creating a layer. You can also put the
;; configuration in `dotspacemacs/user-config'.
dotspacemacs-additional-packages '(youdao-dictionary)
如果使用 customize-group 对é…置进行了修改, ä½ å¯ä»¥ä»¥ä¸‹ä»£ç 将生æˆçš„ custom.el é…置文件纳入 ~/.spacemacs.d 目录ä¸è¿›è¡Œç»Ÿä¸€ç®¡ç†:
(setq custom-file (expand-file-name "custom.el" dotspacemacs-directory))
(load custom-file 'no-error 'no-message)
åªéœ€ä¿®æ”¹ dotspacemacs-themes å˜é‡çš„值, å°†ä¸»é¢˜åŠ å…¥åˆ—è¡¨å³å¯. 在列表ä¸é å‰çš„主题会优先使用. 示例代ç 如下:
;; List of themes, the first of the list is loaded when spacemacs starts.
;; Press <SPC> T n to cycle to the next theme in the list (works great
;; with 2 themes variants, one dark and one light)
dotspacemacs-themes '(
monokai
;; spacemacs-dark
;; spacemacs-light
;; solarized-light
solarized-dark
;; leuven
;; monokai
;; zenburn
)
视频地å€å¦‚下:
主è¦å†…容:
- 如何更新 Spacemacs, åŒæ¥å®˜æ–¹ develop åˆ†æ”¯åŠæ³¨æ„事项
- Layer çš„ variables å˜é‡åŠä½¿ç”¨æ–¹æ³•
- 如何创建自己的 Layer
- 如何定制 modeline
- evlified state
å¯ä»¥é€šè¿‡ git çš„æ–¹å¼æ¥æ›´æ–°ä»£ç , å‡è®¾æˆ‘们使用的是 develop 分支:
git checkout develop
git fetch upstream
git merge upstream/develop
一般æ¥è¯´, å¦‚æžœä½ ä¸ç†Ÿæ‚‰ emacs å¹¶ä¸”ä½ çš„ Spacemacs é…置能够æ£å¸¸å·¥ä½œ, 则ä¸éœ€è¦é¢‘ç¹çš„æ›´æ–°ä»£ç , 以é¿å…更新之åŽé…ç½®ä¸èƒ½ä½¿ç”¨.
æ¯ä¸€ä¸ª layer 都å¯ä»¥é…置一些å˜é‡, å¯ä»¥é€šè¿‡ SPC h SPC ç„¶åŽè¾“å…¥ layer åç§°, 点击对应的选项å³å¯æ‰“开该 layer çš„ README.org 文件. ç„¶åŽæŒ‰ä¸‹ SPC f j 进入 dired 模å¼, 选择 config.el 文件打开, 该文件ä¸å³å®šä¹‰äº†è¯¥ layer çš„å˜é‡.
例如 better-default layer çš„å˜é‡å¦‚下:
(defvar better-defaults-move-to-beginning-of-code-first t
"when t, first stroke of C-a will move the cursor to the beginning of code.
When nil, first stroke will go to the beginning of line.
Subsequent strokes will toggle between beginning of line and beginning of code.")
(defvar better-defaults-move-to-end-of-code-first nil
"when t, first stroke of C-e will move the cursor to the end of code (before comments).
When nil, first stroke will go to the end of line (after comments).
Subsequent strokes will toggle between end of line and end of code.")
è¦é…置使用这些å˜é‡, å¯ä»¥åœ¨å¯ç”¨ layer 时使用如下的代ç :
(better-defaults :variables
better-defaults-move-to-end-of-code-first t)
在 emacs25.1 ä¸, 该版本的 modeline 和以å‰ç‰ˆæœ¬ä¸åŒ, å¯ä»¥é€šè¿‡å¦‚下方å¼å°† modeline 修改为以å‰çš„æ˜¾ç¤ºå½¢çж:
在 dotspacemacs/user-config ä¸åР入如䏋代ç :
(setq ns-use-srgb-colorspace nil)
å‡è®¾æˆ‘们需è¦åˆ›å»ºä¸€ä¸ª layer, åå« zilongshanren, 并且在 layer 下包å«ä¸€ä¸ªåå« youdao-dictionary çš„ package.
首先利用 spacemacs æä¾›çš„函数创建 layer. 按下 M-x 并且输入 configuration-layer/create-layer, ç„¶åŽé€‰æ‹©è·¯å¾„ ~/.spacemacs.d, 确定创建 README, ç„¶åŽæˆ‘们就å¯ä»¥çœ‹åˆ° layer 创建æˆåŠŸ.
æ¯ä¸€ä¸ª layer 的结构如下:
[layer_name] |__ [local] | |__ [package 1] | | ... | |__ [package n] |-- layers.el |__ packages.el |__ funcs.el |__ config.el |__ keybindings.el [] = directory
峿¯ä¸€ä¸ª layer 目录下都å¯ä»¥åŒ…å« layers.el, packages.el ç‰æ–‡ä»¶, 以åŠä¸€ä¸ªåå« local 的目录.
æ¯ä¸€ä¸ªæ–‡ä»¶çš„内容æè¿°å¦‚下:
文件å | 用处 |
---|---|
layers.el | 申明一些é¢å¤–çš„ layer ä¾èµ– |
packages.el | 一些 layer 使用到的 package 以åŠç›¸å…³é…置函数 |
funcs.el | 定义一些 layer 层次的函数, å³å…¨å±€å‡½æ•° |
config.el | layer çš„é…ç½®, æ¤å¤„定义的é…ç½®å¯ä»¥åœ¨ .spacemacs ä¸ç”³æ˜Ž layer 时进行é…ç½®, 也å¯ä»¥å®šä¹‰ emacs 的默认é…ç½® |
keybindings.el | å¿«æ·é”®é…ç½® |
现在我们å¯ä»¥æŠŠ youdao-dictionary åŠ å…¥åˆ° layer ä¸, 编辑 packages.el:
;; æ·»åŠ package
(defconst zilongshanren-packages
'(youdao-dictionary)
)
;; åˆå§‹åŒ– package
;; å¯ä»¥ä½¿ç”¨ , d m å¿«æ·é”®, ç„¶åŽæŒ‰ä¸‹ e 展开å®
(defun zilongshanren/init-youdao-dictionary ()
(use-package youdao-dictionary
:defer t
:init
(spacemacs/set-leader-keys "oy" 'youdao-dictionary-search-at-point+)
)
)
编辑 config.el 文件:
;; å¼€å¯è¡Œå·æ˜¾ç¤º
(global-linum-mode t)
;; 定义快æ·é”®
(global-set-key (kbd "M-s o") 'occur-dwim)
;; å°† occur çš„ buffer ä¸çš„å…‰æ ‡ç§»åŠ¨æ–¹å¼ä¿®æ”¹ä¸º HJKL
(evilified-state-evilify-map occur-mode-map
:mode occur-mode)
编辑 keybindings.el 文件:
;; dwin = do what i mean.
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(let ((sym (thing-at-point 'symbol)))
(when (stringp sym)
(regexp-quote sym))))
regexp-history)
(call-interactively 'occur))
ç„¶åŽå°† zilongshanren åŠ åˆ° dotspacemacs-configuration-layers å˜é‡ä¸, å³å¯è®© layer é…置生效.
spacemacs 的文档ä¿å˜åœ¨ doc 目录下, åŒ…å«æœ‰ CONVENTIONS.org, DOCUMENTATION.org ç‰æ–‡æ¡£æ–‡ä»¶, 建议大家多多阅读.
视频地å€å¦‚下:
主è¦å†…容:
- ä¿®å¤ä¸Šä¸€æœŸè§†é¢‘ä¸ occur-mode å¯åŠ¨çš„é—®é¢˜
- ä¿®å¤ ivy0.8 导致的问题, åŒæ—¶ç®€å•探讨了一下今åŽå¦‚何é¿å…和处ç†ç±»ä¼¼çš„问题
- ä»‹ç» post-init å’Œ pre-init 的用法, 介ç»äº†å¦‚何定制 spacemacs çš„ company-mode
- ä»‹ç» layers.el 文件, 演示该文件的作用
- ä»‹ç» layer çš„ package çš„ location å˜é‡, 演示了如何从 github 获å–并安装 package 的方法
在之å‰çš„é…置代ç ä¸, 如果我们å¯åЍ emacs 会出现以下错误:
Symbol's function definition is void: evilified-state-evilify-map
è¿™æ˜¯å› ä¸ºè¿™ä¸ªç¬¦å·åœ¨ config.el ä¸ä½¿ç”¨çš„æ—¶å€™è¿˜æ˜¯ç©ºçš„, 我们å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼ä¿®å¤, 编辑 config.el 文件, 将以下代ç 移动到 dotspacemacs/user-config 函数ä¸:
(evilified-state-evilify-map occur-mode-map
:mode occur-mode)
在 ivy å‡çº§åˆ°0.8版本时, 对其ä¸ä¸€ä¸ªAPI的返回值进行了修改:
(let (res)
(ivy-with
'(ivy-read "test: "
'(("one" . 1) ("three" . 3))
:action (lambda (x) (setq res x)))
"t C-m")
res)
;; =>
;; ("three" . 3)
在之å‰çš„版本ä¸, 这个函数的返回值是 3, 在0.8版本ä¸è¢«ä¿®æ”¹ä¸ºäº†ä¸€ä¸ªåˆ—表. 如果è¦ä¿®å¤è¿™ä¸ªé—®é¢˜, 我们需è¦åœ¨ä½¿ç”¨è¿”å›žå€¼çš„æ—¶å€™åŠ ä¸Š cdr, 具体的修改å¯ä»¥æŸ¥çœ‹fix break API changes for ivy 0.8.
有一些 mode å·²ç»å®‰è£…, 例如 company-mode å·²ç»è¢« auto-completion layer 安装, 如果这时我们还想对该 mode 进行一些定制, 那么我们å¯ä»¥è¿™æ ·å¤„ç†:
- 在我们的 layer 䏿·»åŠ è¿™ä¸ªåŒ…
;; æ·»åŠ package
(defconst zilongshanren-packages
'(youdao-dictionary
company ; æ·»åŠ company package
)
)
- ç„¶åŽå®šä¹‰ä¸€ä¸ª post-init 函数
;; 定制 company-mode
(defun zilongshanren/post-init-company ()
(setq company-minimum-prefix-length 1)
)
ç„¶åŽé‡å¯ emacs å³å¯ä»¥çœ‹åˆ°å®šåˆ¶çš„æ•ˆæžœ.
对于 package 的三个函数: pre-init, init, post-init, spacemacsæ˜¯æŒ‰ç…§è¿™ä¸ªé¡ºåºæ¥ä¾æ¬¡è°ƒç”¨çš„.
在安装 package æ—¶, 我们如果åªè¾“å…¥ package çš„åå—, 那么默认是从 melpa 下载安装的. 如果我们想自定义 package 的安装地å€, 那么我们就å¯ä»¥ä½¿ç”¨ location å˜é‡.
例如我们使用一个自带的 occur package:
;; 自定义 package 安装地å€
(defconst zilongshanren-packages
'(youdao-dictionary
(occur-mode :location built-in)
)
)
;; åˆå§‹åŒ– occur mode
(defun zilongshanren/init-occur-mode ()
(evilified-state-evilify-map occur-mode-map
:mode occur-mmode)
)
例如我们从 github 安装 gulpjs package:
;; 自定义 package 安装地å€
(defconst zilongshanren-packages
'(youdao-dictionary
(occur-mode :location built-in)
(gulpjs :location (recipe :fetcher github :repo "zilongshanren/emacs-gulpjs"))
)
)
(defun zilongshanren/init-gulpjs ()
(use-package gulpjs
:init)
)
在 emacs å¯åŠ¨æ—¶å°±ä¼šä»Ž github 上下载 guiljs package 并安装到本地.
如果我们需è¦å¯¹æŸäº› layer ä¸çš„ package é…置进行大é‡çš„é‡å†™, 那么我们å¯ä»¥ç§»é™¤è¿™ä¸ª layer çš„æŸä¸ª package. 我们å¯ä»¥é€šè¿‡ layers.el æ¥å®žçŽ°è¿™ä¸€ç‚¹, 例如移除 chinese layer çš„ youdao-dictionary package:
(configuration-layer/remove-layer 'youdao-dictionary)
ç„¶åŽæˆ‘们å¯ä»¥åœ¨è‡ªå·±çš„ layer 䏿·»åŠ è¿™ä¸ª package, ç„¶åŽå¯¹å®ƒè¿›è¡Œå®šåˆ¶. åœ¨è¿™ç§æƒ…况下, spacemacs ä¸ä¼šåœ¨ chinese layer ä¸åŠ è½½ youdao-dictionary 这个 package, 而是在我们的 layer ä¸åŠ è½½è¿™ä¸ª package, 以实现对 spacemacs 内置的package 的定制.
视频地å€å¦‚下:
主è¦å†…容:
- 我的é…置和 spacemacsé…置的一些ä¸åŒç‚¹
- 文件相关æ“作
- Buffer 相关æ“作
- Dired
从今天的视频开始, 将使用 å龙山人的é…ç½® æ¥è®²è§£è§†é¢‘. 这份é…置对 spacemacs 的定制有两个ä¸åŒç‚¹:
- 没有使用官方的 modeline, 而是采用自己定制的
- 排除掉了大é‡çš„作者认为对他没有作用的 package, å› ä¸ºè¿™äº› package 确实ä¸ç»å¸¸ä½¿ç”¨, å而å¯èƒ½å¯¼è‡´ä¸€äº› BUG 或者导致 spacemacs å¯åŠ¨æˆ–ä½¿ç”¨è¿‡ç¨‹ä¸å˜æ…¢
- SPC p f
在当å‰çš„é¡¹ç›®ä¸æŸ¥æ‰¾æ–‡ä»¶, 类似于 vim ä¸çš„ Ctrl-p. 在作者的é…ç½®ä¸, 该快æ·é”®è¢«ç»‘定到了以下函数:
(defun zilongshanren/open-file-with-projectile-or-counsel-git () (interactive) (if (zilongshanren/vcs-project-root) (counsel-git) (if (projectile-project-p) (projectile-find-file) (ido-find-file))))
该函数会针对ä¸åŒçš„项目类型使用ä¸åŒçš„æŸ¥æ‰¾æ–¹å¼:
- 如果是 git 项目, 那么使用 counsel-git æ¥æŸ¥æ‰¾æ–‡ä»¶, ä¸ä½¿ç”¨ projectile çš„åŽŸå› æ˜¯ counsel-git æ›´å¿«
- 如果是 projectile 项目, å³åœ¨é¡¹ç›®çš„æ ¹ç›®å½•ä¸å˜åœ¨ .projectile 文件, 那么使用 projectile-find-file æ¥æŸ¥æ‰¾æ–‡ä»¶
- å¦åˆ™ä½¿ç”¨ ido-fine-file æ¥æŸ¥æ‰¾æ–‡ä»¶
- SPC f f
从当å‰ç›®å½•开始查找文件. 在作者的é…ç½®ä¸åŒæ—¶å¯ç”¨äº† ivy-layer å’Œ helm-layer, 默认使用的是 helm æ¥æŸ¥æ‰¾æ–‡ä»¶.
- SPC f L
使用 helm-locate æ¥åœ¨å½“å‰ç³»ç»Ÿä¸æŸ¥æ‰¾æ–‡ä»¶.
- SPC f l
查找文件并使用 literal çš„æ–¹å¼æ¥æ‰“开文件, 使用 literal æ–¹å¼æ‰“开的文件ä¸ä¼šé™„åŠ ç¼–ç ä¿¡æ¯, 例如 utf-8 ç¼–ç ä¸å¯èƒ½å˜åœ¨çš„ BOM 头信æ¯, 使用 literal 模å¼å³å¯ä»¥çœ‹åˆ° BOM头.
- SPC f h
æŸ¥æ‰¾æ–‡ä»¶å¹¶ä½¿ç”¨äºŒè¿›åˆ¶çš„æ–¹å¼æ¥æ‰“开文件, å¯ä»¥ä½¿ç”¨ C-c C-c 回到之å‰çš„æ¨¡å¼.
- SPC f o
ä½¿ç”¨å¤–éƒ¨ç¨‹åºæ‰“开文件.
- SPC f E
使用 sudo æ¥ç¼–辑文件, 当æŸäº›æ–‡ä»¶æ˜¯åªè¯»çš„æ—¶å€™å¯ä»¥é‡‡ç”¨è¿™ç§æ–¹å¼æ¥ç¼–辑文件.
- SPC f D
åˆ é™¤å½“å‰çš„æ–‡ä»¶å’Œ buffer.
- SPC f j
以当剿–‡ä»¶çš„目录打开 dired buffer.
- SPC f r
使用 ivy 打开最近文件列表.
- SPC f R
é‡å‘½å当剿–‡ä»¶.
- SPC f v
æ·»åŠ local variables, å¯ä»¥é€šè¿‡è¿™ä¸ªåŠŸèƒ½ç»™é¡¹ç›®åšä¸€äº›ç‰¹æ®Šçš„设置. 例如按下 SPC f v, ç„¶åŽé€‰æ‹© add-dir-local-variable, 选择 org-mode, å†é€‰æ‹©org-highlight-links å˜é‡, æ¤æ—¶ emacs ä¼šåœ¨å½“å‰æ–‡ä»¶çš„目录下生æˆä¸€ä¸ª .dir-locals.el 文件, 内容如下:
;;; Directory Local Variables ;;; For more information see (info "(emacs) Directory Variables") ((org-mode (org-highlight-links)))
这个文件ä¸çš„代ç 会在当å‰ç›®å½•下的所有文件 buffer ä¸ç”Ÿæ•ˆ.
- SPC f y
æ‹·è´å½“剿–‡ä»¶çš„全路径.
- SPC f a d
列出最近访问的目录, 使用命令行工具 fasd 实现.
- SPC f C d/u
将当剿–‡ä»¶çš„ç¼–ç 转æ¢ä¸º DOS/UNIX ç¼–ç .
- SPC f e d
打开 .spacemacs 或 .spacemacs.d/init.el 文件.
- SPC f e i
打开 .emacs 或 .emacs.d/init.el 文件.
- SPC f e l
打开系统ä¸å·²ç»å®‰è£…çš„ el 文件.
- SPC f c
å¤åˆ¶æ–‡ä»¶.
- SPC f b
æ‰“å¼€æ ‡ç¾.
- SPC f s/S
ä¿å˜å½“å‰ buffer 或 所有 buffer.
- SPC b .
打开 Buffer Selection Transient State, 在该模å¼ä¸‹å¯ä»¥è¿›è¡Œæ›´å¤šçš„æ“ä½œ, ç”± hydra æä¾›.
- SPC b b
切æ¢åˆ°å·²ç»æ‰“开的 buffer.
- SPC b d
å…³é—一个 buffer.
- SPC b f
在 finder 䏿‰“开当剿–‡ä»¶, åªåœ¨ Mac系统下生效.
- SPC b B/i
以类似 Dired Mode çš„å½¢å¼æ‰“å¼€ buffer 列表, 在这个列表ä¸å¯ä»¥æ‰§è¡Œå’Œ Dired Mode 类似的æ“作.
- SPC b h
进入 \*spacemacs\* buffer.
- SPC b k
使用æ£åˆ™è¡¨è¾¾å¼æ¥åˆ 除 buffer.
- SPC b N
新建一个 buffer.
- SPC b m
åˆ é™¤é™¤å½“å‰ buffer 外的所有 buffer.
- SPC b R
使用 emacs 自动备份的文件æ¢å¤æ–‡ä»¶.
- SPC b s
跳转到 scratch buffer.
- SPC b w
å…³é—/打开 buffer çš„ read-only.
- SPC b Y
å¤åˆ¶æ•´ä¸ª buffer 的内容.
- SPC b P
将剪切æ¿çš„内容粘贴到整个 buffer.
- SPC <tab>
åœ¨å½“å‰ buffer 和上一个打开的 buffer ä¸è¿›è¡Œåˆ‡æ¢.
在第四天的内容ä¸å·²ç»è®²è§£è¿‡ Dired Mode çš„æ“作, 具体å¯ä»¥æŸ¥çœ‹ Dired Mode.
视频地å€å¦‚下:
主è¦å†…容:
- Layout 相关æ“作
- Window 相关æ“作
- project 相关æ“作
- SPC l L
åŠ è½½ layout 文件
- SPC l l
在 layout 之间切æ¢
- SPC l s
å°† layout ä¿å˜åˆ°æ–‡ä»¶
- SPC l <tab>
åœ¨å½“å‰ layout 和上一个 layout 之间切æ¢
- SPC l o
é…ç½® layout
- SPC l R
é‡å‘½å layout
- SPC l ?
显示更多的与 layout 相关的命令
- SPC w -
上下拆分窗å£
- SPC w /
左峿‹†åˆ†çª—å£
- SPC w .
显示更多的与 window micro state 的相关的命令
- SPC w 2/3
左峿˜¾ç¤º 2/3 个窗å£
- SPC w =
将窗å£å‡ç‰åˆ†
- SPC w b
切æ¢åˆ° minibuffer
- SPC w d
åˆ é™¤å½“å‰çª—å£
- SPC w h/j/k/l
å‘ å·¦/下/上/å³ ç§»åŠ¨çª—å£
- SPC w m
最大化显示当å‰çª—å£
- SPC W H/J/K/L
将当å‰çª—å£å‘ å·¦/下/上/å³ ç§»åŠ¨
- SPC w u/U
å–æ¶ˆ/é‡ç½®ä¸Šæ¬¡æ“作
- SPC w o
切æ¢åˆ°å…¶ä»– frame
- SPC w F
创建一个新的 frame
- SPC w 1/2/3/4
切æ¢åˆ°å¯¹åº”的编å·çš„窗å£
- SPC w w
便¬¡åˆ‡æ¢åˆ°å…¶ä»–窗å£
- SPC w W
ä½¿ç”¨å—æ¯æ ‡è¯†éœ€è¦è·³è½¬çš„窗å£, å¹¶æŒ‰ä¸‹å—æ¯è¿›è¡Œè·³è½¬
- SPC t g
将当剿˜¾ç¤ºçš„窗å£ä¸Žå…¶ä»–窗å£è¿›è¡Œé»„金分割显示
- SPC t -
å¼€å¯/å…³é— å°†å…‰æ ‡å§‹ç»ˆæ˜¾ç¤ºåœ¨ä¸å¿ƒè¡Œ
- SPC p f
åœ¨å½“å‰ project 䏿Ÿ¥æ‰¾å¹¶æ‰“开文件
- SPC p b
åœ¨å½“å‰ project 䏿Ÿ¥æ‰¾æ‰“开的 buffer
- SPC p p
切æ¢åˆ°å…¶ä»–çš„ project
- SPC p l
切æ¢åˆ°å…¶ä»–çš„ project 并创建一个新的 layout
- find-file-in-project
这是一个æ’ä»¶, 支æŒå…¨å¹³å°. ç›®å‰ç»‘定在 SUPER f å¿«æ·é”®ä¸Š.
对 Spacemacs ä¸çš„å¿«æ·é”®æ“作就介ç»åˆ°è¿™é‡Œ, 更多的快æ·é”®ä»‹ç»å¯ä»¥åˆ° Spacemacs ABC 去查看.
视频地å€å¦‚下:
主è¦å†…容:
这期视频主è¦ä»‹ç» ctags å’Œ company-mode 的使用.
ctags 是一个开æºçš„, å¯ä»¥æ–¹ä¾¿çš„对大型代ç 库进行索引的软件, 在使用 ctags ç”Ÿæˆ tag 之åŽå°±å¯ä»¥éžå¸¸æ–¹ä¾¿çš„在这些 tag ä¸è¿›è¡Œè·³è½¬. å› ä¸ºæœ‰äº›ç¼–ç¨‹è¯è¨€, 例如 javascript 或者 lua, 它们ä¸èƒ½è¿›è¡Œç²¾ç¡®çš„è¯ä¹‰è¡¥å…¨, 在有 ctags 进行索引补全的情况下也å¯ä»¥æ–¹ä¾¿ç¼–写代ç .
在之å‰ä¹Ÿä»‹ç»è¿‡ term-mode, 也å¯ä»¥åšåˆ°ä¸€äº›è¯ä¹‰è¡¥å…¨. 但是它也有一些缺点:
- é…置方å¼å¤æ‚, 对于比较大的项目的é…置比较有难度
- 有些时候ä¸èƒ½å¾—到想è¦çš„补全结果
之å‰ä½œè€…使用 YCMD æ¥å¯¹ C/C++ 代ç 进行补全, 但是它ä¸å¤ªç¨³å®š, 现在已ç»åˆ‡æ¢ä¸º ctags æ¥è¿›è¡Œè¡¥å…¨, 对于调试和 profile 会使用 IDE 进行æ“作.
首先新建一个 testJs-ctags 目录, ç„¶åŽåœ¨è¯¥ç›®å½•下新建 a.js ä»¥åŠ b.js 两个文件:
mkdir testJs-ctags
cd testJs-ctags
touch a.js
touch b.js
ç„¶åŽç¼–辑 a.js 的内容如下:
var func1 = function () {
console.log("func1");
};
var func2 = function () {
};
ç„¶åŽåœ¨ b.js ä¸çš„补全ä¸å¯ä»¥æ˜¾ç¤ºå¤„ func1 å’Œ func2 的补全æç¤ºçš„. 为了更方便的讲解之åŽçš„内容, 我们å¯ä»¥æŸ¥çœ‹ä½¿ç”¨çš„补全的åŽç«¯: 输入 M-x, diminish-undo, 选择 company-mode, è¿™æ ·åœ¨ modeline å°±å¯ä»¥çœ‹åˆ° company-mode 的具体信æ¯.
冿¬¡è¾“å…¥ fun ç‰å¾…弹出补全æç¤º, 在补全选项ä¸ä¸Šä¸‹ç§»åЍ, å¯ä»¥çœ‹åˆ°ä½¿ç”¨çš„补全åŽç«¯åŒ…括 dabbrev-code å’Œ etags ç‰, å¦‚æžœæˆ‘ä»¬å…³é— a.js çš„ buffer, å°±ä¸ä¼šå‡ºçް func1 å’Œ func2 的补全选项.
在之å‰çš„æ“ä½œä¸, æˆ‘ä»¬å¹¶æ²¡æœ‰ç”Ÿæˆ ctags, 为什么也能使用 ctags 补全呢? 我们å¯ä»¥ä½¿ç”¨ SPC h d v, ç„¶åŽè¾“出 tags-table-list æ¥æŸ¥çœ‹è¯¥å˜é‡çš„值, 当å‰çš„值是指å‘作者 cocos目录下的 TAGS 文件. ä½¿ç”¨ä»¥ä¸‹ä»£ç æ¸…空该值:
(setq-default tags-table-list nil)
ç„¶åŽå†æ¬¡å°è¯•补全, 这时就ä¸ä¼šä½¿ç”¨ ctags 补全了.
é‚£ä¹ˆå¦‚ä½•ç”Ÿæˆ ctags 补全的文件呢? 使用以下命令å³å¯:
cd testJs-ctags
ctags -e a.js
# 针对目录
# ctags -eR foldername
company-etags 在进行补全的时候, 会从å˜é‡ tags-table-list 值的文件列表ä¸åŽ»æŸ¥æ‰¾ tags, 而且 tags 是ä¸åŒºåˆ†è¯è¨€çš„.
å¦‚æžœéœ€è¦æ‰‹åŠ¨åŠ è½½ TAGS 文件, 那么å¯ä»¥è°ƒç”¨ visit-tags-table 命令. 而在打开一个文件时, ctags 会从文件所在的目录进行查找, ä¸€ç›´åˆ°æ ¹ç›®å½•, åŠ è½½æ‰€æ‰¾åˆ°çš„ TAGS 文件.
在使用 ctags 的过程ä¸, 如果文件的内容被改å˜, 那么需è¦é‡æ–°ç”Ÿæˆ TAGS 文件, 以便 ctags 的补全结果更精确. 作者实现了一个函数æ¥è‡ªåŠ¨åŠ è½½å¿…é¡»çš„ TAGS 文件:
(defun my-setup-develop-environment ()
(interactive)
(when (my-project-name-contains-substring "guanghui")
(cond
((my-project-name-contains-substring "cocos2d-x")
;; C++ project don't need html tags
(setq tags-table-list (list (my-create-tags-if-needed "~/cocos2d-x/cocos"))))
((my-project-name-contains-substring "Github/fireball")
(message "load tags for fireball engine repo...")
;; html project donot need C++ tags
(setq tags-table-list (list (my-create-tags-if-needed "~/Github/fireball/engine/cocos2d")))))))
有å¦å¤–一个工具函数, 当ä¿å˜æ–‡ä»¶æ—¶ä¼šè‡ªåŠ¨çš„é‡æ–°ç”Ÿæˆ TAGS:
(defun my-auto-update-tags-when-save (prefix)
(interactive "P")
(cond
((not my-tags-updated-time)
(setq my-tags-updated-time (current-time)))
((and (not prefix)
(< (- (float-time (current-time)) (float-time my-tags-updated-time)) 300))
;; < 300 seconds
(message "no need to update the tags")
)
(t
(setq my-tags-updated-time (current-time))
(my-update-tags)
(message "updated tags after %d seconds." (- (float-time (current-time)) (float-time my-tags-updated-time))))))
å¯ä»¥å°† my-auto-udpate-tags-when-save å‡½æ•°åŠ å…¥ after-save-hook ä¸, 或者绑定到快æ·é”®ä¸Š.
ctags 自身也有一个é…置文件, å¯ä»¥åœ¨è¯¥æ–‡ä»¶ä¸å®šä¹‰è§„åˆ™æ¥æ›´å¥½çš„ç”Ÿæˆ TAGS, 一个é…置文件的示例如下:
--exclude=*.svn* --exclude=*.git* --exclude=*tmp* --exclude=.#* --tag-relative=yes --recurse=yes --langdef=js --regex-js=/[ \t.]([A-Z][A-Z0-9._$]+)[ \t]*[=:][ \t]*([0-9"'\[\{]|null)/\1/n,constant/ --langdef=css --langmap=css:.css --regex-css=/^[ \t]*\.([A-Za-z0-9_-]+)/.\1/c,class,classes/
在é…置文件ä¸å¯ä»¥ä½¿ç”¨ –exclude æ¥å¿½ç•¥æ–‡ä»¶æˆ–路径, 使用 –langdef æ¥å®šä¹‰å“ªäº›æ–‡ä»¶å±žäºŽ js 文件, 使用 –regex-js æ¥å®šä¹‰ TAGS ç”Ÿæˆæ—¶çš„匹é…规则. 这些匹é…规则ä¸å¯ä»¥ä½¿ç”¨æ£åˆ™è¡¨è¾¾å¼æ¥æå–å†…å®¹ç”Ÿæˆ TAGS.
在有 TAGS 之åŽ, å¯ä»¥ä½¿ç”¨ ctags æ¥æ–¹ä¾¿çš„æµè§ˆæ–‡ä»¶å†…å®¹. 例如在æŸä¸ªå‡½æ•°å上点击 [, g], ç„¶åŽé€‰æ‹© etags-select-find-tag-at-point, 这时会把所有相关的内容列出到 buffer ä¸, ç„¶åŽå¯ä»¥é€‰æ‹©æƒ³è¦è·³è½¬çš„ä½ç½®è·³è½¬è¿‡åŽ».
company-etags ä¸èƒ½å¯¹æ‰€æœ‰çš„ mode 进行补全, 例如在 org-mode ä¸é»˜è®¤æ˜¯ä¸ä½¿ç”¨ company-etags çš„. å› ä¸ºåœ¨ company-etags.el æ–‡ä»¶ä¸æœ‰å¦‚下的代ç :
(defvar company-etags-modes '(prog-mode c-mode objc-mode c++-mode java-mode
jde-mode pascal-mode perl-mode python-mode))
在该å˜é‡ä¸å®šä¹‰äº†å¯ä»¥ä½¿ç”¨ company-etags çš„ mode, å°† org-mode åŠ å…¥è¯¥å˜é‡çš„值ä¸å³å¯åœ¨ org-mode 使用 company-etags 进行补全.
ctags 支æŒä¸Šç™¾ç§è¯è¨€, å¦ä¼šä½¿ç”¨ ctags 能够æäº¤æ•ˆçއ.