在js2-mode中,全局变量会自动为我突出显示:
如何在Emacs lisp中执行相同的操作?我希望能够在以下内容中突出显示flymake-log-level
和barr
:
(defun foo ()
(let (bar baz)
(setq baz flymake-log-level) ;; flymake-log-level isn't locally bound
(setq barr (1+ flymake-log-level)))) ;; misspelled bar
答案 0 :(得分:4)
可以通过安装flycheck来利用字节编译器。 Flycheck是flymake的替代品,并且支持Elisp。
对于第一个示例,它不会帮助您,但它会在第二个示例中出现(假设存在必要的require
):
(require 'flymake)
(defun foo ()
(let (bar baz)
(setq baz flymake-log-level) ;; no complaints here
(setq barr (1+ flymake-log-level)))) ;; assignment to free variable `barr'
还有hl-defined.el,这是一种次要模式,几乎完全符合问题所描述的内容。安装它,然后在emacs-lisp-mode缓冲区中运行hdefd-highlight-mode
。然后,您可以运行命令hdefd-cycle
,直到您只显示尚未定义的变量。这给出了类似的东西:
(这不是完美的,hl-defined不承认fn
是一个参数而不是一个自由变量,它将函数list
与这里使用的参数混淆。但是,它是对问题中描述的用例非常有帮助。)
最后,一些软件包包括突出显示它们定义的功能。例如,dash.el为其函数提供突出显示,以及它在回指宏中使用的变量名称(即突出显示it
)。
;; Enable syntax highlighting of dash functions
(eval-after-load "dash" '(dash-enable-font-lock))
答案 1 :(得分:2)
我想说这是相当多的工作......
最好的方法是使用font-lock-mode
并添加新规则。通常,规则包含匹配某些内容的正则表达式,但是,使用函数执行此操作也是合法的。然后,此函数可以搜索标识符,并且对于每个标识符,它可以通过检查变量是否出现在参数列表中,let
,dolist
或类似构造中来检查它是否在本地绑定。 / p>
类似于cwarn mode的包的一个示例,它突出显示(除此之外)表达式内的赋值,用于类C语言。
答案 2 :(得分:2)
我认为甚至不可能准确地突出显示变量绑定范围,或者至少在没有实际涉及字节编译器(或其部分)的情况下,或者重新实现Emacs Lisp语义的部分内容。
关键问题是宏。这些在Emacs Lisp中不卫生。因此任何
宏可以引入任意本地绑定。事实上,许多宏都这样做,例如来自标准库的dolist
,condition-case
和pcase
,或来自dash.el的照应列表处理函数,以命名受欢迎的第3个党的图书馆..
使用这些宏,仅从语法上下文确定变量作用域变得不可能。请看以下示例:
(condition-case err
(--each my-fancy-list
(my-fancy-function it nil t))
(error (message "Error %S happened: %s" (car err) (cadr err))))
在不知道condition-case
和--each
的情况下,err
和it
是否在本地绑定?如果是这样,它们绑定的子表达式,例如,是err
绑定在所有子表达式中,还是只绑定到处理程序表单(后者是这种情况)?
要确定此类情况下的变量范围,您需要维护宏的详尽白名单及其绑定属性,或者需要扩展宏以动态确定其绑定属性(例如,在中查找let
扩展的身体)。
这两种方法在实施时都相当多,并且有缺点。宏定义的白名单几乎是自然不完整,不正确和过时的(只需查看pcase
的复杂绑定语义),而扩展宏需要存在宏定义,但情况并非总是如此,例如您正在使用前面提到的dash.el编辑Emacs Lisp,而实际上并未安装此库。
尽管如此,扩展宏可能是最好的努力,甚至更好,你不需要自己实现它。 Emacs Lisp字节编译器已经这样做了,并且它警告了对自由变量的引用,并且还启用了关于未使用的词法变量的词法绑定。所以,字节编译你的文件!
充其量,避免在正在运行的Emacs中调用byte-compile-file
,而是在新的Emacs实例中编写Makefile
字节编译,以获得干净的环境:
SRCS = foo.el
OBJECTS = $(SRCS:.el=.elc)
.PHONY: compile
compile : $(OBJECTS)
%.elc : %.el
$(EMACS) -Q --batch -f batch-byte-compile $<
在更复杂的库中,使用-L
标志来设置适当的Emacs
load-path
用于编译。