Emacs 29 发布在即,其中亮点功能就是内置了对 tree-sitter 支持。tree-sitter 除了可以实现高亮外,还可以支持更加准确的结构化导航和编辑,以及代码折叠(比如 ts-fold )等等。不知道目前流行的类似包有哪些?一起交流对比下?
最近看到Master Emacs 作者在 他的网站 介绍 tree-sitter 的使用,并推荐他的结构化编辑插件:combobulate 。
初步使用下来,感觉还不错。
按 C-c o o 就会弹出类似 magit 的 transient 菜单,帮助开始不熟悉时看看:
按 M-P 和 M-N 可以快速拖动 node(可以是很多种对象,取决于光标的位置。比如,如果光标在 python 中的 def 上,就是拖动函数):
8 个赞
多谢猫哥,原来之前有分享过。
刚试了下,感觉 fingertip 是用来替换 paredit 的。
下面补个fingertip的链接,方便不了的朋友。
1 个赞
mark 等分享。在 idea 里特别喜欢的功能估计需要借助 treesit 来实现:
快速移动语法块,看起来就是lz分享的 M-P 和 M-N ,idea 里也是根据当前的最大语法块来移动的,并能根据被移动的位置来决定移动位置。比如向上移动一个方法,如果上一行是一个方法的结尾,就会移动到上一个方法之上。如果上一行是普通代码,就移动到这行普通代码之上;
expand region。根据语法扩展选区,在idea 里是 alt 加上下键,快速扩展选区到单词/字符串/括号/方法等
基于语法的折叠,正好看到了 ts-fold,目前是基于 treesitter,基于 treesit 的还是 WIP
对于你提到的这几点:
combobulate 中的 M-P 和 M-N 就是你要的,看第二张动图的效果。
combobulate 也有了,按 M-h 激活选取,然后按 TAB 就可以扩展了(而且在minibuffer 还有按键提示)。
折叠功能,也在作者的开发计划中,可以跟踪这个新功能请求的issue 。
另外,目前 combobulate 对 C/C++ 的支持正在施工当中,可以关注这个 PR:Start trying to add support for C and C++ by chriselrod · Pull Request #29 · mickeynp/combobulate · GitHub
我今天在 Python 中体验了一天,很好用,期待后续的功能加强。
1 个赞
org
2023 年5 月 28 日 14:39
6
关于emacs的treesitter,我倒是没有使用;不过在neovim的应用中,我觉得GitHub - mfussenegger/nvim-treehopper: Region selection with hints on the AST nodes of a document powered by treesitter 非常好,和狗哥的 meow 的 meow-inner-of-thing/meow-bounds-of-thing 异曲同工,不过 nvim-treehopper是根据treesitter选中,meow有它自己的规则。
另外,我觉得假如扩展meow的treesitter能力会是一件有趣的事,因为原本meow就是先选中后动作的模式,meow-mark-word/meow-next-word这样的设计在原本的文本上做标记非常直观。而meow-inner-of-thing/meow-bounds-of-thing 并不算直观。假设移植了类似nvim-treehopper,会让操作更统一。
1 个赞
先选中再动作比较直观。否则光标所在位置,都不太清楚是属于哪个块。
org
2023 年6 月 5 日 03:48
8
是的,我是认为先选中后动作直观,我讲的那个nevim插件就提供了一种选择块的方式,和meow-inner-of-thing/meow-bounds-of-thing的选中方式相比,更为直观。
meow-thing-register
这个函数可以注册自定义的 thing, 然后用 tree-sitter 来找到边界就可以。参见这个函数的注释。
至于其它的函数,因为 meow 是用按键来调用的底层命令,所以只需要改良版的命令替换掉旧的命令,比如说 forward-word 如果被替换成基于 ts 的 forward-word, 只要绑定还是 M-f
就可。
感觉全面转向 *-ts-mode
非常困难,最大的问题就是这些 mode 基本上都是从 prog-mode
上重新开发的。以 go-mode
为例,go-mode-map
中有用户的大量 key-bindings,以及 lsp
flycheck
org-babel
等以及 golang 的一大堆工具集成,转到 go-ts-mode
后什么都干不了。如果以原有的 go-mode
为 parent mode
那估计就可以无缝迁移了。
Try try 这个
先删掉 go-mode,然后在 go-ts-mode 加载后执行,这样会创建一个新的 go-mode 继承自 go-ts-mode
(define-derived-mode go-mode go-ts-mode "Golang")
(dolist (ext '("\\.go\\'"))
(setf auto-mode-alist (assoc-delete-all ext auto-mode-alist))
(add-to-list 'auto-mode-alist `(,ext . go-mode)))
1 个赞
我现在还在用tree-sitter mode,这个是minor mode,并且不需要啥额外配置。
个人也是比较喜欢 minor-mode 这种方式。
2 个赞
原来 ts-docstr 居然是论坛中高人做的?
我折腾了一晚上,没能成功用起来。能够指导一下?
我在一个 c 文件的一个函数上调用 ts-docstr-at-point
,ts-docstr 它提示我:
user-error: Ignored, tree-sitter-mode is not enabled in the current buffer
于是我手动调用:tree-sitter-mode
,这时候是 tree-sitter 提示我:
tree-sitter--setup: No language registered for major mode ‘c-ts-mode’
我发现该提示是 tree-sitter--setup
抛出来的:
(defun tree-sitter--setup ()
"Enable `tree-sitter' in the current buffer."
(unless tree-sitter-language
;; Determine the language symbol based on `major-mode' .
(let ((lang-symbol (alist-get major-mode tree-sitter-major-mode-language-alist)))
(unless lang-symbol
(error "No language registered for major mode `%s'" major-mode))
(setq tree-sitter-language (tree-sitter-require lang-symbol))))
(unless tree-sitter-parser
(setq tree-sitter-parser (tsc-make-parser))
(tsc-set-language tree-sitter-parser tree-sitter-language))
(add-hook 'before-change-functions #'tree-sitter--before-change :append :local)
(add-hook 'after-change-functions #'tree-sitter--after-change :append :local))
因为 tree-sitter-major-mode-language-alist
为 nil,导致 (lang-symbol (alist-get major-mode tree-sitter-major-mode-language-alist))
的 lang-symbol 为 nil 而报错。
于是我增加配置 (add-to-list 'tree-sitter-major-mode-language-alist '(c-ts-mode . c))
再次手动调用 tree-sitter-mode
,这时候出现新的错误:
tree-sitter-load: Cannot find shared library for language: c
可是我在 /Users/c/.emacs.d/tree-sitter/
文件夹下确实是有 libtree-sitter-c.dylib
文件。
我现在不知道如何解决。
大概你没在配置里 (require 'tree-sitter-langs)
,这不是 Emacs 自带的包,而是那个第三方的 tree sitter 绑定提供的功能
.emacs.d/tree-sitter/
是 Emacs 自带 treesitter 的路径,和这个第三方的不一样
1 个赞