高手都是自称萌新的吗?
未来的大佬
是啊。。。。。
有时候学编程是为了学而学。比如看到 XXX 程序很厉害就去学编程,新手又不能一口吃成大胖子,一点一点学又很难耐住性子,最后只学会了 printf
又比如我一个朋友今年读计算机专业,学了 C++ 他跟我说:“不知道学了 C++ 有什么用”。C++ 本身的复杂度在,不可能直接上手参与开源 C++ 项目开发,更别说成熟的 C++ 项目都有像 CMake 或者 Autotools 的构建系统,还得学习这些东西,复杂度进一步提升。
Hack Emacs 的需求是现实需要的需求,是因为觉得 Emacs 某些地方不方便而去 hack。而且 Hack Emacs 十分方便,直接在编辑器里面写代码然后 eval 就行,通过 advice/hook 等机制直接微调已有插件的函数,立马出货。Hack 完 Emacs 自己的编辑体验确实得到了提高,这是个正向反馈的良性循环。
另外,用 Emacs 的各种语言的高手,在 Emacs 社区里学习,会接触到很多很有意思的东西。拓宽自己的视野,然后超脱出 Hack Emacs,成为真正的 Hacker。
“Multics Emacs是一个巨大的成功—编写新的编辑命令是如此的方便,以至于他办公室里的秘书们都开始学习怎么用了。他们使用的是一个介绍如何扩展Emacs的手册,手册里没说这就是编程。因此,秘书们并不认为他们在编程,也就没被吓跑。他们阅读手册,发现自己也可以做不少有用的事,他们学会了编程。”
— Richard M. Stallman 《我的 Lisp 经历与 GNU Emacs 的开发》
-
为了用 Python 跑点东西不要用 comint。用
start-process
之类的。Asynchronous Processes (GNU Emacs Lisp Reference Manual) -
学一下啥事 trie,这样我觉得两三千字的作文应该不至于卡
-
一堆
(second item)
是 common subexpression,应该 lift 出来。不过都改用 trie 了这个就算了。
楼上说了我再补充几句可能涉及一些“高级Elisp技巧的东西”
-
Emacs 27 用
json-parse-string
性能更好,这是基于 libjansson C 库的 JSON 解析,json-read-from-string
是用 Lisp 实现的 JSON 解析。另外 JSON array 我建议直接按默认变成 vector,然后用(aref array index)
来访问元素,因为转成链表之后虽然方便了,但是访问比较靠后的元素是没有 vector 的下标访问快的 -
用 comint 确实不太优雅,但是用 start-process 应该没法直接发送 Python expression 去给 Python eval。我的建议是学习一下 Emacs 的异步进程机制。先写一个 Python wrapper,从 stdin 接受字符串,然后把分词结果发送到 stdout。
-
cnhl-last-sentence
是一个很耗时的函数,放在after-change-functions
里面,每次变更都要运行,浪费时间。我的建议是加入 debounce – 每次触发时,放到一个 timer 里面,延迟 100ms 左右再执行,如果 timer 正在计时中,那就删除掉原来的 timer 重新计时,可以有效减少这种耗费时间的操作的执行。 -
上面提到
(second item)
是一个 pattern, 这时候可以引入 struct 来抽象化访问,比如用cl-defstruct
定义一个结构,然后写一个函数把 JSON 解析成这个结构,就可以通过 结构的 accessor 访问,更清晰。 -
chnl
里面有一个 cond, 里面有很多(member (second item) '("n" "ns" "ni" "nz" "r" "j")
这样的结构,这里可以使用pcase
模式匹配,让程序更易读。如
(cond
((member (second item) '("n" "ns" "ni" "nz" "r" "j" "np")) 'cnhl-shades-n-r-j)
((member (second item) '("u" "y" "h" "k" "e" "o")) 'cnhl-shades-u-y-h-k-e-o)
((member (second item) '("v" "id" "i")) 'cnhl-shades-v-i-id)
((member (second item) '("d" "c" "p")) 'cnhl-shades-d-c-p)
((member (second item) '("a" "f" "s" "t" "m" "q" "mq")) 'cnhl-shades-a-f-s-t-m-q-mq)
(t 'cnhl-shades-g-w-x))
重构为
(pcase (second item)
((or "n" "ns" "ni" "nz" "r" "j" "np")
'cnhl-shades-n-r-j)
((or "u" "y" "h" "k" "e" "o")
'cnhl-shades-u-y-h-k-e-o)
((or "v" "id" "i")
'cnhl-shades-v-i-id)
((or "d" "c" "p")
'cnhl-shades-d-c-p)
((or "a" "f" "s" "t" "m" "q" "mq")
'cnhl-shades-a-f-s-t-m-q-mq)
(_
'cnhl-shades-g-w-x))
关于 pcase, 论坛里有一个帖子
- 正则表达式用
rx
宏来写,更易懂
参见
那串正则可以改成
(rx
(or (group ",")
(group "。")
(group "?")
(group ";")
(group ":")
(group "、")
(group "‘")
(group "’")
(group "“")
(group "”")
(group "…")
(group "!")
(group "(")
(group ")")
(seq
(group "~")
"|"
(group "*"))))
谢谢!!谢谢各位前辈的宝贵经验!开始有干劲啦哈哈哈哈!
不敢不敢,是真的,学无止境而已
elisp 有hashmap的
我也入坑一年,和你比 差太多了,后浪推前浪,
不至于,我这才做了多么微不足道的一些事啊,大家才是真正有能力、有贡献的!一起加油!
这些天真的感谢大家!无论是各位前辈的热情帮助还是伟大的emacs本身,都实在是太让我感动了!此情非长歌无以言表,特作拙句以遗诸君:
辛丑咏emacs
铸炼琢磨五九年,春秋一去尔一坚。
力出盘古开寰宇,朗若云神御九天。
四海芳邻常伴侧,玲珑情虑每增添。
料得此心君身系,无奈今生爱恨间。
注: 五九年:自emacs1976年发布以来,已有五九四十五年;
云神:云中君,见《九歌》;
只是聊表心绪,字句不甚工整精炼,尾联一字还出了律,让大家见笑了
M-x poem
虽然不懂诗歌,但是这个帖子非常有趣
太牛了,这就是后浪吗
哎,我等前浪和有文化的后浪比,这就是差距啊。
是啊,佩服佩服。。。。
可别这么说,没啥文不文化的,我一没做出什么贡献,二没什么有意义的创造,各位前辈可比我强太多啦
我一直相信,无论什么事,只要认真干一干,付出那么些时间,都是必然可以获得相当的成就的,无论编程还是写作,任何事都是如此!大家大多都比我年龄大许多,智慧也比我高许多,只不过没有在我们看得见的地方罢了,这本也就无可厚非啦。
诗词什么的,如果有同学喜欢,可以手机里下个古诗文网,平常没事就跟刷公众号似的刷两篇;再多关注关注生活,像路边的花鸟草木啊身边的人啊什么的(我就很喜欢学校花园里碧桃树的紫叶和核桃树叶的芳香,还有老是在扑麻雀的花喜鹊,哦还特别喜欢春天的风,它真的是有香气的),清理清理心情,没过两周就有文思蹦出来啦!
如果想写点带格律的,可以买来《诗词格律》读一读,薄薄一本,也就30出头,没几小时就看完了;对填词感兴趣的可以额外看一本《填词丛谈》,不费什么功夫,倒也能为生活添一抹色彩!(总之不会比圆锥曲线难就是了 )
做时间的朋友,心态好,前途无量!
哈哈哈哈我来交作业啦!感谢 @cireu @LdBeth 两位前辈的批评和指导!
代码基本被我整个重写了一遍,足足有421行,而且竟然跑通了,不可思议,感觉自己创造了奇迹
在这个过程中我学到了巨多的东西,探索了很多新的技巧,也de了一堆bug什么的,让我想起了小学刚玩mc时把方块挨个放到地上鼓捣的经历,很有趣~
这里是代码,为了便于阅读,以及为了让我这个逻辑苦手写得下去,我尽可能多地加了注释
(defgroup cnhl-colors nil
"中文词性颜色"
:group 'cnhl-color)
;; 类比色
;; 红色系
(defface cnhl-n-r-j
'((t (:foreground "#F0B0A5")))
"名词、代词、简称颜色"
:group 'cnhl-colors)
(defface cnhl-np
'((t (:foreground "#F0A299")))
"人名颜色"
:group 'cnhl-colors)
;; 绿色系
(defface cnhl-v-i-id
'((t (:foreground "#C8E3A1")))
"动词、习语颜色"
:group 'cnhl-colors)
;; 橙黄色系
(defface cnhl-a
'((t (:foreground "#EDC7A8")))
"形容词颜色"
:group 'cnhl-colors)
(defface cnhl-f-s-t-m-q-mq
'((t (:foreground "#EDBD9D")))
"方位词、处所词、时间词、数词、量词、数量词颜色"
:group 'cnhl-colors)
;; 浅黄色系
(defface cnhl-d
'((t (:foreground "#EDE7A8")))
"副词颜色"
:group 'cnhl-colors)
(defface cnhl-c
'((t (:foreground "#EDE39D")))
"连词颜色"
:group 'cnhl-colors)
(defface cnhl-p
'((t (:foreground "#EDE891")))
"介词颜色"
:group 'cnhl-colors)
;; 中黄色系
(defface cnhl-u-y-h-k
'((t (:foreground "#D7C8A4")))
"助词、语气助词、前接成分、后接成分颜色"
:group 'cnhl-colors)
(defface cnhl-e-o
'((t (:foreground "#D6C299")))
"叹词、拟声词颜色"
:group 'cnhl-colors)
;; 其它
(defface cnhl-g-w-x
'((t (:foreground "gray80")))
"语素、标点及其它颜色"
:group 'cnhl-colors)
;; 浓度色
(defface cnhl-shades-n-r-j
'((t (:foreground "#FFD6CC")))
"名词、代词、简称颜色"
:group 'cnhl-colors)
(defface cnhl-shades-v-i-id
'((t (:foreground "#FFECC2")))
"动词、习语颜色"
:group 'cnhl-colors)
(defface cnhl-shades-a-f-s-t-m-q-mq
'((t (:foreground "#CCBC9B")))
"形容词、方位词、处所词、时间词、数词、量词、数量词颜色"
:group 'cnhl-colors)
(defface cnhl-shades-d-c-p
'((t (:foreground "#C0A199")))
"副词、连词、介词颜色"
:group 'cnhl-colors)
(defface cnhl-shades-u-y-h-k-e-o
'((t (:foreground "#998D74")))
"助词、语气助词、前接成分、后接成分、叹词、拟声词颜色"
:group 'cnhl-colors)
(defface cnhl-shades-g-w-x
'((t (:foreground "gray65")))
"语素、标点及其它颜色"
:group 'cnhl-colors)
;; 简化浓度色
(defface cnhl-shades-simple-n-r-j-v-i-d
'((t (:foreground "#FFECC2")))
"名词、代词、简称、动词、习语颜色"
:group 'cnhl-colors)
(defface cnhl-shades-simple-a-f-s-t-m-q-mq-d-c-p
'((t (:foreground "#DFD1B1")))
"形容词、方位词、处所词、时间词、数词、量词、数量词、副词、连词、介词颜色"
:group 'cnhl-colors)
(defface cnhl-shades-simple-u-y-h-k-e-o
'((t (:foreground "#A99D84")))
"助词、语气助词、前接成分、后接成分、叹词、拟声词颜色"
:group 'cnhl-colors)
(defvar *cnhl-color-scheme* nil
"cnhl中文词性高亮配色方案
nil代表类比色(色彩最丰富),simple代表简化浓度色(色彩最简单),其余值代表浓度色(红黄色系五色)")
(defun thulac-start ()
"启动python版thulac词性分析process"
(make-process
:name "thulac"
:buffer "*thulac*"
:command (list "python3" "-c" "import sys;import json;import thulac;t=thulac.thulac();exec('while True:print(json.dumps(t.cut(sys.stdin.readline()),ensure_ascii=False))')"))
;; 第一次实例化thulac时会耗费一段时间加载分析模型,加载完毕会输出"Model loaded succeed"作为提示
;; 使用accept-process-output等待加载完成。这段时间(大约数秒)emacs会卡住。
(accept-process-output (get-process "thulac"))
;; 绑定filter
(set-process-filter
(get-process "thulac")
'thulac-filter)
;; 退出emacs时自动杀掉thulac process
(set-process-query-on-exit-flag (get-process "thulac") nil))
(defvar *cnhl-hl-enable* t
"是否启用高亮,用于仅分词的情况")
(defvar *cnhl-last-info*
(list :beg nil :end nil :result nil :buffer nil)
"上一分析句的信息")
(defvar *cnhl-filter-timer* nil
"用于临时存储filter所用的timer")
(defvar *cnhl-major-mode* (list 'org-journal-mode 'org-mode 'text-mode)
"允许进行中文高亮的buffer mode")
(defvar *cnhl-whole-buffer* nil
"全buffer高亮模式开关变量")
(defun thulac-filter (process output)
"接收python thulac传回的中文分析结果,进行初步处理后执行操作函数"
(when (member major-mode *cnhl-major-mode*)
;; 使用python -c方式运行的process,单次输出较长的字符串时会被emacs分段读取传入filter(大约在第800C左右),
;; 执行python文件则无此问题。于是此处设置timer延迟执行,防止意外断句
;; 如果有正在准备执行的操作就干掉它重来
(when *cnhl-filter-timer*
(cancel-timer *cnhl-filter-timer*)
(setq *cnhl-filter-timer* nil)
;; 把新到的输出加进记录中
(setq output
(concat (plist-get *cnhl-last-info* :result)
output)))
;; 把输出记录下来
(plist-put *cnhl-last-info* :result output)
;; 设置timer
(setq *cnhl-filter-timer*
(run-at-time
;; 默认间隔0.05s足矣
"0.05" nil '(lambda ()
;; 若开启高亮则执行
(when *cnhl-hl-enable*
(cnhl-run))
;; 执行高亮后删掉自己
(setq *cnhl-filter-timer* nil)
;; 若启动全buffer高亮,则自动跳到下一行重复执行高亮
(when *cnhl-whole-buffer*
(goto-line (+ (line-number-at-pos) 1))
(cnhl)
;; 执行到buffer底部则退出全buffer高亮
(when (= (line-end-position) (buffer-end 1))
(setq *cnhl-whole-buffer* nil))))))))
(defun cnhl-current-word-info ()
"获取光标所在词的一系列信息,用于中文分词"
(interactive)
;; 若缓存中没有光标所在句的结果则对当前句执行高亮以获得信息
(unless (and (plist-get *cnhl-last-info* :result)
(string= (buffer-name) (plist-get *cnhl-last-info* :buffer))
(> (point) (plist-get *cnhl-last-info* :beg))
(< (point) (plist-get *cnhl-last-info* :end)))
(cnhl-sentence)
;; 等待分析结果出来,避免因为timer延时而导致的意外
(accept-process-output (get-process "thulac")))
(block body
;; 从前往后将每个词的结束位置与光标位置相比较,当某词词末大于光标位置时,该位置即为光标所在词词末
;; array - 句子分析结果;p - 光标词词末;prev-1 - 上一词词末;prev-2 - 上上词词末
(let ((array (json-parse-string
(plist-get *cnhl-last-info* :result)))
(p (plist-get *cnhl-last-info* :beg))
(prev-1 nil)
(prev-2 nil))
;; idx - 在遍历的词的位置;word - 在遍历的词
(do* ((idx 0 (1+ idx))
(word (aref (aref array idx) 0) (aref (aref array idx) 0)))
((< idx 0))
;; 挨个腾地儿
(setq prev-2 prev-1)
(setq prev-1 p)
(setq p (+ p (length word)))
;; 当正在遍历的词末位置大于光标位置时
(when (> p (point))
;; 返回本次词末,上词词末,上上词词末
(return-from body (list :end p :prev-1 prev-1 :prev-2 prev-2)))))))
(defun cnhl-forward-word ()
(interactive)
(if (member major-mode *cnhl-major-mode*)
;; 前往本词词末,即下一词词首
(goto-char (plist-get (cnhl-current-word-info) :end))
;; 若不在设置启用的major-mode中,则fallback回emacs默认的分词操作函数
(forward-word)))
(defun cnhl-backward-word ()
(interactive)
(if (member major-mode *cnhl-major-mode*)
;; 前往上上词词末,即上词词首
(goto-char (plist-get (cnhl-current-word-info) :prev-2))
(backward-word)))
(defun cnhl-backward-kill-word ()
(interactive)
(if (member major-mode *cnhl-major-mode*)
(let ((result (cnhl-current-word-info)))
;; 如果光标位置在词末,删掉上上词词末至上词词末,即上词词首至本词词首,即上一个词
(if (= (point) (plist-get result :prev-1))
(delete-region
(plist-get result :prev-2)
(plist-get result :prev-1))
;; 否则整个删掉光标所在词
(delete-region
(plist-get result :prev-1)
(plist-get result :end))))
(backward-kill-word 1)))
(defun cnhl-kill-word ()
(interactive)
(if (member major-mode *cnhl-major-mode*)
(let ((result (cnhl-current-word-info)))
;; 删掉上词词末至本词词末,即本词词首至下词词首,即本词
(delete-region
(plist-get result :prev-1)
(plist-get result :end)))
(kill-word 1)))
(defun cnhl-run ()
"根据存储的信息执行中文词性高亮"
(save-excursion
;; 清除高亮区域内已有的overlay
(dolist (overlay (overlays-in (plist-get *cnhl-last-info* :beg)
(plist-get *cnhl-last-info* :end)))
(delete-overlay overlay))
;; 光标移到句首
(goto-char (plist-get *cnhl-last-info* :beg))
;; 设变量num,从0开始遍历所有分析出的词语
(let ((num 0)
(output (json-parse-string (plist-get *cnhl-last-info* :result))))
(while num
(condition-case err
;; 选取item为output数组中的第num个词的分析结果,格式为数组,第0项为词语,第1项为词性标识
(let* ((item (aref output num))
;; 向前搜索item的第一项,即目标词语,记录词语后端位置,搜索范围仅限分析句内
(end (search-forward
(aref item 0)
(plist-get *cnhl-last-info* :end)))
;; 根据搜索出的位置新建overlay
(overlay (make-overlay
(- end (length (aref item 0))) end)))
;; 贴overlay的颜色
(overlay-put
overlay 'face
(if *cnhl-color-scheme*
(if (string= *cnhl-color-scheme* "simple")
;; 通过语法标识判断应选用的颜色
;; 简单浓度色(黄色系三色)
(pcase (aref item 1)
((or "n" "ns" "ni" "nz" "r" "j" "np" "v" "i" "d")
'cnhl-shades-simple-n-r-j-v-i-d)
((or "a" "f" "s" "t" "m" "q" "mq" "d" "c" "p")
'cnhl-shades-simple-a-f-s-t-m-q-mq-d-c-p)
((or "u" "y" "h" "k" "e" "o")
'cnhl-shades-simple-u-y-h-k-e-o)
(_
'cnhl-shades-g-w-x))
;; 浓度色(红黄色系五色)
(pcase (aref item 1)
((or "n" "ns" "ni" "nz" "r" "j" "np")
'cnhl-shades-n-r-j)
((or "u" "y" "h" "k" "e" "o")
'cnhl-shades-u-y-h-k-e-o)
((or "v" "id" "i")
'cnhl-shades-v-i-id)
((or "d" "c" "p")
'cnhl-shades-d-c-p)
((or "a" "f" "s" "t" "m" "q" "mq")
'cnhl-shades-a-f-s-t-m-q-mq)
(_
'cnhl-shades-g-w-x)))
;; 类比色(彩色)
(pcase (aref item 1)
((or "n" "ns" "ni" "nz" "r" "j")
'cnhl-n-r-j)
((or "u" "y" "h" "k")
'cnhl-u-y-h-k)
((or "v" "id" "i")
'cnhl-v-i-id)
((or "np")
'cnhl-np)
((or "a")
'cnhl-a)
((or "p")
'cnhl-p)
((or "d")
'cnhl-d)
((or "c")
'cnhl-c)
((or "f" "s" "t" "m" "q" "mq")
'cnhl-f-s-t-m-q-mq)
((or "e" "o")
'cnhl-e-o)
(_
'cnhl-g-w-x))))
;; 贴完了,num加一,开始处理下一个词
(setq num (+ num 1)))
;; 如果报错(如搜索出界),则停止当前句的高亮过程
(t (setq num nil)))))))
(defun cnhl (&optional beg end)
"中文词性高亮"
(interactive)
;; 清除可能意外存留的filter timer,防止因高亮过程意外终止,timer未正常清除导致的高亮失败
(setq *cnhl-filter-timer* nil)
;; 启动thulac
(unless (get-process "thulac") (thulac-start))
;; 若无参数运行,则默认取当前行
(unless beg
(setq beg (line-beginning-position))
(setq end (line-end-position)))
;; 记录字符串数据
(setq *cnhl-last-info*
(list :beg beg
:end end
:buffer (buffer-name)))
;; 将范围内的字符串送入thulac进行分析,结果返回至thulac-receive-output进行操作
(process-send-string
"thulac"
(concat
(string-trim (buffer-substring-no-properties beg end))
"\n")))
(defun cnhl-buffer ()
"对当前buffer全文逐行进行中文词性高亮"
(interactive)
;; 启动全文高亮后移动光标至顶部,开始进行高亮
(setq *cnhl-whole-buffer* t)
(goto-char (point-min))
(cnhl))
(defun cnhl-sentence ()
"对当前句进行中文词性高亮"
(interactive)
(save-excursion
;; 生成句读匹配的正则
(let* ((regxp (rx (or (group ",")
(group "。")
(group "?")
(group ";")
(group ":")
(group "、")
(group "‘")
(group "’")
(group "“")
(group "”")
(group "…")
(group "!")
(group "(")
(group ")")
(group "~")
(group "*"))))
;; 寻找语段起始结束位置,若无标点则直到行末
(end
(save-excursion
(or (search-forward-regexp regxp (line-end-position) t)
(line-end-position))))
(beg
(or (search-backward-regexp regxp (line-beginning-position) t)
(line-beginning-position))))
;; 对语段进行中文高亮
(cnhl beg end))))
(defvar *cnhl-sentence-timer* nil
"用于临时存储cnhl实时高亮的timer")
(defun cnhl-sentence-timely (&optional beg end len)
"中文实时高亮函数,加入after-change-functions以实现实时高亮输入内容"
(when (member major-mode *cnhl-major-mode*)
;; 删除准备执行的高亮
(when *cnhl-sentence-timer*
(cancel-timer *cnhl-sentence-timer*))
;; 安排高亮任务,延迟一段时间后执行,防止过于频繁地执行高亮造成资源浪费
(setq *cnhl-sentence-timer*
(run-at-time
;; 默认延迟0.1秒
"0.1" nil '(lambda ()
(cnhl-sentence)
;; 执行完删除自己
(setq *cnhl-sentence-timer* nil))))))
(defun cnhl-switch-color ()
"切换中文高亮配色方案"
(interactive)
;; 按照 类比 - 浓度 - 简化浓度 的顺序切换配色方案
(if *cnhl-color-scheme*
(if (string= *cnhl-color-scheme* "simple")
(setq *cnhl-color-scheme* nil)
(setq *cnhl-color-scheme* "simple"))
(setq *cnhl-color-scheme* ""))
;; 切换后对当前行重新高亮
(cnhl))
;; cnhl中文分词操作按键绑定
(global-set-key (kbd "M-f") 'cnhl-forward-word)
(global-set-key (kbd "M-b") 'cnhl-backward-word)
(global-set-key (kbd "M-d") 'cnhl-kill-word)
(global-set-key (kbd "M-DEL") 'cnhl-backward-kill-word)
;; 启用实时高亮输入内容
(add-hook 'after-change-functions #'cnhl-sentence-timely)
效果:
做出的改动有:
-
写了个粗陋的分词功能。因为thulac本身就有分词功能,想着不利用一下是不是浪费了 本打算抄一抄jieba.el的,却发现自己看不懂,只好写了个掰手指头式的实现 ……
-
使用process运行thulac,filter接收结果后调用执行高亮的函数。这里我把python代码写成了单行,避免了多出一个文件的窘境。不过这带来了一个奇怪的问题,在运行文件时无论句子有多长,python的输出都能被filter一次读取到,但在单行情况下用python -c运行,过长的输出就会被分段送进filter,我才疏学浅解决不了,只得多加个timer,郁闷(
-
语法上的小优化,像timer、pcase、aref、rx等的使用什么的;
cl-defstruct
我暂时没有用,一是我不太懂怎么用,二是我发现在使用array存储分析结果后,它的调用频率会相当的高,如果把结果中的每个数组都转成struct会不会造成浪费?……
trie有在学了,但不太清楚该怎么用,怕贪多嚼不烂我就没写进去qwq……刚好我们这两天的信息课在讲树形结构,为什么我就没认真听呢哈哈哈哈
就像 @cireu 前辈说的,hacking emacs给我以前所未有的干劲和快乐,它简单有趣,又让我觉得,我真的在创造有意义的东西。而且我认为,相比我玩过的其他语言,lisp系的语言最让我觉得合乎人的思维,让我感到有温度,有别的语言所没有的温暖的美,很难不爱上它~
谢谢大家的帮助!请各位前辈多多批评!
我爱emacs!