deno-bridge

我最近准备按照EAF类似的理念开发一个emacs-deno的项目,通过RPC建立emacs和deno的编程协作框架。

这样emacs可以透过deno建立与typescript, javascript, v8以及rust的协作编程方法。

这样非图形部分可以具备emacs-ng所有的能力,比如typescript, webworker, http, dom等先进库,同时不会像emacs-ng那样闹社区分裂。

PS: 图形的部分依然是EAF技术路线最成熟。

28 个赞

emacs 太重了,反而不能像vim那样重构?

意思是不是重新 clone 一份 emacs 源码做修改,而是作为一个 package 提供?

对,和EAF/lsp-bridge一样,就是一个外部插件,不需要修改emacs源码,把elisp当做胶水语言来处理。

这种多语言协作编程比现在emacs调用外部命令行工具后再用正则过滤要高效简洁很多,每个API都可以按照语意进行设计。

未来的目标会包括把 emacs-deno/python 作为 EAF / lsp-bridge 的底层抽象出来么?

emacs-deno应该会,EAF的底层其实就是lsp-bridge非lsp的代码,没有动力分离出来,不想为了维护框架而框架。

今天研究了一下 Emacs 和 Deno 的 Websocket 库, 实现了一个简单的版本 GitHub - manateelazycat/deno-bridge: Build bridge between Emacs and Deno, execution of JavaScript and Typescript within Emacs.

现在已经可以具备以下能力:

  1. Emacs 通过 Deno 调用任意TypeScript函数
  2. TypeScript 通过 messageToEmacs 接口发送消息到 Emacs minibuffer
  3. TypeScript 通过 evalInEmacs 接口执行 Elisp 代码
  4. TypeScript 通过 getEmacsVar 接口获取 Elisp 变量值

接下来的任务:

  1. 封装 deno-bridge 接口, 方便快速用 TypeScript 给 Emacs 开发插件
  2. 开发几个 TypeScript 插件来反过来完善 deno-bridge 本身
  3. 看看能否低成本的移植几个VSCode插件到Emacs这边来

Rust很快, 但是动态模块和强类型开发 Emacs 插件太难受了。 Deno 基于 V8 引擎, 所以 TypeScript 的性能应该要比 Python 快很多, 而且同时保留了脚本语言开发效率高的特点。

我抄了一下 emacs-ng 的README, 相对于 emacs-ng 的优势是不用修改Emacs的源代码, 也不挑 Emacs 的版本, 除了 WebRender 没法弄以外, emacs-ng 宣传的点应该都有, 比如 TypeScript, V8 JIT, Async IO, Rust Tokio, WebWorker, WebAssembly 等

10 个赞

Python插件 有 EAF, TypeScript 插件有 deno-bridge, Emacs应该不用怕 VSCode 和 Neovim 了。

deno-bridge 好了, 最大作用估计是方便从 VSCode 那边偷插件, 哈哈哈。

10 个赞

lsp-bridge 添加了对 Deno LSP Server 的支持 : Support Deno LSP server. · manateelazycat/lsp-bridge@e816f4b · GitHub

因为 Deno 也是用 TypeScript 来编程, 为了和平常 TypeScript 项目做区分, 需要定制选项 lsp-bridge-get-single-lang-server-by-project, 比如我自己的配置:

(setq lsp-bridge-get-single-lang-server-by-project
      (lambda (project-path filepath)
        (when (string-equal (file-name-base project-path) "deno-bridge")
        "deno")))

当 lsp-bridge 发现 git 目录是 deno-bridge 就启用 Deno LSP服务器, 其他的 TypeScript 项目使用默认的 TypeScript LSP服务器。

Deno这个运行时很厉害, 默认就包括了 LSP Server (用 deno lsp 命令来启动)。

2 个赞

牛啊,这效率

简单写了一个Demo GitHub - manateelazycat/deno-bridge: Build bridge between Emacs and Deno, execution of JavaScript and Typescript within Emacs.

目前还只能在 deno-bridge 目录下玩, 等我把 deno-bridge.ts 上传到 deno 的第三方仓库里, 大家就可以脱离 deno-bridge 的目录, 在任意位置写 TypeScript 插件。

1 个赞

vscode 那边的插件没觉得有啥值得羡慕的, 半斤八两吧最近也有用vscode做开发,主要还是emacs会卡顿。

sublime 和 vscode 已经用上gpu渲染了,但是emacs还在跑cpu。EPC 解决了多线程问题。但是 sublime 和 vscode流畅真的甩emacs 很多。

Emacs本身绘制这个现在无解, 改动太大, 只能从多线程方面改进。

deno-bridge项目的目的主要是给Emacs赋予TypeScript的能力, 除了WebRender的部分, 其他在能力上不再差 VSCode.

VSCode的流畅性是优点, 缺点是插件生态都面向鼠标设计, 没有Emacs全键盘的效率高, Emacser开发插件都是默认支持全键盘。

发布了一个 Deno 模块 https://deno.land/x/[email protected]?pos=1&qid=e973829e1f399a6847184f381bd151e3

现在大家可以基于 deno-bridge 在自己的仓库开发TypeScript插件了, 不受 deno-bridge 目录的限制。

Deno-Bridge 开发教程

deno-bridge-demo.el

(require 'deno-bridge)
(setq deno-bridge-demo-ts-path (concat (file-name-directory load-file-name) "deno-bridge-demo.ts"))
(deno-bridge-start "demo" deno-bridge-demo-ts-path)
;; (deno-bridge-call "demo" "ping" "Hello from Emacs.")
  1. 启动Deno进程: (deno-bridge-start "demo" deno-bridge-demo-ts-path)
  2. Emacs中调用TypeScript函数: (deno-bridge-call "demo" "ping" "Hello from Emacs.")
  3. 清理Deno进程: deno-bridge-exit 选择应用的名称

deno-bridge-demo.ts

import { DenoBridge } from "https://deno.land/x/[email protected]/mod.ts"

const bridge = new DenoBridge(Deno.args[0], Deno.args[1], Deno.args[2], messageDispatcher)

async function messageDispatcher(message: string) {
    const info = JSON.parse(message)
    if (info[0] == "ping") {
        console.log("Emacs message: ", info[1][0])

        const emacsVar = await bridge.getEmacsVar("deno-bridge-app-list")
        console.log("Emacs var 'deno-bridge-app-list': ", emacsVar)

        bridge.messageToEmacs("Hi from TypeScript")

        bridge.evalInEmacs('(message \"Eval from TypeScript\")')
    }
}
  1. DenoBridge 对象主要的作用就是和Emacs通讯
  2. 获取Emacs变量值: await bridge.getEmacsVar(emacs-var-name)
  3. 在Emacs中显示消息: bridge.messageToEmacs("message")
  4. 在TypeScript中执行Elisp代码: bridge.evalInEmacs('(message \"Eval from TypeScript\")')

这样就打通了Elisp和TypeScript的互调用, 大家可以自由发挥, 现在可以用TypeScript给Emacs写插件啦!

10 个赞

我今天翻了一下 Neovim 的插件 GitHub - rockerBOO/awesome-neovim: Collections of awesome neovim plugins. , 发现也没啥亮点插件 neovim 有但是Emacs没有的。

大家知道哪些 VSCode/Neovim 插件非常抢眼, 但是 Emacs 缺失或者同等插件性能不足的点子吗?

远程开发? vscode的 wsl / container。

远程开发的回复我写在 远程文件补全 · Issue #357 · manateelazycat/lsp-bridge · GitHub

这个还比较复杂, Emacs没有一个好的远程文件同步工具之前, 这个都很难做到, tramp 那样的东西完全没法用。

neovim唯一一个可能就是treesitter,neovim的treesitter的完成度非常高,配合treesitter做文本编辑能干很多有意思的事情,目前的那个elisp-treesittere真的只能做非常basic的事情。但是emacs现在也有自己的treesitter在core了,估计再等一两个版本完成度就会很高了。

硬要说的话感觉还是文本编辑类很多的插件,可能很多都没有evil版本的实现,比如 targets.vim (lua实现的mini.ai)之类的这种插件,用evil可能有的时候会想念这些插件,但是大部分时候就还好。而且emacs大部分估计也可以找到equivalent的非evil编辑类插件。

neovim毕竟不像eamcs,有一个真正的图形界面,所以作为一个终端的编辑器,限制了它能做的事情有限。emacs的gui虽然和vscode这种比不了,但好歹是个真正的gui,因此能干很多neovim干不了的事情。

但是neovim最大的优点就是快,就是真的在任何方面真的都是更快一点。懒猫的lsp-bridge已经非常快了,在我看来速度已经有nvim-lsp配合nvim-cmp的95%了,但是还是有非常corner case的情况下,打第一个字的时候会卡一下等popup框出来的情况。(这个问题我感觉是无解的,因为哪怕写org这种和lsp无关的,应该不要求补全性能的时候,用company都可能会突然卡一下补全界面)

第一个字符卡一下能否举个例子?

确实会有这种情况,比如你刚打开一个文件,然后第一次编辑,补全弹出就会卡。但是我关了dabbrev?那个选项以后就好很多了