为 Emacs 增加新语言支持

发布于 2025-03-02 22:35:56 字数 5305 浏览 6 评论 0

能否编写一个 major mode 是是否能称为 elisp hacker 的分水岭. 你早晚都会遇到一种编程语言或者一种配置格式是 Emacs 尚不支持的.原因可能是它们是才出现不久,也可能是因为它们太小众了。

最终,你会决定卷起袖子开始填坑. 那么你该如何编写一个 major mode 呢?怎样才算是一个好的 major mode 呢?

入门

创建一个最少功能的 major mode,你只需要设置 syntax table 即可,只要你的 mode 能高亮出注释和字符串,那就是有用的

下面是一个最简化的 JS mode:

  (defconst my-js-mode-syntax-table
    (let ((table (make-syntax-table)))
      ;; ' is a string delimiter
      (modify-syntax-entry ?' "\"" table)
      ;; " is a string delimiter too
      (modify-syntax-entry ?\" "\"" table)

      ;; / is punctuation, but // is a comment starter
      (modify-syntax-entry ?/ ". 12" table)
      ;; \n is a comment ender
      (modify-syntax-entry ?\n ">" table)
      table))

  (define-derived-mode my-js-mode prog-mode "Simple JS Mode"
    :syntax-table my-js-mode-syntax-table
    (font-lock-fontify-buffer))

Here’s the result:

看起来并没有作什么工作,但对于配置文件来说,一般够用了。恭喜你,你现在已经是一名 elisp hacker 了! 将你的 major mode 发布到 MELPA 上吧,这样大家可以使用并贡献給你的新 mode。

完全的语法高亮

从这里开始,存在一个很大的扩展空间了,你需要看一下 sophisticated syntax highlighting,这篇文章囊括了一门语言的所有语法说明。

随着你的 major mode 变得越来越复杂,你应该开始考虑如何对它进行测试了,虽说许多 major mode 确实都没有测试,但是像你这么一位自重的 hacker 是很乐意看到 bug 被修复的 (but a self-respecting hacker like you likes bugs to stay fixed).

第一步是创建一个包含各种特殊语法情况的案例文件然后打开它,这种方式很繁杂,最终你会想用程序来进行测试。puppet-mode 就是一个很好的例子 .

缩进

下一步该处理缩进的问题了. 用于希望 Emacs 在任何状态下都能正确地缩进代码,你需要检查光标附近的语法然后计算出当前的嵌套层级。

为了计算当前的嵌套层级,你往往需要从光标当前位置向后搜索整个 buffer,并计算出现 { (或其他等价的作用域分隔符) 的次数. 然后再根据嵌套层级调整当前行的缩进位置(一般是将嵌套层级乘于 my-mode-tab-width ),若你仔细的处理了字符串和注释中的 { ,这种方式往往能行。

还有一种方法,Emacs 提供了 Simple Minded Indentation Engine (SMIE). 你只需要写好 BNF 语法,然后你就能生成基础的缩进与移动命令了。

You could be a total lunatic, and Emacs has to make you happy.
– Steve Yegge on indentation

在实际中,对什么才是正确的缩进是有争议的,因此为了适应不同的缩进风格,你可以需要提供一些配置项供用户自己调整. 若一切正常的话,你应该能做: 到从一个现存的项目中打开一个大文件,然后运行 (indent-region (point-min) (point-max)) , 结果缩进并不会有什么改变。

缩进的逻辑测试起来很简单,你可以参见 julia-mode 中的例子. 你还需要测试在大文件中缩进是否足够快速,因为一不小心就可能应用了缓慢的算法。

实时检查

若能为 flycheck 添加一个 linter 那必是极好的. 然而即使尚没有成熟的 lint 工具,能够实时高亮语法错误也不错。

flycheck-pyflakes 标示出未用的变量

补全

一个好的 major mode 能够提供自动补全的功能. 你可以通过编写 company 后端来为 major mode 提供补全的能力. 下面这些例子也许能给你一些灵感:

company-clang ( company 的一部分) 使用 Clang 来发现结构体成员:

company-c-headers 搜索本地文件系统来提供补全 C 头文件的建议

pip-requirements 在 internet 上搜索可用的 package 列表

Eldoc

Eldoc 是一个在 minibuffer 显示光标所在内容相关信息的 minor mode,一般被用于提示函数前面或变量类型,但你可以用它来提示任何一样东西。

假设你你的 major mode 能进行一些静态分析,使用 eldoc 来显示上下文相关信息是一种很好的方式。

用 eldoc 显示 elisp 中的 docstrings:

c-eldoc 显示光标所在函数的函数原型:

整合 REPL

最后,最完美的 major mode 会允许你直接在 Emacs 中以交互的方式运行代码。

Emacs 提供了一个 comint-mode ,该 mode 允许你自定义解析器,并在 Emacs 中运行该解析器. 许多 major modes,尤其那些 Emacs 自带的 major mode,都是继承自 comint-mode 的。

cidersly 这样的项目整合 REPL 的程序甚至比 comint-mode 还要高. 这些包允许你通过解释器进程查询文档字符串,进行自动补全,宏扩展等等其他很多内容。

cider 将 Emacs 和 Clojure REPL 完美的整合在一起了:

Polish

Emacs 一开始就内建支持 C 语言编程,而且 这种支持直到 2015 年还在不断的改进 ! 尽早发布,经常发布,你会创造精品。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

听你说爱我

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文