使用 Emacs 作为万能粘合剂

最近一段时间,我编写了几个 Emacs 工具,用于提高工作效率。作为一个 Emacs Lisp 新手,并没有选择编写纯粹的 Emacs Lisp 程序,而是使用 Emacs Lisp 来封装若干 Cmd 工具,把 Emacs 作为粘合剂。总体使用下来,感觉很不错。

想要用 Emacs 来做所有的事情,可能会比较困难。但使用 Emacs 来结合所有的其他工具,是一个很好的方法。

最近为写了几个 Emacs 工具:

  1. leetcode-emacs: GitHub - ginqi7/leetcode-emacs: an emacs plugin to write leetcode programs
  2. hbase-shell-emacs: GitHub - ginqi7/hbase-shell-emacs: A Emacs Plugin for hbase shell
  3. kubectl-emacs: GitHub - ginqi7/kubectl-emacs: This is an Emacs plugin that makes it easier and faster to manage k8s using kubectl.
  4. global-interactive-emacs: GitHub - ginqi7/global-interactive-emacs: Global Interactive Emacs

这几个工具,可以分为两类:

  • 前 3 个工具,把 Emacs 作为一系列命令行工具的 GUI 交互式 interface

  • 最后一个,把 Emacs 做为系统应用快捷启动器的后端。 在 Emacs 之外使用在 Emacs 中定义的交互式函数的方法。

    使用用例:

希望有兴趣的朋友可以相互交流,提供意见,促进开发。

34 个赞

很酷,最近我刚开始接触容器,感觉也需要类似的工具。 另外这个做缝合怪的思想我也很赞同!

前 3 个工具的核心思想是用 Emacs 作为一系列 Cmd 工具的GUI,处理cmd的输入输出。这样,既能够复用Emacs本身一系列方法和插件,把最常用的方法、工作流抽取出来。另一方面也不用重复造cmd的核心逻辑。

最好是能够抽出一个框架,然后不断的扩展插件。不过目前并没有很好的抽象思路。就先把工作中需要用到的工具,用 Emacs 封装一下。后续积累多了,或许可以抽象出一个核心。

最后一个工具,思路比较有意思。基于,Global interactive Emacs functions | isamert.net 这篇文章的思路。我这边尝试,用 Emacs 作为应用启动器,替代正在使用的 Launchbar

3 个赞

Prerequisites

  • choose

choose github

README 这里并没有链接可以点。

GitHub - chipsenkbeil/choose: Fuzzy matcher for OS X that uses both std{in,out} and a native GUI 这个链接。 之前我把 ssh 的链接附带上了,github 没能解析出来。已经替换成 http 链接。

都是很好的创意👍🏻 Emacs当初命令行在类Unix上都有不错的表现,实现也比较容易,就是性能弱些。

是的,性能可能比较弱。但通常问题不大,把 Shell 放到异步的进程里,让它自己慢慢跑。只要不卡住Emacs,可以不用停止手头的编辑。等结果返回再弹出结果窗口。

可能 kak 很适合这个想法,kak 的哲学就是连接 commandline 来实现插件

1 个赞

kak 是什么?

kakoune

Selection-based modal text editor

看定位,类似一个交互式的Vim。但看起来并没有比(vim + 一系列的配置)更有优势的样子。

感觉不用扩展到拿另外一个编辑器来做类比,我理解 magit, counsel-rg/ag/git-grep 类就是典型的在 emacs 里 “粘合” 命令行工具的实现,比如说 magit 是 git 在 emacs 里的前端,或者就叫 interface ,rg 的结果导入 minibuffer 就可以继续用模糊搜索, occur 等其他工具来操作了(终端里对应 fzf 这类工具)。emacs-anywhere/everywhere 是类似第四个的思路,全局的 emacs popup window。 @DogLooksGood 大佬开发的 emacs-rime 也是对 rime 的粘合了,只不过是和更底层的 librime 库交互,而不是已经封装的命令行接口,与 pyim 的关系就是楼主说的以下用 elisp 实现还是用外部实现的区别

eaf 是和 pyQt 粘合,exwm是和 x window的接口粘合。不知道是不是这么理解?

1 个赞

EAF不仅仅是pyqt和vue的黏合,更是用python,javascript和c++来横向扩展emacs,只不过EAF是以图形为载体的。

从lsp-bridge实践来说,可以借助EAF核心技术实现无界面的python编写emacs插件,这种技术和命令行工具黏合区别是,命令行工具往往都是对字符串输出做正则过滤,很难深度扩展和语法交互。

其实我有时候在想,EAF和lsp-bridge探索出了一条路,通过 “RPC+多线程+elisp/外部语言互相调用” 机制,我们可以构建一套基于 jsonrpc 的通用多语言框架,我们可以用任意语言扩展emacs,elisp专注文本编辑和黏合,所有性能相关的解析工作都交给外部语言,这样会形成所有语言都可以扩展emacs,不仅仅是python,javascript和c++,甚至是golang和rust等,它山之石的生态为emacs所用。

我最近发现比较流行的neovim,在核心机制上居然和EAF有异曲同工之妙,都是通过RPC和外部语言及生态协同开发的思路。

10 个赞

无比赞同这个想法。 目前受限于个人 Emacs Lisp 水平,我目前的做法比较简单,把某个 cmd 工具丢到异步去运行。Emacs 做为 input / output 的接口,来进行功能扩展。目前的一大缺点是,输入、输出的格式,不同的命令完全不统一,导致无法进行抽象,只能一个工具一个工具去适配。

使用 RPC 确定 Emacs 与外部交互的协议格式,就如同 lsp-bridge,这样就可以做成一个统一的框架,只需要适配不同的语言/工具时,实现对应协议的适配即可。

全局的 emacs popup window,可能是一个更好的选择。使用 mac 工具 =choose= 作为全局的输入输出有一些局限性。

我看看 Emacs 弹出全局窗口时,能否更好的设定窗口的样式。例如:

  1. 进行输入、选择时,只需要弹出 minibuffer
  2. 当用户选择完,弹出窗口进行查看结果。

以前也有人尝试用其他语言扩展 Emacs (不是那种需要编译的动态模块),例如 Pymcs,就跟用一般的包一样 require,然后启动一个 python 进程,用来进行 Python-Emacs 双向交流。虽然当时没有提出 RPC 和多线程的想法,但大致目标是差不多的:在 Emacs 和其它语言之间架一道桥。

可能当时的各方面条件还不成熟,用户的接受度也不怎么样。类似这样的项目大多都废弃了。

image

相关连接:

1 个赞

可能多数的 Emacs 用户还是更希望在 Emacs 内部解决所有问题。能用 elisp 解决的问题,不太希望引入其他工具。lsp-bridge 能够完善起来,还是主要是其他的 emacs lsp client 太卡了,生产使用不是太靠谱。才觉得 lsp-bridge 是真香。

对,EAF主要是解决了浏览器集成和PDF渲染性能问题,lsp-bridge主要解决写代码不要卡顿的问题。

如果脱离了核心应用场景,纯粹的多语言编程模型确实很难发展起来。

1 个赞

我居然漏了一个工具:git-emacs GitHub - ginqi7/git-emacs: A Emacs plugin for Git 异步的运行若干 git 命令。主要由于使用 magit 觉得卡,而编写的工具。

1 个赞

感谢答复,我以前用过一段时间的 vim/neovim, 个人感觉是,相比 elisp, vimscript 写起来比较别扭,和 bash 有点像,实现复杂的逻辑会比较麻烦,也没那么有趣,vim 主打的又是它的编辑模式,所以 vim 里插件基本还是围绕文本编辑和 IDE 类的,既然 vimscript 不好写, IDE 类功能性能要求又高,可能反而让 vim 开发者更向外找方法了(个人猜测)。但 emacs 里 org, 邮件啥都有,也都能用 elisp 来写,就把人粘住了。