第一聲問候

前一篇《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.pswp.cn/news/285099.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285099.shtml
英文地址,請注明出處:http://en.pswp.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…

C#實現清理系統內存

金山內存整理工具、360內存清理工具非常好用&#xff0c;可以將系統內存最小化&#xff0c;提升系統運行速度。其實這些事情C#也可以做到&#xff0c;原理就是對系統進程中的進程內存進行逐個優化。 網上大多推薦使用系統的SetProcessWorkingSetSize的函數API&#xff0c;但是經…

C語言試題168之獲取矩陣的最大值及其下標

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:要求使用…

.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 …

C語言試題169之誰家孩子跑得最慢

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:張、王、…

【ArcGIS微課1000例】0008:ArcGIS中如何設置相對路徑?(解決圖層前紅色的感嘆號)

文章目錄 問題舉例問題分析解決辦法問題舉例 我們在使用ArcGIS時經常會碰到這樣的問題:將地圖文檔(.mxd)保存到本地并拷貝到別的電腦上或改變一個路徑時,出現數據丟失的現象,具體表現為圖層前面出現一個紅色的感嘆號,如下圖所示。 出現以上問題的根本原因是數據GSS.tif的…

IPC-----消息隊列

消息隊列&#xff08;報文隊列&#xff09;:兩個進程間通過發送數據塊的形式進行通信。一個進程把需要發送的消息通過一個函數發送到消息隊列中&#xff0c;另一個進程再從消息隊列中讀取該消息。函數&#xff1a;# include <sys/types.h># include <sys/ipc.h>key…

[轉]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…

網構軟件-Internetware

網構軟件&#xff0c;973項目提的一個概念。概念。作為一種新型軟件形態&#xff0c;它應該涵蓋哪些研究范疇&#xff1f;評價它成功的基本標準是什么&#xff1f;我們看待一件事物&#xff0c;首先都會從已知的認知空間里尋找與之對應者。那么&#xff0c;能與網構相對應的大概…

List集合的remove一個對象的方法

import java.util.ArrayList;import java.util.List;class A{   public boolean equals(Object obj){     return true;   }} public class ListTest2 { public static void main(String[] args) {   // TODO Auto-generated method stub     System.out.println…

【ArcGIS微課1000例】0009:ArcGIS影像拼接(鑲嵌、鑲嵌至新柵格)

本課程以 DEM數據為例,講述ArcGIS中影像的拼接方法及注意事項。 文章目錄 方法一:Mosaic工具方法二:Mosaic To New Raster工具實驗數據下載觀察兩個數據,接邊處切合效果很好。 方法一:Mosaic工具 使用Mosaic工具要千萬注意,Mosaic的結果是將輸入柵格追加到目標柵格上,…

Python:file (read,readline,readline )使用方法

Python讀取文件時&#xff0c;在使用readlin、readlines時會有疑惑&#xff0c;下面給大家詳解&#xff1a;一、例&#xff1a;a.txt的內容為 aaa 123 bbb 456二、首先我先設置個變量&#xff1a; a"a.txt" cfile(a)三、此時我們分別看下使用read、readl…