第一声问候

前一篇《Emacs 是一台计算机》

理解了 Emacs 身为计算机的本质之后,在 Emacs 里编程就顺理成章了。不过,在此之前,还需要略微介绍一下 Emacs 最基本的操作。

系统的不一致,令人有点烦躁

现在,也可以坦然地说,Emacs 是一台虚拟的计算机,目前,它只能在宿主操作系统中运行,而这个宿主操作系统可以是 Windows、Linux 或 Mac OS X。由于这个世界上绝大多数计算机所运行的操作系统不外乎这三者之一,因此无需担心无 Emacs 可用。

现在假设你对自己所用的操作系统足够熟悉,至少达到能够从 https://www.gnu.org/software/... 页面找到与自己所用的操作系统匹配的 Emacs 版本的安装包并成功安装的程度,那么我就假设你的操作系统中已经存在了一个可用的 Emacs。此外,我还得假设你知道怎么打开你所用的操作系统的命令行窗口。

命令行窗口,在 Windows 里,叫控制台或命令行提示符,而在 Linux 与 Mac OS X 里,则称为终端(Terminal)。

实际上,Windows 里所谓的命令提示符,这真的是一个很奇葩的名字,它实际上是以命令行窗口中里 > 符号的名字。在 Linux 与 Mac OS X 的终端里,命令提示符是 $。所谓命令提示符,意思是在这个符号的后面可以输入命令,这个符号本身不需要你输入。下文以 $ 作为命令提示符。

启动 Emacs 的命令如下:

$ emacs

执行这条命令之后,可以得到如图 1 所示的窗口,这或许是你有生以来第一次看到 Emacs,记住这一天。

接下来,在 Emacs 里执行第一个命令 C-x C-f。这是 Emacs 特色的组合按键序列的表现形式,其含义:摁住 Ctrl 键,单击 x 键;摁住 Ctrl 键,单击 f 键。执行这一命令后,观察 Emacs 窗口,它的底栏应该会出现 Find file: ... 字样,其中 ... 是 Emacs 的当前工作目录的路径。在此,我不得不继续假设你知道在一个操作系统中一个工作目录的路径指的是什么。或许 Windows 用户对此不甚了解,下面略作解释。

当你打开 Windows 命令提示符窗口的时候,窗口中应该会出现像下面这样的字样:

C:\Users\用户名 >

这个 C:\Users\用户名 就是当前的工作目录的路径。

再回到 C-x C-f 按键在 Emacs 底栏召唤出来的 Find file: ...,现在,在 ... 之后输入 foo.txt,然后击回车(Enter)键,这样便在工作目录中创建了一份名称为 foo.txt 的文本文件。这份文件没有什么特殊意义,它只不过是为了让你体验 Emacs 而随便创建的一份文本文件。

从现在开始,将 Emacs 用于接受我们输入 foo.txt 文件名的底栏称为微缓冲区(Minibuffer)。微缓冲区是我们向 Emacs 传递各种按键序列以及命令的通道。

当 Emacs 在工作目录中创建一份新的文件时,它会在微缓冲区上方的窗口中为这份文件创建一个缓冲区。这个缓冲区就叫缓冲区,它对应一块内存区域,可以与硬盘上的文件相关,也可以无关。以后,当我谈及「缓冲区」的时候,指的就是微缓冲区上方的缓冲区。

我们在缓冲区中编辑文本,在需要将所编辑的内容保存到与缓冲区相关联的文件里之时,只需向 Emacs 发出 C-x C-s 指令——摁住 Ctrl 键,击 x 键;摁住 Ctrl 键,击 s 键。

C-x C-fC-x C-s 这样的组合键,由于每组按键都需要摁住 Ctrl 键,因此可以采用类似「英文连读」的方式减少按键次数,即摁住 Ctrl 键,依次单击 xf,或依次单击 xs

我们对 Emacs 的操作暂时只需了解这么多。倘若你学有余力,可继续阅读我写的另一份文档 [1]。

hello, world

这个世界上,被重复写过最多的一个程序,它的名字叫 hello world。始作俑者是《The C Programming Language》的作者 Brain Kernighan。无数初学编程的人,用这个程序向计算机软件世界发出了第一声问候。

在 Emacs 中,我们不妨也贯彻一下这个仪式。在上一节所建立的 foo.txt 文件缓冲区里输入 hello, world

对此,请不要吝惜发出~噫~的声音!

若真的是这样的 hello world,不论是谁,都会感到失望。不过,由于我此前将 Emacs 的窗口(还记得俄罗斯方块吗)称为显示器。这种直接在缓冲区里键入 hello, world 的方式其实很黑客,这是直接修改 Emacs 的显存内容啊!

发出~噫~的声音的人说,散了,散了,他就这两下子!

当然不是。要通过一段程序,在 Emacs 窗口中显现 hello, world,这需要了解一下 Emacs 的启动配置文件 init.el。要了解这个文件,需要继续为三大操作系统的不一致而烦躁。

Emacs 的 HOME 目录

init.el 文件是 Emacs 的启动配置文件。它应该位于 HOME 目录的 .emacs.d 子目录中。

对于 Windows 用户,倘若你的操作系统安装在 C 盘。对于 Windows 7 或更新的版本,Emacs 会将 C:\Users\<用户名>\AppData\Roaming 作为默认的 HOME 目录。对于 Windowx 2000 或 XP,Emacs 会将 C:\Documents and Settings\<用户名>\Application Data 作为 HOME 目录。对于……Windows 就是这样麻烦啊,倘若对此很烦躁,建议使用 Linux,或阅读 Emacs 文档中对 Windows 的 HOME 目录的说明 [1]。

对于 Linux 与 Mac OS X 而言,由于它们有点血缘关系,因此它们的 Emacs HOME 目录就是 $HOME~,亦即操作系统的 HOME 目录。

函数

init.el 文件是 Emacs 的配置文件。现在,假定你已经能够在自己的系统中找到 Emacs 的 HOME 目录。接下来,就在这个目录中创建 .emacs.d 目录,然后使用 Emacs 在这个目录创建 init.el 文件。使用其他文本编辑器并非不可,但是不要浪费使用 Emacs 编辑文件的实践机会。

每当 Emacs 启动时,它都会读取 init.el,认真贯彻这个文件中的一些设定。因此,我们可以在这个文件中写一个 hello world 程序,让 Emacs 能够在缓冲区中显现 hello, world。以后,这个文件就是我们在 Emacs 环境里的编程实验场地。

在开始写这个 hello world 程序之前,先体验一下如何通过 init.el 调整 Emacs 的外观。

在 init.el 文件中写入以下内容:

; 关闭菜单、工具栏、滚动条
(tool-bar-mode 0)
(menu-bar-mode 0)
(scroll-bar-mode 0)

然后重新启动 Emacs,发现它的菜单、工具栏以及滚动条都不见了。

上述内容,以 ; 开头的语句是 Emacs Lisp 的注释语句,会被 Emacs 忽略。之后的三行语句,对于 Emacs 而言,是三个程序,因为之前很认真地说过,Emacs 是计算机。init.el 中的内容,对于 Emacs 而言就是一组指令,而每条指令都可以视为一个程序。

由于我们通常所遇到的程序往往是由很复杂的代码构成。将这简短的三行代码视为三个程序,有煞有介事之嫌。那么,我们就将它们称为表达式。对于 Emacs 而言,init.el 中的每对小括号包含的文本,只要它不属于注释语句,对于 Emacs 而言都是表达式,要牢记这一点。

(tool-bar-mode 0) 为例,这个表达式可以让 Emacs 在启动时关闭工具条。倘若将这个表达式改为 (tool-bar-mode 1),那么下次开启 Emacs 的时候,工具条又会被打开。显然,是语句中的 01 决定着 Emacs 是关闭还是打开工具条。

假设你曾经认真学过中学数学,想必还记得函数吧?y = f(x),以映射的记法可写为 f: x -> y。倘若将 tool-bar-mode 视为 f,将 01 视为 x,将工具条的关闭与打开这两种状态视为 y,那么 (tool-bar-mode 0)(tool-bar-mode 1) 在 Emacs 环境中所产生的作用,像不像 f: x -> y?

因此,像 tool-bar-mode 这样的事物,在 Emacs 里,是函数。上面在 init.el 中写入的三行语句,实际上是对三个函数进行求值。是谁在对函数进行求值,是 Emacs Lisp 解释器!

定义一个函数

接下来,我们可以在 init.el 中定义一个函数,即在 init.el 文件的尾部新开一行,然后写入以下内容:

(defun hello-world ()(interactive)(insert "hello, world"))

倘若你的确是按照我说的,使用 Emacs 编辑 init.el 文件,那么此刻只需使用 C-x C-s 便可将上述内容保存到 init.el 文件中,

现在关闭 Emacs,然后重新启动它,再重新打开刚才创建的 foo.txt 文件。这样 Emacs 便会重新读取 init.el 文件,但是这次它会读取上述语句。先不考虑 Emacs 对它们作何处置,现在,先在 Emacs 中尝试输入 M-x hello-world <RET> 命令,看看会缓冲区里会出现什么。这条命令里的 M-x 表示摁住 Alt 键,然后单击 x,然后松开 Alt 键,接下来继续输入 hello-world,然后单击回车键。由于在 Emacs 中,每当使用 C-xM-x 时,Emacs 都会认为你要向它发出命令,所以它会使用微缓冲区接受你后续的输入。我的表述虽然有些冗长,但是倘若你真的动手尝试两三次,就自会明白这一切。

向 Emacs 发送 M-x hello-world <RET> 命令之后,结果会怎样呢?结果就是在 Emacs 当前的缓冲区里出现了 hello, world

这是我们向 Emacs 世界发出的第一声真正的问候。

函数的定义是表达式

对于 Emacs 而言,像

(defun hello-world ()(interactive)(insert "hello, world"))

这样的语句,虽然它似乎有些特殊——可以形成一条指令,但它依然是一个表达式。上文曾说过,在 init.el 中,每对小括号包含的文本,只要它不属于注释语句,对于 Emacs 而言,都是表达式。上述文本虽然比 (tool-bar-mode 0) 这样的表达式更复杂了一些,但由于它是以 ( 开始又以 ) 结尾,所以它是一个表达式。前文也说过,Emacs Lisp 解释器会对表达式进行求值。那么对于上述表达式,求值结果是什么呢?现在若不过于探究细节的话,不妨将这个求值结果视为在 Emacs 环境里定义了一个名为 hello-world 的函数,并且这个函数不接受任何参数。

不接受任何参数的函数,相当于一个常量函数,类似于 y = 1 这样的函数。因此,上述的 hello-world 函数是一个常量函数,函数值永远为 (insert "hello, world"),这对于 Emacs 而言,又是一个表达式,而这个表达式是对 insert 这个函数进行求值。求值结果是什么?就是在缓冲区中出现 hello, world,这就是 Emacs 对在响应 M-x hello-world <RET> 命令后,对 hello-world 函数的最终求值结果。

为什么 hello-world 的求值结果不是 (interactive) 呢?能在不清楚 (interactive) 这个表达式的含义的前提下提出这个问题的人,都是好同学。

hello-world 函数进行求值,本质上是对 hello-world 所包含的一组表达式进行求值。hello-world 包含了两个表达式:

(interactive)
(insert "hello, world")

它们构成了 hello-world 函数的实体。函数的实体与函数的名称通过 (defun ...) 表达式绑定到一起,这就是所谓的函数定义。

Emacs Lisp 解释器对 (defun ...) 这种表达式的求值逻辑较为特殊,它会顺序地对嵌入这一表达式中的子表达式按照先后进行排序,将最后一个表达式的求值结果作为函数的求值结果。

(interactive) 也是一个表达式,暂时不需要关心它对 Emacs 起到了什么作用—— Emacs Lisp 解释器对它的求值结果,由于它位于 (insert "hello, world") 之前,所以它的求值结果没有资格作为 hello-world 的求值结果。

公仆与民众

那么,(interactive) 的求值结果是什么?让 (defun ...) 定义的函数成为 Emacs 命令——可在微缓冲区执行的命令。

可以试着从 hello-world 函数中去掉 (interactive),即 hello-world 的定义变为:

(defun hello-world ()(insert "hello, world"))

然后保存 init.el 文件,再重新启动 Emacs,再重新打开刚才创建的 foo.txt 文件,然后再次执行 M-x hello-world <RET> 命令,就会发现,Emacs 根本不知道你在做什么。

因此,在 Emacs 的世界里,有两种函数,一种是可以作为命令执行的函数,它们就像通常所谓的程序一样,另一种则是普通的函数,它们默默无闻、甘于奉献,为那些可以作为命令使用的函数贡献了光和热。

重启不是必要的

在上文中,每次修改了 init.el 文件的内容之后,为了验证修改的结果,需要关闭 Emacs 再重新启动它,然后再次打开 foo.txt。这种操作过于繁琐,造成了人民日益增长的美好生活需要和不平衡不充分的发展之间的矛盾。

事实上,我们可以打开两个 Emacs 窗口,一个用于编辑 init.el,另一个用于体验 init.el 中的改动的效果,即用于编辑 foo.txt 文件。不妨前者称为「哼」窗口,将后者称为「哈」窗口。我们在「哼」窗口中所作的任何改动,保存到 init.el 文件中之后,在「哈」窗口中,只需执行 M-x load-file <RET> ~/.emacs.d/init.el <RET>,便可让修改后的 init.el 在「哈」窗口中生效。这条命令中的 ~ ,Emacs 会将其视为 HOME 目录路径的简写。

以后,随着对 Emacs 熟悉程度的增进,或者在阅读文档 [1] 之后,会发现打开两个 Emacs 窗口也是不必要的。

下一篇:勤劳,还是懒惰?

[1] 走近 Emacs

[2] Emacs 文档对 Windows 系统中的 HOME 目录的说明

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

破解支付宝AR红包

支付宝新出的AR红包没多久&#xff0c;就有人破解了&#xff0c;大致原理是将上面的像素条遮挡下面的黑条&#xff0c;基本上得到模糊的图就可以扫到红包。不过现在大多是ps解决&#xff0c;那得有多麻烦啊&#xff0c;所以我用java写了一个&#xff0c;效果还不错。 先截屏&am…

在 Windows 上搭建配置 Jenkins 然后编译打包 VS 项目

在 Windows 上搭建配置 Jenkins 然后编译打包 VS 项目独立观察员 2022 年 7 月 6 日一、安装1、下载并安装 JRE &#xff08;Java 运行环境&#xff09;。2、下载 Windows 版本的 Jenkins 安装包并安装。3、安装 Visual Studio&#xff0c;以供编译项目使用。4、安装 Advanced …

【ArcGIS微课1000例】0007:基于数字高程模型DEM生成剖面线、剖面图

文章目录 效果预览数据分析工具介绍生成过程剖面图编辑保存、导出剖面图实验数据下载效果预览 数据分析 本实例使用到的原始数据为案例提供的规则格网DEM

[转]javaandroid线程池

java多线程-概念&创建启动&中断&守护线程&优先级&线程状态&#xff08;多线程编程之一&#xff09;java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()&#xff08;多线程编程之二&#xff09;java&android线程池-Exe…

.Net下极限生产力之efcore分表分库全自动化迁移CodeFirst

开始本次我们的主题就是极限生产力,其他语言望尘莫及的分表分库全自动化Migrations Code-First 加 efcore 分表分库无感开发还记得上次发布博客还是在上次,上次发布了如何兼容WTM框架后也有不少小伙伴来问我如何兼容如何迁移等问题,经过这么多框架的兼容我自己也认识到了一些问…

Hadoop日常管理与维护

本文描述了hadoop、hbase的启动关闭、表操作以及权限管理。一、Hadoop服务的启动与关闭1、启动使用hadoop以及hbase自带的脚本进行启动&#xff0c;先启动hadoop个服务&#xff0c;再启动hbase服务。 hadoopbdi:~$ start-dfs.sh hadoopbdi:~$ start-yarn.sh hadoopbdi:~$ start…

Mathematica修改默认字体

1. 打开Option Inspector 2. 第一个下拉框选择Global Preference, 搜索stylehints 3. 修改字体为想要换的字体FamilyName, 比如换成苹果黑体 SimHei, 字体FamilyName自行研究 4. 效果 转载于:https://www.cnblogs.com/dabaopku/p/6221960.html

基于JavaScript 数组的经典程序应用源码(强烈建议收藏)

文章目录设计一个数组输入并显示的程序。数组输入和显示选择排序选择排序排序程序包排序网页杨辉三角形杨辉三角形网页C语言画一个sin(x)的曲线螺旋线访问二维数组JavaScript数组的定义、使用都是非常简单的&#xff0c;仅仅定义的话&#xff0c;就使用&#xff1a; var anew …

【ArcGIS微课1000例】0008:ArcGIS中如何设置相对路径?(解决图层前红色的感叹号)

文章目录 问题举例问题分析解决办法问题举例 我们在使用ArcGIS时经常会碰到这样的问题:将地图文档(.mxd)保存到本地并拷贝到别的电脑上或改变一个路径时,出现数据丢失的现象,具体表现为图层前面出现一个红色的感叹号,如下图所示。 出现以上问题的根本原因是数据GSS.tif的…

[转]OKR结合CFR的管理模式

读前预 无论任何管理书籍&#xff0c;都是围绕着人性&#xff0c;如果激发员工的人性中的自尊和自我价值观、自我成就感。 作为一名领导者&#xff0c;在管理前&#xff0c;必须要是冷静&#xff0c;安静的对待他人 约翰杜尔为谷歌送上大礼 “好主意”再加上”卓越的执行”&…

NetCore 国际化最佳实践

NetCore 国际化最佳实践ASP.NET Core中提供了一些本地化服务和中间件&#xff0c;可将网站本地化为不同的语言文化。ASP.NET Core中我们可以使用Microsoft.AspNetCore.Localization库来实现本地化。但是默认只支持使用资源文件方式做多语言存储&#xff0c;很难在实际场景中使用…

复分析——第1章——复分析准备知识(E.M. Stein R. Shakarchi)

第一章 复分析准备知识 (Preliminaries to Complex Analysis) The sweeping development of mathematics during the last two centuries is due in large part to the introduction of complex numbers; paradoxically, this is based on the seemingly absurd no…

【ArcGIS微课1000例】0009:ArcGIS影像拼接(镶嵌、镶嵌至新栅格)

本课程以 DEM数据为例,讲述ArcGIS中影像的拼接方法及注意事项。 文章目录 方法一:Mosaic工具方法二:Mosaic To New Raster工具实验数据下载观察两个数据,接边处切合效果很好。 方法一:Mosaic工具 使用Mosaic工具要千万注意,Mosaic的结果是将输入栅格追加到目标栅格上,…

C语言试题170之矩阵转置

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:设有一矩…

【ArcGIS微课1000例】0010:ArcGIS影像裁剪(裁剪、掩膜提取)

文章目录 裁剪方法方法一:Extract By Mask(按掩膜提取)方法二:Clip(裁剪)数据下载裁剪方法 方法一:Extract By Mask(按掩膜提取) 加载配套的实验数据,运行Extract By Mask(按掩膜提取)工具,参数设置如下: 掩膜提取结果: 方法二:Clip(裁剪) 加载配套的实验…

阿里创新自动化测试工具平台--Doom

背景 信息系统上线后通常会需要迭代升级甚至重构&#xff0c;如何确保系统原有业务的正确性非常重要。曾经有一家叫瑞穗证券的证券公司因为一个系统bug导致了数亿美金的损失&#xff0c;赔掉了公司一年的利润。这样的极端例子虽然少见&#xff0c;但是却像达摩克利斯之剑警示着…

《微信读书》自定义样式

一直用微信读书看书&#xff0c;但是微信读书的Web版的布局不太喜欢。 重写下它的样式再加上单击关闭工具栏&#xff0c;这样看着舒服多了^_^&#xff1a; /*浮动工具栏*/ document.getElementsByClassName("readerControls")[0].style.left"0"; document.…

C# NanoFramework WIFI扫描、连接和HttpWebRequest 之 ESP32

可喜可贺新板子终于到了&#xff0c;啥也不说&#xff0c;赶紧搞起来。ESP32的主要功能就是WIFI&#xff0c;有了WIFI &#xff0c;就可以直接连接家里的WIFI路由器啥的&#xff0c;直接连接到外网了&#xff0c;这个时候&#xff0c;它就相当于是一个小型的电脑或手机&#xf…

【ArcGIS微课1000例】0011:ArcGIS空间查询(按位置选择Select by Location)完全案例详解

利用按位置选择工具,您可以根据要素相对于另一图层要素的位置来进行选择。例如,如果您想了解最近的洪水影响了多少家庭,那么可以选择该洪水边界内的所有家庭。 您可使用多种选择方法,选择与同一图层或其他图层中的要素接近或重叠的点、线或面要素。 文章目录 1、点—点查询…

[转]收集android上开源的酷炫的交互动画和视觉效果:Interactive-animation

原文链接&#xff1a;http://www.open-open.com/lib/view/open1411443332703.html 描述&#xff1a;收集android上开源的酷炫的交互动画和视觉效果。 1.交互篇 2.视觉篇 交互篇 1.SlidingUpPanelLayout 项目介绍&#xff1a;他的库提供了一种简单的方式来添加一个可拖动滑动面板…