[重复造轮子] websocket-bridge

1. 背景

使用 deno-bridge 来扩展 Emacs 很好用。它的逻辑是:在 emacs 和 deno 两边都启动 websocket ,然后通过 websocket 通信。根据不同的消息来运行不同的命令。整个结构相当的简洁,并且很够用。

只是 deno 现有的包还是比较少。有一些需求难以找到现有的实现。

例如:我现在需要获取本地 chrome 已有的 cookie, deno 没有现有的包。但是 python 有很好用的 pycookiecheat。

本来打算使用 python-epc 来完成我的需求。但 epc 并没有 deno-bridge 简洁。因此看了一下 deno-bridge 的代码,应该可以很容易的移植到 python

epc 不足之处:

  • 由于 epc 太老旧。新版的 Emacs 并不能直接使用,需要修改 epcs
  • 每次写新的包,都需要在 emacs 和 python 端都启动 server 通信
  • 使用、管理没有 deno-bridge 简洁。

由于 deno-bridge 的核心就只是 websocket 通信。因此可以抽象出一个 websocket-bridge ,emacs 端,启动一个 websocket server, 外部每一个插件都是一个 websocket connect 。 因此插件的实现可以是任何语言。

2. 实现

目前只实现了 python 版,理论上使用任何语言 + 对应 websocket-client 即可。

  • emacs 服务端实现:websocket-bridge , 基于 deno-bridge 实现,缩减了部分代码,emacs 部分只启动一个 websocket-server, 负责接受所有 client 的连接。
  • python 客户端实现:websocket-bridge-python

3. 插件

根据自己英文阅读,写作的需求。打算实现两个包:

  1. websocket-bridge-grammarly 使用 grammarly sdk 进行英文写作的语法校验。
  2. dictionary-overlay 使用词典、或者在线翻译对 buffer 中的生词进行翻译渲染展示。

3.1. dictionary-overlay

dictionary-overlay 已经初步可用。

在帖子 【讨论】一种提升英文阅读体验的可能性 - #52,来自 skywind3000 中有这个项目的一些细节讨论。

3.2. websocket-bridge-grammarly

websocket-bridge-grammarly 还在开发阶段。选择开发这个插件的原因是:已有的 lsp-grammarly、eglot-grammarly 不支持登录链接到 grammarly 的个人帐号。如果使用免费版本,其实使用 lsp-grammarly eglot-grammarly 应该已经很好用了。

16 个赞

哇, 大佬, 你要把Emacs英语学习的插件提升到全新的高度啊, 热烈期待, 抢沙发。

grammarly 针对个人使用是收费的吗? 还是注册一个个人账号就好了?

grammarly 不注册帐号应该也可以免费使用。这里有一个 lsp server

只是 emacs 版本的不能连接个人帐号。好像 vscode 的可以。

目前我还不确定收费帐号有没有什么高级功能。但淘宝先买了一个。

websocket-bridge 看起来是很通用的,我觉得这个思路很好。期待能有更多插件,能上melpa,甚至elpa :grinning:

websocket-bridge.el 本身比较的简单。只是定义了 emacs 和外部应用的通信方式。上不上melpa,好像对用户的差别不大。

主要还是需要有更多可用的插件,这些插件的核心功能都不是 elisp 实现的,这就和 melpa 远了。

我个人是个 Java 开发。所以我最大的需求是:emacs 可以和 IntelliJ IDEA 进行通信,在 emacs 中运用到 idea 的高级功能,使用 lsp 进行 java 开发还是不太给力。(等什么时候研究一下idea的api,看看能否可行)

当年有一个大佬做过一个 idea 的lsp server,可惜不维护了。

2 个赞

核心上就行了,插件可以另外处理。或者带几个杀手级的插件一起发布。我是不是理想化了 :joy:

哈哈。难有杀手呀。

赞!

选择只用一个websocket-server而不是可以启动多个的考虑是啥? 感觉每个插件如果能启动自己的server是不是更稳妥点?互相之间可以隔离,不至于一个server出问题,所有插件都不工作了。

不过我没看你的实现,对websocket也不怎么了解,就是凭空想的一个问题。

仅仅只是能简单点,便于管理而已。否则 process 里一堆 websocket-server 。

websocket-server 本身并不容易出问题,它的实现逻辑比较简单。理论上只有手动 kill 了进程才会消失。

使用一个emacs 长驻的 server 。后续的管理,都只需要管理 client 就可以。新增,重启,server 都可以不动。

我是赞同这个观点的,通讯机制或者每个插件一个websocket都不是太大事情。

因为RPC本身没有价值,应用代码才有价值。

每个插件的进程单独kill本身可能才是最佳实践。

grammer 检查就是一个啊 :joy:

其实用了很久的atomic-chrome就是用的websocket来实现的,还有实时预览markdown的插件、org-roam-ui也是这么做的。效率确实很高,也不容易出问题。

大佬看看这个是不是类似的

有意思的插件写起来

这个包有点类似。不过它没有提供 eval-code 这样万能的接口,而是通过 porthole-expose-function 明确哪些函数可以使用。

emacs 还有一个更老的rpc 包:GitHub - kiwanami/emacs-epc: A RPC stack for Emacs Lisp

功能上,epc 已经比较完善了。lsp-bridge 之类的在使用。只是由于包比较老,可能需要自己fork 根据需求改一些东西。

由于“太长不看”的原因,就借鉴deno-bridge 的模式,实现了一个理论上可以应用任何其他语言的版本。主要就是看重了,互相通信的简洁性。

我是觉得rpc 调用明确注册方法能够避免方法调用的滥用。不过为了简单,使用 eval-code 会比较方便。

其实 rpc 注册方法那个很容易被绕过, 你把 elisp eval 函数注册给外部语言, 外部语言就可以随意 eval 了。

实践证明, eval code 这种方法才是实用的。

1 个赞

也太棒了 !