emacs 按键绑定
Table of Contents
全局按键绑定global-set-key
(global-set-key ... 'my-funtion) 比如 (global-set-key (kbd "C-f") 'forward-char) (global-set-key (kbd "C-x C-f") 'find-file) 或者 (define-key global-map (kbd "C-f") 'forward-char) (define-key global-map (kbd "C-x C-f") ''find-file)
常用的 像C-x C-f ,C-f ,C-c C-f 等按键 很容易写出来
但是有些按键 包含 f1 f2 backspace,delete return shift 等按键
这样的按键不好配置。
有一种方法可以帮你解决这个问题
- M-x global-set-key RET 交互式的绑定你的键。
- C-x Esc Esc 调出上一条“复杂命令”。
好了,你现在就能在 minibuffer 里看到你应该写在 .emacs 的东西 了。
比如 我想绑定 Alt-Return 到 forward-char 这个命令
M-x:global-set-key RET 然后 按下 Alt-Return 按键 ,然后输入forward-char 然后回来
再然后 按下 C-x Esc Esc 就会在minibuffer 里显示出
(global-set-key [27 13] (quote forward-char))
绑定新的前缀键
其实上面的办法只能让你绑定一个已有的前缀。你有可能想绑定一个
save-buffer 到 "C-c C-c C-b a"。上面的办法就不灵了。我们必须 使用另外
的办法:
(global-set-key (kbd "C-c C-c C-b a") 'save-buffer)
上面的那个 "C-c C-c C-b a" 是自动把 "C-c C-c", "C-c C-c C-b" 都定义
成了一个 prefix-command.
创建新的 prefix command
上面这个办法只对开头的键已经是 prefix command 的键序列起作用, 如果
你的第一个键不是一个 prefix,那么就会出错。你可以试试:
(global-set-key (kbd "C-z C-c C-w b") 'find-file)
出现错误:(error "Key sequence C-z C-c C-w b uses invalid prefix characters")
所以你必须事先把第一个键设定为 prefix:
(define-prefix-command 'ctl-z-map) (global-set-key (kbd "C-z") 'ctl-z-map) (global-set-key (kbd "C-z C-c C-w b") 'find-file)
如何查看 某个快捷键绑定了什么命令
C-h k 或 F1 k
比如我想看 C-x C-s 这个快捷键 绑定了什么命令
C-h k 然后按下C-x C-s按键
或者
F1 k 然后按下C-s C-s按键
如何查看 某个函数或命令的文档
C-h f 或F1 f 然后输入相应函数名
如查看 forward-char 命令的文档
C-h f 然后输入forward-char 回车
F1 f 然后输入forward-char 回车
为具体的 major mode 绑定按键
(require 'dired) ;;比如在dired mode 下 直接按u 就回到上层目录dired-up-directory (define-key dired-mode-map "u" 'dired-up-directory) ;; 或者 (defun my-dired-mode-hook() (local-set-key "u" 'dired-up-directory)) (add-hook 'dired-mode-hook 'my-dired-mode-hook)
常用按键总结
光标移动/快速定位相关
快捷键 | 绑定的函数 | 解释 |
---|---|---|
C-f, C-b | forward-char backward-char | 以字符为单位移动。 |
M-f, M-b | forward-word,backward-word | 以单词为单位移动。 |
C-M-f, C-M-b | forward-sexp backward-sexp | 以一个语法单元尾单位前后移动 |
C-a, C-e | move-beginning-of-line move-end-of-line | 移动到行首,行末。 |
M-a, M-e | backward-sentence forward-sentence | 移动到句子头,句子尾。 |
C-M-a ,C-M-e | beginning-of-defun end-of-defun | 到函数头尾 |
M-{, M-} | forward-paragraph backward-paragraph | 移动到段落头,段落尾。 |
C-d | delete-char | 删除光标后的字符 |
M-d | kill-word | 删除光标后的单词 |
C-backspace | backward-kill-word | 删除光标前的一个单词 |
M-backspace | backward-kill-word | 删除光标前的一个单词 |
C-k | kill-line | 删除一行 |
C-M-k | kill-sexp | 删除一个语法单元(比如一对(),[]{}) |
C-x k | kill-buffer | 关闭打开的文件/buffer |
M-h | mark-paragraph | 选择一段 |
C-M-h | mark-defun | 选择一个函数 |
C-x h | mark-whole-buffer | 全选 |
C-v, M-v | scroll-up-command scroll-down-command | 翻页。 |
M-<, M-> | beginning-of-buffer end-of-buffer | 到文件头和文件尾。 |
M-r | move-to-window-line-top-bottom | 加参数,移动到窗口里的某一行。不加参数缺省移动到窗口中间。 |
M-g c | goto-char | 到文件的第 N 字节。 |
M-g g | goto-line | 到文件第 N 行。 |
C-g | keyboard-quit | 取消或放弃一个操作 |
C-g的详细说明: 比如我想打开一个文件C-x C-f 当我按完C-x 还没按C-f 前,我突然想放弃了,这个时候直接C-g 就可以了
常用操作相关
C-x C-f | find-file | open file |
C-x C-s | save-buffer | save file |
C-x C-w | write-file | save as |
C-x k | kill-buffer | close current file |
C-x C-c | save-buffers-kill-terminal | exit |
C-_ 或C-/ | undo | undo |
C-@ or C-<SPC> | set-mark-command | 设置起始点,设置完之后移动光标,光标所在位置与C-@时所在位置之前的区域即为选中区域 |
C-w | kill-region | cut |
M-w | kill-ring-save | copy |
C-y | yank | paste |
M-x:truncate-line | truncate-line | set word wrap |
C-s | isearch-forward | search forward |
C-r | isearch-backward | search backward |
C-s C-s | isearch-repeat-forward | find next forward |
C-r C-r | isearch-repeat-backward | find next backward |
M-x:replace-string | replace-string | replace |
对于拷贝粘贴,Emacs 有点不一样。在一般的编辑器中,先鼠标选择一段区域,
然后 C-c 拷贝。Emacs 中的不是这样的,当前光标位置叫point , 还有一个
点是 mark ,可以用 C-@ 设置 mark 的位置,然后移动光标 point 和 mark 之间的内容
就是 region , C-w 剪切 , M-w 拷贝都是针对 region 的。 C-@ 的作用就是
设置一块region的起始位置,point 是光标当前的位 置, region 是 mark 和
point 之间的区域。
上面有好多命令都是kill-开头的 如kill-line ,kill-word kill-region等这些
命令执行后被删除的东西都会放到kill-ring 中, 然后 C-y 可以再次把它粘贴
回来
唯一让我觉得不方便的就是 C-@ ,因为 C-<SPC> 一般用来切换输入法了。还好,
用他的次数也不多, 就算用鼠标,也挺好, 习惯问题。
C-@ = C-S-2 不好按,所以我设置成 C-2 好按一下,
(global-set-key (kbd "C-2") 'set-mark-command)
一些常用操作的优化
比如 C-x k kill-buffer 默认会提示你输入要kill 的buffer 名 ,如果是当前buffer 则直接回车
我嫌输入回车麻烦, 我想做到输入C-x k 直接把当前buffer 关闭
(autoload 'server-edit "server") ;;;###autoload (defun kill-buffer-or-server-edit() (interactive) (message "kill buffer %s" (buffer-name)) (when (equal (buffer-name) "*scratch*") (copy-region-as-kill (point-min)(point-max))) (if (and (featurep 'server) server-buffer-clients) (server-edit) (kill-this-buffer) ) ) (global-set-key (kbd "C-x k") 'kill-buffer-or-server-edit)
C-a smart-beginning-of-line
默认情况下C-a 绑定的的函数move-beginning-of-line 。
但是我对 move-beginning-of-line这个函数不太满意,我想做到,当我第一次
按下C-a时,跳到行首,当已经在行首时,则忽略行首的空白字符,并且C-a 可以在这
两个位置来回跳转.于是有了下面的 smart-beginning-of-line
;;;###autoload (defun smart-beginning-of-line () "Move point to first non-whitespace character or beginning-of-line. Move point to beginning-of-line ,if point was already at that position, move point to first non-whitespace character. " (interactive) (let ((oldpos (point))) (beginning-of-line) (and (= oldpos (point)) (back-to-indentation) ))) (global-set-key (kbd "C-a") 'smart-beginning-of-line)
C-e smart-end-of-line
C-e对于end-of-line ,也想要同样的效果。
;;;###autoload (defun smart-end-of-line() "Move point to first non-whitespace character or end-of-line. Move point to end-of-line ,if point was already at that position, move point to first non-whitespace character." (interactive) (let ((oldpos (point))) (beginning-of-line) (when (re-search-forward "[ \t]*$" (point-at-eol) t) (goto-char (match-beginning 0))) (when (= oldpos (point)) (end-of-line)))) (global-set-key (kbd "C-e") 'smart-end-of-line)