步步为营,零秒精通 Emacs

步步为营是一步一个脚印, “零秒"乃调用直觉力, 非物理概念上的"零秒”.

一个以讹传讹的观念"Emacs很难且耗费时间", 标题"零秒"有意打消对Emacs学习的成见. 通过点出Emacs要点的方式, 举一反三, 心有灵犀, 一通百通. 而不必案牍劳形, 悬梁刺股.

曾国藩的战术“结硬寨, 打呆仗”, 初时很慢, 待工事渐成, 则坚不可摧; 同时努力学习SICP的策略, 首先抛出点滴星火,再看时,已成燎原之势。

以直觉力为基础,步步为营,稳扎稳打,构筑Emacs技能。

00.引子

Emacs的简单, 则一言以蔽之, 只是一个Meta键.
Meta键(键盘上的option/alter键)
Meta的词源含义是higher, beyond,没有最高,只有更高.
中文译为"元", 发端处, 源头处;
So Meta is Source, and it relates to source code. Meta关联Source-Code, 在Source-Code中, Function又是的一等公民.
Emacs的简单策略便是将Meta键绑定到Function上.
具体则是:
M-x (x for execucte), 然后可以天马行空的查询要做的事情, 比如插入当前的时间:

至此, Emacs在战略层面上在全局层面上的所有事情便全部结束了, 剩下的事情仅仅是战术层面上的高效问题与缝缝补补的实现问题.

第一个策略: 引入Ctrl键

比如从目录中打开一个文件, 可以M-x find-file,
需要键入十一个字符 Ctrl策略, 可以C-x C-f. 只需要键入4个字符.

01.Semantic Keybinding

Emacs从最源头处, 用Meta-Execte调用所有的function; 然后定义Ctrl的技术简化Meta的流程.
正文从语义化快捷键入手, 辅助在5分钟之内永久记忆(Never have a second look), 20多个一级快捷键(高频), 30几个二级绑定键(中频), 闲看三级快捷键(低频); 以及按照功能分类的表格.

答题区连载.

Additional

建议不要从零开始折腾Emacs.
两步安装doom-emacs, 可以实现此项目内的所有操作.

16 个赞

厉害了,搞成故事连载

起手式总结的很到位...

较真一下,应该是:

一级绑定之cursor光标的移动: (高频)
在一级绑定中, C-x, M-x中的x(execute)省略, 简化为C-与M-x;

光标操作的对象:
character, word, line, sentence, (*paragragh), page, buffer.

  1. character and word
    C-f (M-x forward-char) 向前移动一个字符的位置
    C-b (M-x backword-char) 向后移动一个字符的位置
    char是最小的操作单元, char之上则是word, 回顾上文阐述的meta的词源含义是higher,因此Meta绑定相同的键, 范围要比Ctrl更大一点,
    由此, 比char大一级的是word
    M-f (M-x forward-word) 向前移动一个单词的位置.
    M-b (M-x backword-word) 向后移动一个单词的位置.

  2. line and sentence.
    C-e (e for end) move to end of line,
    C-a (a for ahead) move to ahead of line
    同样的逻辑,Meta比Ctrl的范围高一个等级
    M-a move to ahead of the sentence
    M-e move to end of the sentence.

以上两点为光标在水平方向的移动(horizontal),
与之相对应的纵向(Vertiallly)移动的操作.

  1. Vertical Movement between lines
    C-n (调用function next-line), 向下移动一行
    C-p (previous-line)
    接下来, 有意思的事情来了.
    由character和line操作可知, 绑定相同的键, Meta的作用范围总是比Ctrl更高一级, 但是此时查看:
    M-p
    M-n
    发现Emacs没有定义这两个key-sequnces, 根据前面的逻辑,
    M-p应该向上移动更多行, 至少比一行要多; Emacs竟然没有定义, 这真是千载难逢的良机.

    暂时按下不表, 先小结Ctrl的光标操作. Ctrl能操作的最大单位是line, 更大范围的光标动作交由Meta处理.

  2. Vertically Page Down and Up
    向上翻页M-v, v当然是vertical, 而Meta是higher, 往更高处纵向移动, 便是UP,
    那么向下呢? 既然Meta相对于Ctrl而higher, 反过来Ctrl则是Lower; 因此向下翻页是C-v.
    此处的心思, 一级绑定键, 始终用最少的动作, 最少的触发键, 如果绑定三个键, 则不需要Ctrl的参与.
    M-v-u(up), M-v-d(down)向下(对比两键操作
    M-v与C-v向上或者向下翻动一整页, 大多数时候, 这不是我们想要的. 我要半屏半屏的翻页.

现在重新回到M-p与M-n, 绑定半屏翻页.

#+begin_src emacs-lisp :session sicp :lexical t
(defun scroll-half-page-down ()
  "scroll down half the page"
  (interactive)
  (scroll-down (/ (window-body-height) 2)))

(defun scroll-half-page-up ()
  "scroll up half the page"
  (interactive)
  (scroll-up (/ (window-body-height) 2)))

(global-set-key "\M-n" 'scroll-half-page-up)
(global-set-key "\M-p" 'scroll-half-page-down)
#+end_src

备注
#+BEGIN_QUOTE 因为设置了触控板(或者鼠标)Invert scroll direction(Natural Scrolling), 因此up与down是反着映射到next和previous的 #+END_QUOTE

  1. Buffer
    M-<, to the biginning of the buffer
    M->, to the end of the buffer.
    只要清楚ctrl只管到line, 其余全部都是Higher的Meta的工作.

(在网页编辑的排版, 英文状态下的, 不管后面留多少空格, 都自动去掉, 太紧凑, 很难看, 因此贴图.

github库中添加emacs手册的org文档。

初步计划的章节

这是要写书的节奏啊

嗯那, 多赐教啊。

编辑功能

  • 复制黏贴 (M-w, C-y)

  • insert (C-q quotation)
  • delete(C M d delele), kill ring
  • modify(undo, transpose, uppercase, lowercase, title,
  • Search(Swiper…)

  • Numeric arguents C-u
  • Repeat C-x z

  • Completion(yasnippet)
  • indentation (M-i 缓解小指的负担
  • white space(C-x C-o)
  • Filling(global-visual-line-mode)
  • Spelling-checking

  • Register

Emacs作为编辑器, Manuals中有15章(有用没用的)直接在讲编辑功能.

键的绑定同样遵循语义化的原则:

比如Delete(killing)

delete键(即backspace退格键, backword);
C-<del> 搭配是删除一个字符,
M-<del>则是倒退删除一个单词;
与backwords对应的是forwards,(进格删除)
C-d M-d分别进格删除一个字符和一个单词.

Killing的范围比delete大;
C-k是删除到行尾, M-k是删除到句尾, 跟前面一致. 以上是forwards进格删除,
对行的backwardst退格删除 C-x <del>

1 个赞

感觉质量很高啊,解释也通俗易懂

w, 好暖啊,ty.

第二章的拓展topic1:

这么多的键绑定, 从语义化的理解是一方面, 更重要的一方面可能应该去找捷径, 比如调用直觉和由此带来的强烈满足感和成就感.

编辑过程中对blank-lines的处理,

C-x C-o调用(delete-blank-lines)

C-x C-o的绑定键没有逻辑, o是个洞吗? 一个洞代表空行?

Emacs Manual中很多这样的处理细分领域的绑定键, 头悬梁锥刺股的用下来, 对emacs的热情和兴趣早早磨光了.

回到C-x C-o调用(delete-blank-lines)

假设有这样四行

"The quick brown fox jumps over the lazy dog"


"The quick brown fox jumps over the lazy dog"

当前的光标在第一行上的fox,后 发现两行文字中间的空行是多余的, 因此要删掉.

需要动用人肉劳力这样做:

  1. C-n 管标移动到下一行
  2. 连续两次C-k删除空行
  3. 然后凭借超强的记忆力(记住刚才是在fox的位置, 和导弹一般精确的点位控制回到fox后面.

劳神费力.

应用C-x C-o呢? 可以在第一行的任意位置上调用C-x C-o, 下面的空行会自动删除.

怎样从直觉上理解呢?

  1. 光标在第一行的某个点上, 然后调用一个命令, 在光标之外的另外一个地方会立刻发生某件事情, 这就是远程控制呗;
  2. 更直觉一点, 这边是"意念移物"呗,

由此从直觉里生发的成就感和兴趣会驱动我们应用更加复杂的命令和组合.

P.S. 作为对"零秒" 这个标题党的补充.

Appendix B: Git Version Control

|-----------------------+------------------------------+----------------------------------------------|
| Objects               | Features                     | Actions:                                     |
|-----------------------+------------------------------+----------------------------------------------|
| 0.Introduction        |                              |                                              |
|                       | Faster commands              |                                              |
|                       | Stability                    |                                              |
|                       | Isolated Environments        |                                              |
|                       | Efficient Merging            |                                              |
|-----------------------+------------------------------+----------------------------------------------|
| 1.Overview            | Objects:                     | Actions:                                     |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 1.working directory          | configure                                    |
|                       | 2.staging area               | recording                                    |
|                       | 3.Commit history             | undoing                                      |
|                       | 4.developmnent branches      | branch (non-linear)                          |
|                       | 5.remotes                    | remote                                       |
|-----------------------+------------------------------+----------------------------------------------|
| 2.Configuration       | 1) User Info:                |                                              |
|                       |                              | git config --global user.name                |
|                       |                              | git config --global user.email               |
|                       | 2) Editor:                   |                                              |
|                       |                              | git config --global core.editor emacs        |
|                       | 3) Alias:                    |                                              |
|                       |                              | git config --global alias.ci commit          |
|                       | .inspect                     |                                              |
|                       |                              | git config -l                                |
|-----------------------+------------------------------+----------------------------------------------|
|                       | help:                        | git help log                                 |
|                       |                              | man git-log                                  |
|                       |                              | tldr git-log                                 |
|-----------------------+------------------------------+----------------------------------------------|
| 3.Recoding Chaneges   |                              |                                              |
|                       | Staging area:                |                                              |
|                       |                              | git add                                      |
|                       |                              | git rm --cached                              |
|                       | .inspecting:                 |                                              |
|                       |                              | git status                                   |
|                       |                              | git diff (--cached)                          |
|-----------------------+------------------------------+----------------------------------------------|
|                       | Commits                      |                                              |
|                       |                              | git commit                                   |
|                       | .inspecting                  |                                              |
|                       |                              | git log                                      |
|                       |                              | git log --oneline  <file>                    |
|                       |                              | git log <since> ... <until>                  |
|                       | Tagging commit               |                                              |
|                       |                              | git tag -a v1.0  'stable version'            |
|-----------------------+------------------------------+----------------------------------------------|
| 4.Undoing Changes     | 1) Woriking directory        |                                              |
|                       |                              |                                              |
|                       |                              | git reset --hard HEAD                        |
|                       |                              | git clean -f (git rid of unstaged files)     |
|                       | .individual file:            |                                              |
|                       |                              | git checkout HEAD <file> (most frequent)     |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 2) Staging area              |                                              |
|                       |                              | git reset HEAD <file> (extra staged file)    |
|                       |                              | (No --hard here)                             |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 3) Commits                   |                                              |
|                       | .resetting                   |                                              |
|                       |                              | git reset HEAD~1                             |
|                       | .reverting                   |                                              |
|                       |                              | git revert <commit-id> (created new commit ) |
|                       | .ameding                     |                                              |
|                       |                              | git commit --amend                           |
|-----------------------+------------------------------+----------------------------------------------|
| 5.Branches            | 1) Manipulate brnaches       |                                              |
|                       | .listing branches            |                                              |
|                       |                              | git branch                                   |
|                       | .creating branches           |                                              |
|                       |                              | git branch <name>                            |
|                       |                              | git checkout -b <name>                       |
|                       |                              | .git/refs/heads/develop                      |
|                       | .deleting branches           |                                              |
|                       |                              | git branch -d, -D                            |
|                       |                              |                                              |
|                       | Checking out branches        |                                              |
|                       |                              | git checkout  <branch>                       |
|                       | .detached                    |                                              |
|                       |                              | git checkout -b <new-branch-name>            |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 2) Merging branches          |                                              |
|                       | .fast-forward:               |                                              |
|                       |                              | git checkout master                          |
|                       |                              | git merge some-feature                       |
|                       | .3-way merge:                |                                              |
|                       |                              | same as the above                            |
|                       | .merge conflicts             |                                              |
|                       |                              | <<<<<<HEAD                                   |
|                       |                              | ==================                           |
|                       |                              | >>>>> some-feature                           |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 3) Branches workflow         |                                              |
|                       | .types of branches           |                                              |
|                       |                              | permanent or topic                           |
|                       | .permanent_branch            |                                              |
|                       |                              | master(public ), develop,                    |
|                       | .topic_branch                |                                              |
|                       |                              | feature and hotfix                           |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 4) Rebasing:                 |                                              |
|                       |                              | git checkout some-feature                    |
|                       |                              | git rebase master                            |
|-----------------------+------------------------------+----------------------------------------------|
|                       | .interactive_rebasing:       |                                              |
|                       |                              | git rebase -i master                         |
|                       |                              | (Notice for rewriting)                       |
|-----------------------+------------------------------+----------------------------------------------|
| 6.Remote Repositories |                              |                                              |
|                       | 1) Manipulate remotes:       |                                              |
|                       | .listing remotes:            |                                              |
|                       |                              | git remote                                   |
|                       |                              | git remote -v                                |
|                       | .creating_remotes:           |                                              |
|                       |                              | git remote add <name> <path-to-repo.         |
|                       | .deleting_remotes:           |                                              |
|                       |                              | git remote rm <remote-name>                  |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 2) Remote branches:          |                                              |
|                       | .fetching_remote_branches    |                                              |
|                       |                              | git fetch <remote> <branch>                  |
|                       |                              | git branch -r                                |
|                       | .inspecting_remote_branches: |                                              |
|                       |                              | git log origin/master                        |
|                       | .merging/rebsing:            |                                              |
|                       |                              | git checkout some-feature                    |
|                       |                              | git fetch origin                             |
|                       |                              | git merge origin/master                      |
|                       |                              | (littered with meaninglesss merge commits)   |
|                       |                              |                                              |
|                       |                              | git checkout some-feature                    |
|                       |                              | git fetch origin                             |
|                       |                              | git rebase origin/master                     |
|                       | .pulling:                    |                                              |
|                       |                              | git pull origin/master (--rebase )           |
|                       | .pushing:                    |                                              |
|                       |                              | git push <remote> <branch>                   |
|                       |                              |                                              |
|-----------------------+------------------------------+----------------------------------------------|
|                       | 3) Remote workflow:          |                                              |
|                       | .bare_repository:            |                                              |
|                       |                              | git init --bare <path>                       |
|                       | .centralized_workflow:       |                                              |
|                       |                              | git fetch origin master                      |
|                       |                              | git rebase origin/master                     |
|                       |                              | git push                                     |
|                       | .integrator_workflow:        |                                              |
|                       |                              | github的模式                                 |
|-----------------------+------------------------------+----------------------------------------------|
| Conclusion            |                              |                                              |
|                       | 1.working directory          |                                              |
|                       | 2.staging area               |                                              |
|                       | 3.commit history             |                                              |
|                       | 4.branches                   |                                              |
|                       | 5.remotes                    |                                              |
|-----------------------+------------------------------+----------------------------------------------|
1 个赞

修改成了M-x find-file, C-x C-f,
这样下文可以自然进入到编辑功能, 先把文件打开, 才好编辑.

对比Search功能的Emacs操作与命令行操作

Emacs的优势是对数据和查询结果的便捷二次处理.

比如想从宏观上了解下Emacs手册中中全部whitespace操作.

可以从Terminal中完成

find . -type f -exec grep --color -inH --null -e  "whitespace" \{\} +

可以看到结果, 但没法做简单的统计.

即使加上nl

 find . -type f -exec grep --color -inH --null -e  "whitespace" \{\} +

也只能大略了解到’whitespace’在整个文档中, 有95句话提到过.

而在Emacs中执行同样的命令:
C-x grep-find;

则瞬间眼明心亮, 有95句话有一个或多个whitespace这个单词, 总计有151个. 而且在 Killing.org 这个文件中有6句话, 在 text.org 中有5句, 在 Display,org 中有17句话, 在 Program.org 中也有17句, 等等,

Emacs中执行命令的突出优势是简单方便的二次处理.

对初学者帮助很大

初学, 有多初?
看看这个帖子,

假如是自己从零DIY, 后面几章真正施展Emacs的强大功能之处,
可能在你的机器上不能复现.

目前的流程图 Meta --> Control —> Cursor —> Edit

由Meta的词源语义出发分析Emacs的快捷键绑定, 引入Ctrl键简化输入过程, 光标的移动作为edit的前置步骤, 以find-grep查询收尾基本的编辑功能.

在切入到God’s Eyes(Dired) and God’s Hands(Booksmarks)之前,
先光速浏览File的基本操作(读取和保存):
C-x C-f (M-x find-file) 找到并打开文件
C-x C-r (r是read-only), 比如浏览自己的配置文件, 要避免无心修改掉东西.
C-x C-s (s,save) 保存单个文件
C-x s 保存全部文件, 保存全部文件功能更常用, 因此组合键也少.
最后在个人配置上添加两行, 设置自动保存文件.

(setq auto-save-visited-mode t)   
(auto-save-visited-mode +1)

以上完结, 马上进入精彩的部分.