Emacs教程(四)

上回介绍了在Emacs中如何插入删除文本的简单操作,以及一些杂七杂八的命令,都还是蛮容易的。这回先跳过编辑这部分,介绍Emacs中的Minibuffer,呃,翻译过来叫迷你缓冲,听着比较难受,后面还是用E文吧。

一、初识Minibuffer
  Minibuffer 乃是Emacs命令读取复杂参数的位置。比如说文件名,缓冲名,命令名以及Lisp表达式这些东西。Minibuffer 显示在echo area中,当Minibuffer处于使用状态时,会出现一个彩色的提示符并以冒号结尾,根据提示符信息输入参数,以回车提交。取消Minibuffer 使用C-g,也就是上节介绍的取消命令。
  其实Minibuffer并不是太神秘,最常见的地方就是打开文件时提示我们输入文件名:

  按下C-x C-f 后,回显区就会变成这个样子,其中Find file 就是Minibuffer的提示符,因为它是蓝色的。后面的路径是Minibuffer自动添加的默认值,我们可以把参数选项insert-default-directory设置为nil,关闭这个默认路径。
  这里插入一下如何设置Emacs参数选项,我们键入M-x set-variable RET insert-default-directory RET后输入nil 即可,这里的RET代表回车。改回默认,前面输入一样最后输入t 。其实我们按下M-x set-variable也激活了Minibuffer。
  
二、在Minibuffer中编辑
  我们可以将Minibuffer看成和主输入区类似的缓冲,Minibuffer中也有个buffer嘛,就是说某些主输入区的命令Minibuffer也可以用。同样我们看上面那张图,使用C-a 可以把光标移到d字符的位置,再按C-e 光标又回到最后,还可以使用M-Backspace删除“info/” 回到上级目录。不过需要注意的一点是,RET是Minibuffer的结束符而不是换行符,所以如果我们需要插入新行就不能使用回车,而是用C-o。同样对于TAB、SPC、?(前两个分别对应Tab键和空格键)在Minibuffer中经常用于自动补全,所以也不能直接输入,我们需要使用C-q 来插入,比如TAB,就用C-q TAB来替换。可以说Minibuffer和主输入区基本上一样,同样的快捷键、同样的操作方式,复制粘贴功能一应俱全。
  通常情况,Minibuffer在屏幕中只有一行,随着你输入的增多,Minibuffer会自动调整大小来适应。变量 resize-mini-windows用于控制Minibuffer的大小变化,其默认值是grow-only,大小只增不减,设为t 后,如果你删除一行会自动缩小,设为nil,就不会动了。变量max-mini-window-height 控制Minibuffer高度的最大值,设为浮点数表示占整个窗口的百分比,整数表示最大可以有多少行。默认值是0.25。
  当我们操作Minibuffer时也可以控制另一个窗口,C-M-v 命令就是用来滚动另一个窗口的文本,这个是往下翻页,C-M-S-v 是往上翻页,大家要看清楚,这不是四个键一起按,如果你不小心按的是s键,你会发现出来的是QQ聊天窗口,所以出于对中国广大QQ用户的考虑,Emacs把它改成了大写的s,就是说还要加上Shift键,呃,这是我目前见的最长的按键了而且比较变态。其实,也有简洁的方式,M-PageUp和M-PageDown,不过这两个键不在主键盘区,就看各位心情了。
  Minibuffer 一般情况是不允许递归调用的,也就是我们不能连按两次C-x C-f,它会提示Minibuffer正在使用,我们也可以设置变量enable-recursive-minibuffers 为t 来激活递归调用,不过容易引起错误,大家还是尽量避免吧。

三、自动补全
  Emacs中的命令有那么多,我们也不可能每一个都记的住,电脑里的路径也很长,记漏几个字符也很正常,这个时候自动补全就显得很重要了。常用的自动补全有四个键TAB、SPC、RET和?。我们先看它们的准确定义。
  TAB    尽可能的补全Minibuffer中的字符,如果没有满足要求的,则列出所有可能的补全。对应命令minibuffer-complete。
  SPC    最多补全Minibuffer中的一个词,如果没有满足要求的,则列出所有可能的补全,在输入路径时SPC不可用。对应命令minibuffer-complete-word。
  RET    提交Minibuffer中的文本,或者选取第一个可能的补全提交。对应命令minibuffer-complete-and-exit。
  ?      列出所有可能的补全。对应命令minibuffer-completion-help。
  下图就是我们按ins TAB TAB后自动补全的例子:

  第一个TAB补全了“ert-”,第二TAB列出了所有可能的补全。
  再仔细解读下这几个键,TAB是用的最多的自动补全,可以说每个操作系统的shell都支持TAB自动补全,它的设计目标也是尽可能的补全我们的输入,而一次补全需要满足下面三个准则:

  • 光标前Minibuffer中的文本必须和补全候选项中开头的内容一致,如果光标后还有文本则其需为补全候补项剩下内容的字串。
  • 如果不满足上一条件,则使用部分匹配补全,即将Minibuffer中的文本以"-"或者空格分开,分别补全。比如输入"em-l-m",再按TAB,则会补全至"emacs-list-mode"。
  • 如果仍无满足的候选项,则继续使用第一条准则,不过忽略光标后的文本。

  空格键的匹配模式与TAB类似,不过它只匹配到下一个"-"或者空格,比如输入auto-f 后按空格会完成auto-fill-,需要再按一个空格才会完全补全为auto-fill-mode。此外,在TAB和SPC的匹配当中可以使用通配符"*",代表任意一个或多个字符。
  在没有完全匹配项时,Emacs会列出所有满足条件的匹配,我们可以使用多种方法来选择某一项。
  Mouse-1, Mouse-2,就是鼠标左右键。
  或者在Minibuffer中按M-v,就会切换到补全候选项窗口,然后我们可以使用RET选择光标位置的项(choose-completion)。或者使用左右箭头键移动光标(next-completion、previous-completion)。很遗憾,除了使用上下左右,没有更快的方法了,M-f 和M-b 都是移到"-"字符的位置。再说明一点,上面几个命令想要能用,就必须把Minibuffer递归调用打开。
  在我们使用RET提交输入时,会出现三种不同情况的自动补全,三种情况根据提交内容的使用情况区分。

  • 严格匹配,故名思意,就是说输入的内容要完全匹配某一项才行。我们使用C-x k 来关闭某一个buffer时会提示输入buffer名,这个时候就是使用的严格匹配。如果找不到这个buffer 命令就不会执行。
  • 谨慎匹配,这个和严格匹配类似,区别在于回车后如果没有找到一个完全匹配的项Minibuffer不会退出,而是进行自动补全,再按RET就可以提交输入,然后退出Minibuffer。谨慎匹配用在读取必须存在的文件时。
  • 宽松匹配,C-x C-f 就是典型的宽松匹配,有一致的就打开这个文件,没有一至的就新建个文件。

  自动补全还有种icomplete 模式,使用M-x icomplete-mode 启动,作用是自动更新可能的补全。

  接下来再介绍一些自动补全的变量。
  completion-auto-help ,设为nil 时不会出现补全候选项列表,必须使用? 手动调出。设为lazy,在按第二次TAB时会出现补全候选项列表。
  completion-ignored-extensions,它的值包含了一些字符串,包含了比如".o", ".elc", "~" 之类的,这样在输入文件名自动补全时就不会选择以这些结尾的文件了,不过当所有可能的候选都在忽略后缀里面,所有忽略全部无效。比如有foo.c 和 foo.elc 两个文件,输入foo TAB,会得到foo.c,但你输入foo.e TAB 还是会出现foo.elc。此外如果它的某项值是以"/" 结尾,则代表的是一个文件夹。
  read-file-name-completion-ignored-case ,值为non-nil 表示忽略大小写,nil 为不忽略大小写。

四、Minibuffer 历史
  在Minibuffer中的每次输入都保存在Minibuffer的历史当中,我们可以很方便的调出之前输入的某次命令。
  M-p 移到Minibuffer历史中的前一条,previous-history-element。
  M-n 移到Minibuffer历史中的后一条,next-history-element。
  M-r regexp RET 移到Minibuffer历史中的前一条,使用正则表达式,previous-matching-history-element。
  M-s regexp RET 移到Minibuffer历史中的后一条,使用正则表达式,next-matching-history-element。
  提醒一下,这些要Minibuffer处于激活状态才能使用。每次移动后取出的历史会替换当前的输入,而当我们在最后一条记录时继续使用M-n,还是会照样出现一条记录,不过这个记录是Emacs猜的。此外还需要说明的是,Emacs 维护了多个不同的历史,比如我们打开文件的路径历史,或者我们调用编译器的编译参数历史,而Emacs搜索历史也是在相应的历史列表中进行。
  关于Minibuffer历史的参数常用有两个,history-length 历史队列最大值,history-delete-duplicates 是否删除相同的历史。都是字面意思就不仔细说了。
  如果我们现在在主窗口也可以快速的调出最近执行的命令,使用C-x ESC ESC (repeat-complex-command)再执行一次最近的Minibuffer中的命令,Emacs会提示你是否执行。我们还可以使用M-p, M-n 来选择其他的历史。命令M-x list-command-history 可以列出最近所有的历史。
  最后说下Minibuffer历史的本质,它们都是储存在Lisp变量command-history中项,其中每一项都保存的每次执行的命令和参数。

小结:
  这次讲的东西不少哈。


按键


命令


作用

(none) set-variable 设置变量
C-M-v scroll-other-window 向下滚动另一个窗口
M-PageDown 同上 同上
C-M-S-v scroll-other-window-down 向上滚动另一个窗口
M-PageUp 同上 同上
TAB minibuffer-complete 自动补全Minibuffer
SPC minibuffer-complete-word 自动补全Minibuffer中一个词
RET minibuffer-complete-and-exit 提交Minibuffer
? minibuffer-completion-help 列出所有可能补全
RET(候选列表中) choose-completion 选择候选项
previous-completion 上一个候选项
next-completion 下一个候选项
C-x k kill-buffer 关闭一个buffer
(none) icomplete-mode 自动更新补全模式
M-p previous-history-element 前一历史
M-n next-history-element 后一历史
M-r (regexp) previous-matching-history-element 前一历史,使用正则表达式
M-s (regexp) next-matching-history-element 后一历史,使用正则表达式
C-x ESC ESC repeat-complex-command 重复最近一次命令
(none) list-command-history 列出所有命令历史

  


变量


作用

insert-default-history 打开文件是否插入默认路径
resize-mini-window Minibuffer大小变化模式
max-mini-window-height Minibuffer最大高度
enable-recursive-minibuffers 是否允许Minibuffer递归调用
completion-auto-help 自动补全帮助模式
completion-ignored-extensions 自动补全忽略后缀名列表
read-file-name-completion-ignored-case 自动补全是否大小写敏感
history-length 自动补全历史长度
history-delete-duplicates 自动补全是否删除重复项

  
ps:文中出现的高亮文本含义,红色为快捷键,前几章也是这么用的;绿色为命令,即按M-x 后输入的内容;蓝色为Emacs的变量名。

未完待续。。。

时间: 2025-01-07 09:07:52

Emacs教程(四)的相关文章

史上最详细的Android Studio系列教程四--Gradle基础

史上最详细的Android Studio系列教程四--Gradle基础

微信开放平台 公众号第三方平台开发 教程四 代公众号调用接口的SDK和demo

原文:微信开放平台 公众号第三方平台开发 教程四 代公众号调用接口的SDK和demo 教程导航: 微信开放平台 公众号第三方平台开发 教程一 平台介绍 微信开放平台 公众号第三方平台开发 教程二 创建公众号第三方平台 微信开放平台 公众号第三方平台开发 教程三 一键登录授权给第三方平台 微信开放平台 公众号第三方平台开发 教程四 代公众号调用接口的SDK和demo 前几章中我讲解了微信开发平台提供第三方平台的好处,和使用流程,如果你看了我的文章相信你对开放平台有了初步的了解,但是在实际的开发过程

Junit 4 Tutorials(Junit 4 教程) 四、Junit4 参数化测试

Junit 4 参数化测试 允许通过变化范围的参数值来测试方法.参数擦测试可以通过以下简单的步骤实现: 对测试类添加注解 @RunWith(Parameterized.class) 将需要使用变化范围参数值测试的参数定义为私有变量 使用上一步骤声明的私有变量作为入参,创建构造函数 .创建一个使用@Parameters注解的公共静态方法,它将需要测试的各种变量值通过集合的形式返回. 使用定义的私有变量定义测试方法 Junit 4 参数化测试样例 EvenNumberChecker.java 校验输

Swift中文教程(四)--函数与闭包

原文:Swift中文教程(四)--函数与闭包 Function 函数 Swift使用func关键字来声明变量,函数通过函数名加小括号内的参数列表来调用.使用->来区分参数名和返回值的类型: 1 func greet(name: String, day: String) -> String { 2 return "Hello \(name), today is \(day)." 3 } 4 greet("Bob", "Tuesday")

Quartz教程四:Trigger

原文链接 | 译文链接 | 翻译:nkcoder 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣研究源码的同学,可以参考我对quartz-core源码的注释(进行中). 与job一样,trigger也很容易使用,但是还有一些扩展选项需要理解,以便更好地使用quartz.trigger也有很多类型,可以根据实际需要来选择. 最常用的两种trigger会分别在教程五:SimpleTrigger和教

BootStrap入门教程 (四)

上讲回顾:Bootstrap组件丰富同时具有良好可扩展性,能够很好地应用在生产环境.这些组件包括按钮(Button),导航(Navigation),缩略图( thumbnails),提醒(Alert),进度条(progress bar)等,能够很好减少前端工程师的代码量,实现更加丰富充实的页面. Bootstrap作为一套良好的前端工具,要实现现代的动态页面效果,javascript插件是必不可少的.它提供了12个基于JQuery类库的插件,包括模态窗口(Modals),滚动监控(Scrolls

CRL快速开发框架系列教程四(删除数据)

本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框架系列教程四(删除数据) CRL快速开发框架系列教程五(使用缓存) CRL快速开发框架系列教程六(分布式缓存解决方案) CRL快速开发框架系列教程七(使用事务) CRL快速开发框架系列教程八(使用CRL.Package) CRL快速开发框架系列教程九(导入/导出数据) CRL快速开发框架系列教程十(

Laravel教程 四:数据库和Eloquent

Laravel教程 四:数据库和Eloquent 此文章为原创文章,未经同意,禁止转载. Eloquent Database 上一篇写了一些Laravel Blade的基本用法和给视图传递变量的几种方式, 这一节我们来说说跟数据库打交道的数据库配置和Laravel强大的Eloquent. Laravel的数据库配置 本部分内容为下节做准备 Laravel的配置文件都是在项目目录的config/文件夹之下,这里也就是在blog/config文件夹之下,你可以打开这个文件夹看看,你面有很多配置文件:

Git的入门教程<四>

Git 的入门教程<四> 5> git分支的管理 git默认的有一个主分支叫做master,随着每次的提交,master主分支会形成一条线,而HEAD是指向当前的主分支master的,一般来说,我们将master分支作为向外发布的主分支,而开发的时候会新建一个分支或者好多分支,作为开发分支,等到开发分支完成,在一次性的想master主分支上合并,并进行发布. 5.1 git 分支的创建.删除.切换 git branch dev //创建分支 git checkout dev //切换分支

Flask实例教程四

一:Flask处理请求和回复 Flask和Werkzeug提供了request和response对象去处理请求和回复的数据.Flask通过@app.route包裹的函数(后面我们称这个函数叫做视图函数),来响应请求. 视图函数返回的值可以分为三类: string:返回的就是普通的字符串. 一个response的实例:具备HTTP属性的一个响应的对象的实例.通过make_respone来构建 一个元组:(string,status)或者(string,status,http_headers)这样的