[生无可恋]怎么从零为新语言提供一个major mode

image

问题说明

我最近有点学懵了,查资料半天查不到想要的东西
我想自己写一个major mode做个练习,没想到好难啊,难得我前列腺炎都犯了

这是我的test.ne文件,我需要写一个nemode来给这种文件提供功能

/*
  hello world
  I am Steiner
*/

#include <stdio.h>

int main() {
  printf("hello world\n");
  char * str = "hello world !";
  return 0;
}

/* I like Julia language */
// and I also like Clojure too

<h1> Hello World </h1>

我的配置

1. 为不同的标识设置不同的face

需要高亮keyword, type, html-tag,string, function,

;; define face for all type
;; first is keyword
(defface neface/keyword
  nil
  "Face for keyword")
;; next is type
(defface neface/type
  nil
  "Face for type")


;; function face
(defface neface/function
  nil
  "Face for function")

;; for tag
(defface neface/tag
  nil
  "Face for tag")
;; for string
(defface neface/string
  nil
  "Face for string")

(face-spec-set 'neface/keyword
	       '((t :foreground "red"
		    :weight bold
		    :underline t)))


(face-spec-set 'neface/type
	       '((t :foreground "yellow"
		    :weight bold
		    :underline t)))

(face-spec-set 'neface/function
	       '((t :foreground "green"
		    :weight bold
		    :underline t)))

(face-spec-set 'neface/tag
	       '((t :foreground "blue"
		    :weight bold
		    :underline t)))
(face-spec-set 'neface/string
	       '((t :foreground "magenta"
		    :background "red"
		    :weight bold)))

(setq neface/keyword 'neface/keyword
      neface/type 'neface/type
      neface/function 'neface/function
      neface/tag 'neface/tag
      neface/string 'neface/string)

2. 设置匹配的正则表达式

(setq regex-keyword (concat "^#include " "\\|" "\\<return\\>")
      regex-type (concat "\\<int\\>" "\\|" "\\<char\\>")
      regex-tag (concat "<h1>" "\\|" "</h1>")
      regex-function "\\w+(.*)"
      regex-str "\".*\""
      highlights `(
		   (,regex-keyword . neface/keyword)
		   (,regex-type . neface/type)
		   (,regex-function . (1 neface/function))
		   (,regex-tag . neface/tag)
		   (,regex-str . neface/string)))

3. 整合为nemode

(define-derived-mode nemode prog-mode "nemode"
  (setq font-lock-defaults '(highlights)))

发现问题

图片

正则匹配了也不高亮

给你们看看,我也是醉了

无法匹配字符串

无法匹配标签

无法匹配函数

还有一些不会设置的东西

1. 缩进

比如说,在c文件中随便按Tab键,他就会帮你弄好缩进,但是自定义major mode该怎么定义缩进啊?
我这样设置tab-width,按了几下Tab就变这样了

(define-derived-mode nemode prog-mode "nemode"
  (setq-local font-lock-defaults '(highlights))
  (setq-local indent-tabs-mode t)
  (setq-local tab-width 4))

2. 函数渲染?

在李杀的教程里有这样一个例子来改变文字属性

(defun x-make-word-red (begin end)
  "make current region colored red, using text properties"
  (interactive (list (region-beginning) (region-end)))
  (put-text-property begin end 'font-lock-face '(:foreground "red")))

哪有没有方法在mode加载的时候调用这种函数,匹配到文字后修改其文字属性

3. defcustom和defground

查文档的时候这两个宏看不懂,不知道这两玩样怎么使

4. syntax-table 的语法

英文实在看不懂,这是什么反人类的语言

最后有个吐槽

给条活路吧,让我用其他语言配置好不好
花了3天时间学习配置,现在的我只想安安静静的敲代码,去他妈的自动检查,去他妈的自动补全,去他妈emacs-lisp,我还是去学Java
image

4 个赞

https://ksqsf.moe/blog/howto-emacs-major-mode/

以前写过一个简单的小总结……不过你这个需求看起来比我当时的复杂很多,仅供参考吧……

edit: 缩进这部分还可以用 SMIE,文章里面没提到。

1 个赞

没有中文吗? :joy:

快进到钻研Javascript转用VSCode成为大神,并发表文章我为什么放弃Emacs

7 个赞

emacs终究是不适合急功近利。既然已经尝试过了,说明可能并不适合lz,拥抱vscode吧,别有心理负担。如果有一天依然羡慕其他emacser,欢迎回来,嗯! :blush:

1 个赞

如果有人能重构Elisp和Emacs,让他更简单,我就是失身也要学这玩样

我想问一下,作为一个Emacs老手,有必要去掌握Major Mode的编写吗,通常学到哪里就可以了
minor-mode呢?

所谓Emacs老手就是不断学习,不断打磨自己的Emacs, 并且乐于分享,有自由软件精神的人。Emacs老手的Elisp编程水平不一定顶尖,Emacs里的功能和Elisp,需要用到就去学习,不需要用的暂时放一边。

研究编辑器就是为了优化自己的工作流程,不要学得像坐牢,为了学而学。英语是一个很重要的工具,尽量掌握,掌握不了用Google DeepL 百度翻译辅助掌握。

难道你想付钱给别人然后别人给你颁个证你就是Emacs老手了?

利益相关:不太会写major mode但是会写minor mode

7 个赞

elisp就是用到再去看的嘛,我是觉得elisp水平和你说的这些弱相关就是了(逃

不过一定要给出大概的技能包的话,

会写一个从当前目录进行递归搜索并跳转到具体位置的工具就行了(rg,grep随便),也就是到一些简单的字符串处理+命令行的交互+一些跳转函数的运用.

3 个赞

不需要. 基于自己的需求. 我是没碰到过要自己写major mode的情况, 如果太麻烦, 我可能就考虑不用emacs来干这件事情.

这个"利益相关"有点skr :zipper_mouth_face:

elisp没有很难,学不会也不要着急。过几天再看看,你现在主要是不冷静。写程序遇到障碍很正常。这不是emacs的问题,emacs提供了极好的elisp文档,所有精妙都在文档和代码之中,这也要求楼主的英语水平。不喜欢的话也没所谓,可以用别的语言做,elisp不背锅。

要写major mode可以看这个介绍:

  • 不需要定义自己的face,应该使用标准的 font-lock-keyword-face 这些。
  • 需要把syntax-table配置对,这样才能正确扫描字符串、注释这些。
  • 可以从一个类似的语言的major-mode衍生出你的major-mode
  • 看英文文档是无法避免的。
  • 更多时候是看别人的elisp的代码来发现怎么做一个功能。

同意楼上的观点,不要折磨自己。用别人写好的包一时爽,一直用就一直爽。这样最好了。

4 个赞

我没从头写过major mode。我写的Lisp代码集中在改善工作流(文本文件操作,命令行和脚本整合等等)。技术上都很简单。

1 个赞

如果从头写major-mode 困难,可以先找一个语法和你需求相近的major-mode,看懂它,然后修改一下就能用啦。我之前就以basic-mode 为基础改了一个自己所需要的。

2 个赞

这个老手说的是你啊 :kissing_smiling_eyes:

我觉得应该专注于如何把emacs用于工作中,提高工作效率才是要紧事(如把其它工具集成到emacs里面来用)

写major mode没什么实用价值,发明新语言是证明自己能力的一个好办法,但是也只能自己用,因为要考虑到别人的感受,王垠好像有篇讲DSL的文章结论是应该尽可能的避免发明新语言,我觉得还是有点道理的

1 个赞

好吧,我调整一下学习方向

猜测楼主似乎是想作为一门语言来学习 emacs-lisp?

这样的话个人觉得 elisp 不是个特别好的选择, 不如先去学些正统的语言, 比如楼主提的 Java, 学会之后用处也比 elisp 多.

elisp 里面陈旧的东西比较多, 从现代的观点看有不少设计不够科学. 而且很多东西和编辑功能是绑定的, 比如一些字符串处理, elisp 有可能需要你把字符串放进一个编辑器 buffer 里面, 处理之后再读出 buffer 内容. 如果不是作为 emacs 的配置语言的话, 我猜很少有人会愿意用它.

2 个赞

说起这个,auctex对于cls和sty等tex文件的支持近乎没有,连基本的高亮和缩进都没有,真的感觉挺不方便