可以。但我们这里讨论的是设计一套用 clojure 写插件系统,就好像在搭网线,网线搭好后访问什么网页都可以,系统搭建好后想写什么插件就写什么插件,到那时在讨论要不要写一套 LSP 才更好。
waypipe 怎么样
今天已经实现了基本框架:
- Elisp到Clojure的异步调用方法
- Clojure到Elisp的异步消息发送
- Clojure到Elisp的异步方法调用
- Clojure到Elisp的同步函数执行
- Clojure到Elisp的同步变量读取
这5个接口基本上就是Clojure扩展Emacs的全部核心函数。
接下来的工作:
- Clojure接到的Elisp请求全部封装到线程中,保证Clojure的处理函数不会卡住
- Elisp这端支持多App, 不同的App可以启动不同的Clojure进程, 这样一个框架可以支持多个应用的独立启动、停止和重启
- Clojure核心框架代码封装成一个 Clojure 库, 这样新的扩展应用就写写Clojure的业务代码就好了, 不用拷贝代码
从实际的体验看, clj -M 来启动 Clojure 的启动速度很快, 执行速度也很快,关键是两边都是Lisp风格的代码, 不认真品, 都区分不出来两边的代码。
method :eval
和 method :async-eval
的格式怎么不一样。为何 :async-eval
就可以有一个额外参数 :func
指定函数名称,eval 就只能是列表?
改成 apply/funcall 能减少岐义
已经修改了, 等我周末再折腾折腾
Clojure 有很多种异步的方案,卡的问题感觉都不是问题,可能是哪里打开方式不对。
对接现有的 nrepl 或 socket repl 还是会更好一些,最大的好处就是可以直接对接上 clj, cljs, babashka 之类的,后端选择就很多。
特别是 babashka 很适合这个场景。
- 100ms 以内的启动时间
- clojure 完全一样的语法
- 自己有常用库的 pod ,基本上覆盖了这个实用场景
- 本身是二进制发布的
- 同样用了 vthread 支持异步(内置的 core.async 实现)
我感觉用 clojure 比 babashka 的优势在这个场景下只有一个,就是 clojure 可以用 libpython-clj 去无缝的调用 python 里面的函数。libpython-clj 虽然名称朴素了点,但其实是个很给力的东西。就看怎么取舍了。
我目前还是想构建了 python-bridge 一样的开发环境。
如果平常调试Elisp可以用 ielm, Clojure 调试用 Cider
Clojure 更像做成一个多进程TCP通讯的方式, 编译运行, 而不是解释执行, 我感觉解释执行容易把东西搞废。
clojure 还有 js版的
下面三点都搞完了:
- Clojure接到的Elisp请求全部封装到线程中,保证Clojure的处理函数不会卡住
- Elisp这端支持多App, 不同的App可以启动不同的Clojure进程, 这样一个框架可以支持多个应用的独立启动、停止和重启
- Clojure核心框架代码封装成一个 Clojure 库, 这样新的扩展应用就写写Clojure的业务代码就好了, 不用拷贝代码、
晚上试着写一个基于 cloel 框架的App出来。
Demo和文档都整完了, 欢迎大家试用, 一起用 Clojure 开发 Emacs 插件。
Cloel 吸取了 EAF 设计的经验, 基于 Cloel 开发Clojure插件是非常松散的, 只需要提供应用名称和应用Clojure文件的路径即可。
Clojure的开发体感很好, JVM生态很全, 而且从我实际体验看, 启动速度飞快, 大家习惯了, 我觉得基本上可以像 Lua 对 NeoVim 的作用一样大。
(defn ^:export elisp-eval-async [func & args]
(let [id (generate-call-id)]
(send-to-client {:type :call :id id :method :eval-async :func func :args args})
(future
(let [result (apply elisp-call :eval-async func args)]
result))))
猫大你看这是不是不对,怎么先 async-eval 了一次又在 future 中 async-eval 了第二次,两次的协议还不一样。另外 el 那边也没有 handle 第一次 call 的协议啊!
等我重构哈,zsbd
我早上把Clojure和Elisp代码都重构了一下, 清理了很多开发过程中的调试代码。
clojure(script)用了3,4年了。 开发体验相比于大部分主流语言真的是好很多(更不用说elisp)
欢迎大佬一起玩呀
架构已经搭建好了,欢迎大家贡献卡emacs的地方,我以后周末有空就去一个一个用clojure加速
今天开发了基于 cloel 的第一个插件 reorder-file
这个插件的作用很简单, Emacs传递一个Buffer的内容给 Clojure, Clojure 利用多线程代码自动分析文本的内容, 重新改变序号后, 把新的内容传递给Emacs进行更新, 具体的效果可以看这个补丁的内容 Reorder todo.md · manateelazycat/lsp-bridge@09e7f32 · GitHub
因为整个文件分析的代码都在外部 Clojure 进程的子线程执行的, 这样遇到超大文件的时候, 可以让 Clojure 自己去慢慢分析, 等分析完了以后再问用户是否要替换。
如果原来用Elisp实现也是可以的, 但是如果一旦文件非常大以后, Elisp就会卡住Emacs, 这时候用户啥也不能做。
用 cloel 开发这个插件很简单, 代码只有70行就轻松实现了, 而且Clojure的开发体验也是Lisp风格, 全程和Elisp的风格是一样的, 开发心流很一致。
学着做了一个生成随机 quote 的插件: