分类: linux
2012-05-21 17:50:21
2.1 前面的话
开始的时候,你可能会觉得emacs不好用,有点古怪,尤其是当你发现连个粘贴只能用一堆快捷键而不能像
其它编辑器那样用鼠标右键时,心里可能会有一种被愚弄的感觉,难道这就是“神的编辑器”,难道只有“神”
才能使用嘛! 可是当你慢慢习惯之后,你会发现它作为一个编辑器,它的文字处理能力和编辑效率确实很高。
你可以随意删除或者跳过字符,词组,一句,一行一段,这在编辑的时候非常有用,而这还不是emacs最大的
卖点,它最大的优点在于具有高度的配置能力,你能像盖房子一样,搭建一个完全适合自己习惯的编辑器。
2.2 emacs简介
emacs编辑器是由richard stallman 和 guy steele于1975年合作开发的,它是在20世纪60年代末的文本编器
teco的基础上,扩展了其中的一系列命令和宏发展而成的。emacs不仅仅是一个文本编辑器,它还可以利
用lisp编程语言的优势对emacs进行定制和扩展。这也是emacs和其它编辑器的最大区别,但这种“便利”只有
lisp高手才能尽情享用。一般用户只能使用已经绑定好的命令或者由某个“高手”编写好的配置文件,但这基本
上已经够用了。如果你喜欢折腾的话也可以自己试着编写,这样当你在学emacs的同时还能学会lisp,这也算是
一剑双雕了。。
2.3基本命令
下面这些是emacs默认的绑定键。如果你学会使用lisp配置你自己的emacs,请尽量不要自己修改这些默认的
key-bindings,否则容易出错。(c对应ctrl,m对应alt)
2.3.1基本文件操作
下面这些主要涉及了文件的基本操作,包括打开,新建,保存,另存为以及退出emacs等比较常用的命令。
c-x c-f 打开/新建一个文件
c-x c-s 保存文件
c-x c-w 另存为文件
c-x c-v 关闭当前缓冲区文件并打开新文件
c-x i 在当前光标处插入文件
c-x b 新建/切换缓冲区
c-x c-b 显示缓冲区列表
c-x k 关闭当前缓冲区
c-x c-c 关闭emacs
2.3.2光标移动
这里边最方便的就是句首句尾和行首行尾,因为我的是笔记本键盘,上下左右主要是用方向键,如果要是
标准键盘的话,最好常用绑定键。
c-f 后一个字符 c-b 前一个字符
c-p 上一行 c-n 下一行
m-f 后一个单词 m-b 前一个单词
c-a 行首 c-e 行尾
c-v 向下翻一页 m-v 向上翻一页
m-< 到文件开头 m-> 到文件末尾
2.3.3文本编辑
这里面包括了复制粘贴剪切删除等常用的操作命令。注意,在这里,移除包括了剪切和删除两个概念,要
区分清楚。
m-n/c-u n 重复执行后一个命令n次
c-d 删除后一个字符 m-d 删除后一个单词
del 删除前一个字符 m-del 删除前一个单词
c-k 移除一行
c-@ 设定标志位(主要是为了粘贴剪切以及删除使用)
c-w 移除标记区域的内容(剪切)
m-w 复制标记区域的内容(复制)
c-y 召回(yank)复制/移除的区域/行(粘贴)
m-y 召回更早的内容 (在kill缓冲区内循环)
c-t 交换两个字符的位置
m-t 交换两个单词的位置
c-x c-t 交换两行的位置
m-u 使从光标位置到单词结尾处的字母变成大写
m-l 与m-u相反
m-c 使从光标位置开始的单词的首字母变为大写
2.3.4 一些重要的命令
c-g 停止当前运行/输入的命令
c-x u/c-_ 撤销前一个命令(undo)
m-x revert-buffer return 撤销上次存盘后所有改动
m-x recover-file return 从自动存盘文件恢复
m-x recover-session return 如果你编辑了几个文件, 用这个恢复
2.3.5搜索
c-s 向后搜索
c-r 向前搜索
2.3.6窗口命令
窗口命令比较常用,尤其是编辑多个文件的时候,你可以打开多个窗口,可以提高编辑效率。
c-x 2 水平分割窗格
c-x 3 垂直分割窗格
c-x o 切换至其他窗格
c-x 0 关闭窗格
c-x 1 关闭除了光标所在窗格外所有窗格
m c-v 滚动其他窗格内容
c-x 4 f 在其他窗格中打开文件
c-x 4 0 关闭当前缓冲区和窗格
c-x 5 2 新建窗口(frame)
c-x 5 f 在新窗口中打开文件
c-x 5 o 切换至其他窗口
c-x 5 0 关闭当前窗口
2.3.6 c/c /java编程
这些就是光标的移动,比较有用。
m-a 移动光标到声明的开始处
m-e 移动光标到声明的结尾处
m c-a 移动光标到函数的开始处
m c-e 移动光标到函数的结尾处
2.3.7 帮助
c-h c 显示快捷键绑定的命令
c-h k 显示快捷键绑定的命令和它的作用
c-h f 显示函数的功能
c-h b 显示当前缓冲区所有可用的快捷键
c-h t 打开emacs教程
2.3.8 其它
c-x c-e 在lisp语句后可以执行那条语句
m-x eval-buffer 可以执行当前buffer内的elisp代码
m-x eval-region 执行这个region内的代码
2.4 emacs定制
说实话,emacs的迷人之处就是具有非常强的自主配置能力,你可以完全根据自己的个人习惯来设置它。
就像我在下面罗列的那些lisp代码,你可以尽情的改变f1,f2。。等等键所对应的功能,也可以在编
辑c/c /java时使用自动补全等等非常人性化的功能。或许这就是emacs作为一个“神”一样的编辑器所
存在的理由。如果你非常喜欢折腾,那emacs绝对是你的首选编辑器。
每一次emacs启动的时候,它将加载一个名为~/.emacs的lisp代码文件,对该文件进行编辑是一种常用的
定制emacs的方式。我不会讲lisp的具体使用方法,只是罗列出常用的对emacs进行配置的lisp代码,当你
熟悉这些代码的时候,再去深入学习lisp,或许效果更好。
下面是一个典型的lisp语句:
(setq column-number-mode t)
(setq line-number-mode t)
它的意思是显示行列号。其中,括号表示这是一个lisp函数调用,圆括号内第一个符号setq为emacs配置文件
中常用的的函数,它为某个全局变量赋值。该函数第一个参数为要设置的变量名,第二个数则是该变量的值。
下面讲到的每一行代码,你都可以直接拿到~/.emacs中使用。当你想要了解某一行代码的作用时,可以把它
复制粘贴到~/.emacs中,保存然后重启emacs就可以看到效果了。
小技巧:当你编辑~/.emacs配置文件的时候,每一次要看到效果都必须重新启动emacs,非常麻烦。你可以用emacs打开.emacs文件并加入你想要的lisp代码后,使用c-x c-s保存,接着在minibuffer输入:
m-x eval-buffer,它会立即生效。你可以试验一下,非常方便和简单。
2.4.1 设置界面
;;设置字体颜色为黑色,默认为黑色
(set-foreground-color "grey")
;;设置背景为黑色,默认为白色,你也可以自由设置其它颜色
(set-background-color "black")
;;设置光标的颜色为金黄,默认为黑色
(set-cursor-color "gold1")
;;设置鼠标的颜色
(set-mouse-color "gold1")
;; 设置语法高亮显示的背景和主题,区域选择的背景和主题,二次选择的背景和选择
(set-face-foreground 'highlight "white")
(set-face-background 'highlight "blue")
(set-face-foreground 'region "cyan")
(set-face-background 'region "blue")
(set-face-foreground 'secondary-selection "skyblue")
(set-face-background 'secondary-selection "darkblue")
2.4.2 设置周边
;;显示行列号,它显示在minibuffer上面那个杠上
(setq column-number-mode t)
(setq line-number-mode t)
(setq-default indent-tabs-mode t)
;;设置滚动栏在窗口右侧,默认是在左侧
(customize-set-variable 'scroll-bar-mode' right)
;;取消滚动栏
(set-scroll-bar-mode nil)
;;取消工具栏
(tool-bar-mode nil)
;; 禁用菜单栏,f10 开启关闭菜单
(menu-bar-mode nil)
;;设置标题栏为buffer的内容
(setq frame-title-format "emacs@%b")
;; 设置启动时窗口的长宽,下面为90*35
(setq initial-frame-alist '((width . 90) (height . 35)))
;;关闭出错时的提示声
(setq visible-bell t)
;;关闭emacs启动时的画面
(setq inhibit-startup-message t)
;;关闭gnus启动时的画面
(setq gnus-inhibit-startup-message t)
;;允许屏幕左移
(put 'scroll-left 'disabled nil)
;;允许屏幕右移
(put 'scroll-right 'disabled nil)
;;把这些缺省禁用的功能打开。
(put 'set-goal-column 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'latex-hide-environment 'disabled nil)
2.4.3 显示时间设置
;;启用时间显示设置,在minibuffer上面的那个杠上
(display-time-mode 1)
;;时间使用24小时制
(setq display-time-24hr-format t)
;;时间显示包括日期和具体时间
(setq display-time-day-and-date t)
2.4.4 设置日历
;;设置日历的一些颜色
(setq calendar-load-hook
'(lambda ()
(set-face-foreground 'diary-face "skyblue")
(set-face-background 'holiday-face "slate blue")
(set-face-foreground 'holiday-face "white")))
;; 设置阴历显示,在 calendar 上用 pc 显示阴历
(setq chinese-calendar-celestial-stem
["甲" "乙" "丙" "丁" "戊" "己" "庚" "辛" "壬" "癸"])
(setq chinese-calendar-terrestrial-branch
["子" "丑" "寅" "卯" "辰" "巳" "戊" "未" "申" "酉" "戌" "亥"])
;; 设置 calendar 的显示
(setq calendar-remove-frame-by-deleting t)
;;设置星期一为每周的第一天
(setq calendar-week-start-day 1)
;; 去掉不关心的节日,设定自己在意的节日,在 calendar 上用 h 显示节日
;; 在这里,可以把家人还有朋友的生日写上
(setq christian-holidays nil)
(setq hebrew-holidays nil)
(setq islamic-holidays nil)
(setq solar-holidays nil)
(setq general-holidays '((holiday-fixed 1 1 "元旦")
(holiday-fixed 2 14 "情人节")
(holiday-fixed 3 14 "白色情人节")
(holiday-fixed 4 1 "愚人节")
(holiday-fixed 5 1 "劳动节")
(holiday-float 5 0 2 "母亲节")
(holiday-fixed 6 1 "儿童节")
(holiday-float 6 0 3 "父亲节")
(holiday-fixed 7 1 "建党节")
(holiday-fixed 8 1 "建军节")
(holiday-fixed 9 10 "教师节")
(holiday-fixed 10 1 "国庆节")
(holiday-fixed 12 25 "圣诞节")))
2.4.5 设置符合个人的操作习惯
;;设置打开文件的缺省路径,这里为桌面,我喜欢把东西放在桌面上,默认的路径为“~/”
(setq default-directory "~/桌面")
;;设置m-_作为标志位,默认c-@来setmark,c-@不太好用
(global-set-key (kbd "m-") 'set-mark-command)
;;改变emacs要你回答yes的行为。按y或空格键表示yes,n表示no。
(fset 'yes-or-no-p 'y-or-n-p)
;;禁止在鼠标点击的地方插入剪贴板内容
(setq mouse-yank-at-point t)
;;所有模式中都自动填充
(setq-default auto-fill-function 'do-auto-fill)
;;设置默认的文档宽度
(setq default-fill-column 60)
;;不用 tab 字符来indent, 这会引起很多奇怪的错误。
;;编辑 makefile 的时候也不用担心,因为 makefile-mode 会把 tab 键设置成真正的 tab 字符,并且加亮显示的
(setq-default indent-tabs-mode nil)
(setq default-tab-width 8)
(setq tab-stop-list ())
;;防止页面滚动时跳动
;;scroll-margin 3 可以在靠近屏幕边沿3行时就开始滚动
;;scroll-step 1 设置每次都是一行一行向下翻,更有连贯性。
(setq scroll-step 1
scroll-margin 3
scroll-conservatively 10000)
;;设置缺省主模式是text,,并进入auto-fill次模式.而不是基本模式fundamental-mode
(setq default-major-mode 'text-mode)
(add-hook 'text-mode-hook 'turn-on-auto-fill)
;;打开括号匹配显示模式
(setq show-paren-mode t)
;;括号匹配时可以高亮显示另外一边的括号,但光标不会烦人的跳到另一个括号处。
(setq show-paren-style 'parenthesis)
;;让 emacs 可以直接打开和显示图片。
(setq auto-image-file-mode t)
;; 不自动保存模式
(setq auto-save-mode nil)
;;允许emacs和外部其他程序的粘贴
(setq x-select-enable-clipboard t)
;; 自动的在文件末增加一新行
(setq require-final-newline t)
;;non-nil if transient-mark mode is enabled.
(setq-default transient-mark-mode t)
;; 当光标在行尾上下移动的时候,始终保持在行尾。
(setq track-eol t)
;; 设置时间戳,标识出最后一次保存文件的时间。
(setq time-stamp-active t)
(setq time-stamp-warn-inactive t)
(setq time-stamp-format "%:y-m-d : h:m:s chunyu")
;emacs的插件一般都是一个以el为后缀名的文件, 把这个文件下载下来后放到一个目录, 比如~/emacs/lisps, 然后执行下面这两条语句:
(add-to-list 'load-path "~/emacs/lisps")
(require 'pluginname)
;;把c-j绑定到”到达指定行上”(goto-line)
(global-set-key (kbd "c-j") 'goto-line)
;;对c -mode进行快捷键定制, 用define-key即可
;;define-key第一个参数map一般为mode后面直接加”-map”
(define-key c -mode-map (kbd "c-j") 'goto-line)
;; 设置默认tab宽度为2
(setq tab-width 2
indent-tabs-mode t
c-basic-offset 2)
;; 回车缩进
(global-set-key "\c-m" 'newline-and-indent)
(global-set-key (kbd "c-
;; 实现全屏效果,快捷键为f11
(global-set-key [f11] 'my-fullscreen)
(defun my-fullscreen ()
(interactive)
(x-send-client-message
nil 0 nil "_net_wm_state" 32
'(2 "_net_wm_state_fullscreen" 0))
)
;; 最大化
(defun my-maximized ()
(interactive)
(x-send-client-message
nil 0 nil "_net_wm_state" 32
'(2 "_net_wm_state_maximized_horz" 0))
(x-send-client-message
nil 0 nil "_net_wm_state" 32
'(2 "_net_wm_state_maximized_vert" 0))
)
;; 启动emacs时窗口最大化
(my-maximized)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 实现不设置标志就能复制
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;复制单词
(defun copy-word (&optional arg)
"copy words at point into kill-ring"
(interactive "p")
(copy-thing 'backward-word 'forward-word arg)
(paste-to-mark arg))
;;绑定键
(global-set-key (kbd "c-c w") (quote copy-word))
;;复制一行
(defun copy-line (&optional arg)
"save current line into kill-ring without mark the line "
(interactive "p")
(copy-thing 'beginning-of-line 'end-of-line arg)
(paste-to-mark arg))
;;绑定键
(global-set-key (kbd "c-c l") (quote copy-line))
;;复制一段
(defun copy-paragraph (&optional arg)
"copy paragraphes at point"
(interactive "p")
(copy-thing 'backward-paragraph 'forward-paragraph arg)
(paste-to-mark arg))
;;绑定键
(global-set-key (kbd "c-c p")(quote copy-paragraph))
;;复制字符串
(defun beginning-of-string(&optional arg)
" "
(re-search-backward "[ \t]" (line-beginning-position) 3 1)
(if (looking-at "[\t ]") (goto-char ( (point) 1)) )
)
(defun end-of-string(&optional arg)
" "
(re-search-forward "[ \t]" (line-end-position) 3 arg)
(if (looking-back "[\t ]") (goto-char (- (point) 1)) )
)
(defun thing-copy-string-to-mark(&optional arg)
" try to copy a string and paste it to the mark
when used in shell-mode, it will paste string on shell prompt by default "
(interactive "p")
(copy-thing 'beginning-of-string 'end-of-string arg)
(paste-to-mark arg))
;;绑定键
(global-set-key (kbd "c-c s") (quote thing-copy-string-to-mark))
(defun beginning-of-parenthesis(&optional arg)
" "
(re-search-backward "[[<(?\"]" (line-beginning-position) 3 1)
(if (looking-at "[[<(?\"]") (goto-char ( (point) 1)) )
)
(defun end-of-parenthesis(&optional arg)
" "
(re-search-forward "[]>)?\"]" (line-end-position) 3 arg)
(if (looking-back "[]>)?\"]") (goto-char (- (point) 1)) )
)
(defun thing-copy-parenthesis-to-mark(&optional arg)
" try to copy a parenthesis and paste it to the mark
when used in shell-mode, it will paste parenthesis on shell prompt by default "
(interactive "p")
(copy-thing 'beginning-of-parenthesis 'end-of-parenthesis arg)
(paste-to-mark arg))
;;绑定键
(global-set-key (kbd "c-c a") (quote thing-copy-parenthesis-to-mark))
;;所有以上几个函数,都依赖于下面这三个基础函数,由他们三个负责完成实际的工作。
(defun get-point (symbol &optional arg)
"get the point"
(funcall symbol arg)
(point))
(defun copy-thing (begin-of-thing end-of-thing &optional arg)
"copy thing between beg & end into kill ring"
(let ((beg (get-point begin-of-thing 1))
(end (get-point end-of-thing arg)))
(copy-region-as-kill beg end)))
(defun paste-to-mark(&optional arg)
"paste things to mark, or to the prompt in shell-mode"
(let ((pasteme
(lambda()
(if (string= "shell-mode" major-mode)
(progn (comint-next-prompt 25535) (yank))
(progn (goto-char (mark)) (yank) )))))
(if arg
(if (= arg 1)
nil
(funcall pasteme))
(funcall pasteme))
))
2.4.6 绑定键设置
;;绑定键的设置最好放在配置文件的最后,以免被后面的配置文件覆盖
;;设置f1打开帮助文档
(global-set-key [f1] 'info)
;;设置f2为恢复键
(global-set-key [f2] 'undo)
;;设置f3关闭当前buffer
(global-set-key [f3] 'kill-this-buffer)
;;设置f4打开一个终端,可以绑定:eshell,shell,terminal-emulator
(global-set-key [f4] 'term)
;;c-f5 设置编译命令
;;f5 保存所有文件然后编译当前窗口文件
(defun du-onekey-compile ()
"save buffers and start compile"
(interactive)
(save-some-buffers t)
(switch-to-buffer-other-window "*compilation*")
(compile compile-command))
(global-set-key [c-f5] 'compile)
(global-set-key [f5] 'du-onekey-compile)
;;f6设置为在emacs中调用gdb
(global-set-key [f6] 'gdb)
;;可以显示所有目录以及文件
(setq speedbar-show-unknown-files t)
;;设置f9调用speedbar命令
;;使用 n 和 p 可以上下移动,
;; 展开目录或文件进行浏览,- 收缩,ret 访问目录或文件,g 更新 speedbar。
(global-set-key [f9] 'speedbar)
;;设置f10打开/关闭菜单
(global-set-key [f10] 'menu-bar-mode)
;; 设置f11快捷键指定emacs 的日历系统
(global-set-key [f11] 'calendar)
;; 设置f12 快速察看日程安排
(global-set-key [f12] 'list-bookmarks)
;; "c-,"设为屏幕左移命令
(global-set-key (kbd "c-,") 'scroll-left)
;; "c-."设为屏幕右移命令
(global-set-key (kbd "c-.") 'scroll-right)
2.4.7 c/c /java编程模式
;; c语言模式
(add-hook 'c-mode-hook
'(lambda ()
;;把c语言风格设置为k&r风格
(c-set-style "k&r")
;; 此模式下,当按backspace时会删除最多的空格
(c-toggle-hungry-state)
;; tab键的宽度设置为4
(setq c-basic-offset 4)
;; 在菜单中加入当前buffer的函数索引
(imenu-add-menubar-index)
;; 在状态条上显示当前光标在哪个函数体内部
(which-function-mode)))
;; c 语言模式
(add-hook 'c -mode-hook
'(lambda()
;;把c 语言风格设置为stroustrup风格
(c-set-style "stroustrup")
(c-toggle-auto-state)
(c-toggle-hungry-state)
(setq c-basic-offset 4)
(imenu-add-menubar-index)
(which-function-mode)))
;; java语言模式
(add-hook 'java-mode-hook
'(lambda()
(c-set-style "java")
(c-toggle-auto-state)
(c-toggle-hungry-state)
(setq c-basic-offset 4)
(imenu-add-menubar-index)
(which-function-mode)))
;;能把一个代码块缩起来,需要的时候再展开
;; m-x hs-minor-mode
;; c-c @ esc c-s show all
;; c-c @ esc c-h hide all
;; c-c @ c-s show block
;; c-c @ c-h hide block
;; c-c @ c-c toggle hide/show
(load-library "hideshow")
(add-hook 'c-mode-hook 'hs-minor-mode)
(add-hook 'c -mode-hook 'hs-minor-mode)
(add-hook 'java-mode-hook 'hs-minor-mode)
(add-hook 'perl-mode-hook 'hs-minor-mode)
(add-hook 'php-mode-hook 'hs-minor-mode)
(add-hook 'emacs-lisp-mode-hook 'hs-minor-mode)
;;自动补全右边的部分.包括<>, "", '', (), //, [] , {}等等。
(defun my-c-mode-auto-pair ()
(interactive)
(make-local-variable 'skeleton-pair-alist)
(setq skeleton-pair-alist '(
;;自动补全<>
(?\< ? _ ">")
;;自动补全//
(?` ?` _ "/")
;;自动补全()
(?\( ? _ " )")
;;自动补全[]
(?\[ ? _ " ]")
;;设自动补全""
(?\" ? _ "\"")
;;自动补全''
(?\' ? _ "'")
;;自动补全{}
(?{ \n > _ \n ?} >)))
(setq skeleton-pair t)
(local-set-key (kbd "<") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "/") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "(") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "/") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "'") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "\"") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "[") 'skeleton-pair-insert-maybe)
(local-set-key (kbd "{") 'skeleton-pair-insert-maybe))
(add-hook 'c-mode-hook 'my-c-mode-auto-pair)
(add-hook 'c -mode-hook 'my-c-mode-auto-pair)