前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >编辑器的自制

编辑器的自制

作者头像
Phodal
发布2020-08-12 01:16:33
7620
发布2020-08-12 01:16:33
举报
文章被收录于专栏:phodalphodal

最近的几个月里,我一直在寻找一种合适的方式来构建底层应用。可能是 Web、App 应用已经缺乏了一些新鲜感;也可能是受受国际局势的影响,我开始思考构建底层应用架构的能力。

于是,在我学习了一段时间的 Rust 之后,我便不断地往系统的底层探索。在那之前,另外一门合适的语言大抵是 Golang,不过我偏向于认为 Golang 是一个 Web 应用或者普通应用的开发语言,而非一个系统编程语言。

这其中的一个话题就是:编辑器以及 IDE。毕竟,讨论 Emacs 和 Vim 哪一个更好,已经不能满足我的需求。程序员的乐趣应该在于如此去写一个 Emcas,便实现一个 Vim —— 毕竟 Emacs 操作系统太复杂了。

1. 无 UI 式:命令行编辑器

作为过程的第一步,我开始寻找一些合适的编辑器(PS:主要是简单),以作为我的编辑器和 IDE 生涯的第一步。然而,这并不是一件容易的事,毕竟我先前构建 Client 端的经验,都是使用现成的 UI 组件,如 WebView 的 Textarea、Android 框架中的 EditText 组件。

于是乎,我模仿 + 复制 Iota 项目的一部分代码,形成了一份最小可工作的代码,以了解命令行编辑器如何运作的整体原理:

字符移动

对于终端编程来说,并不存在组件可以使用,所以我们所要做的事情是:在特定的位置显示特定的字符,如:

代码语言:javascript
复制
rustbox.print_char(1, 1, RustBoxStyle::empty(), Color::White, Color::Black, 'A')

这样一来,它就在屏幕上的 1,1 的位置画了一个 A,它的前景是白色,背景是黑色。嗯,没错,这种体验就是我大学玩的嵌入式编程。

于是,第一步我们要做的就是读取文本,然后渲染。这里用的库是 RustBox,它封装了 C 语言下的 Termbox。对于一些人来说,更为熟悉的名字可能是 curses,又或者是 GNU 里的 ncurses。在另外的一个 Rust 编写的编辑器 [amp] 中,使用的是 termion。

快捷键识别随后,我们可以启动起编辑器,而后做各种事件轮询,等待用户的交互,如快捷键。同样的,这个功能也是由底层的 Termbox 提供了支持,我们只需要创建行为与快捷键的绑定即可。

状态栏 + 命令模式。有了上面的基础之后,这个也不会遇到什么困难。

语法高亮。这里我就被 iota 这个项目坑了,项目的截图上是有语法高亮的,但是代码上已经删了。回溯了一下过程,发现这部分的功能删了,因为原先的设计并不合理。合理的方式应该是使用 syntect 这种现成的方案,它使用了 Sublime Text 的语法定义格式。

理解了原理,快速画了个瓢之后,我就转向 UI 式的文件编辑器。

GitHub: https://github.com/rapilab/rinput

2. UI 式:进程分离

随后,我在 Awesome-rust 项目中,物色到了第二个可以项目:xi-editor。Xi Editor 是 Google 员工开源的一款用Rust 语言编写的文本编辑器。从之前的新闻来看,像是火了一段时间,但是好像已经没有那么活跃了。

它最主要的特点有:

前后端分离。编辑器分为两部分,后端和前端。后端(即核心部分)负责保存文件缓冲区,并负责所有潜在的昂贵编辑操作。你可以将等价为前后端分离应用的关系,又或者是 Electron 应用中:Electron 的 Node.js 和 WebView 部分的区别。

JSON RPC。xi-editor 提供了 JSON 形式的 RPC(远程过程调用)用于前后端之间进行通讯。采取 JSON 的主要原因是减少开发插件的成本,更好的扩大生态。如,我从 UI 上修改编辑器的主题,将通过 RPC 的方式通知后端,并将对应的配置存储到系统中。并且诸如于 IDEA 的索引模式,它应该也会在后台运行,而不占用 UI 进程,影响用户体验。如此一来,我们所面临的卡顿问题,会进一步得到缓解。

不限 UI。因为 xi-editor 本身只提供 core 模块,所以,我们可以看到有各种各样的 xi-editor 的前端,如原生 macOS 实现、基于 Electron 实现等等。

所以,我尝试基于这种架构模式,开发了一个基于这种架构模式的系统状态应用 Stadal。有了这样的模式,我们就可以分离 UI 进程,提供更好的用户体验。

顺便一题,在这种模式之后,编辑器的模型都统一由后端管理(PS:这一点与 Web 应用是相似的,笑~)。

Emacs 架构:M-V-C 架构

这样一类比的情况下,Emcas 的架构就好似一个大单体一样。毕竟这是 M-V-C 架构(源自《架构之美》:

  • 模型。程序所操作数据的底层描述,如文本属性、缓冲区等等;并与系统进行交互。
  • 视图。面向用户展示数据的方法,如对于窗口增量显示更新逻辑等。
  • 控制器。负责实现用户与视图的交互(如按键、鼠标事件等),并对模型进行更新(采用 Lisp 作为支撑)

至于插件部分则是由 Lisp 脚本来实现,至于是插件好还是脚本好就是另外一个问题了。

GitHub :https://github.com/phodal/stadal

IDE:IDEA 的插件化

因为偶然地原因,我分析了一段时间的 Intellij IDEA 社区版 + Android Studio 的源码之后,我有了一些新的感受 —— 这个系统架构有点复杂,哈哈。当然,也发现了一些相似的模式。

隔离层:独立二进制

对于工具的制造者来说,开发者并不希望工具被捆绑在某一个开发工具上。因此,对于开发者而言,优先做的是提供一个可独立运行的程序,而后再封装一个针对于该工具的实现。

于是乎,这个运行的程序,它可能是:

  • C/C++ 编写的二进制应用。通过 daemon 的方式来运行,并能通过解析输出来进行错误处理。
  • Gradle 开发的插件。并借助于 Gradle Tooling API 来实现插件的调用。
  • Java 编写的应用。通过直接集成的方式进行。
  • ……

这样一来,我们就在 IDE 中集成了这样的能力,并引入到我们的系统中使用。

语言扩展

IDEA 本身的插件体系已经设计得很完善了,如我们可以快速添加一门语言,只需要:

  • 注册文件类型
  • 实现 Lexer(词法分析)
  • 实施 Parser(语法分析) 和 PSI(程序结构接口)
  • 语法高亮显示和错误高亮显示
  • 代码补全
  • 查找用法
  • 重构:重命名、安全删除
  • 代码格式化程序
  • ……

这样一来,我们就能快速地具备一个语言 IDE 应该有的能力。比如 IDEA 的 Rust 插件就是这样一个不错的示例。

总结

一个好的编辑器/IDE 应该能:

  • 滋长的特性:通过插件化支撑
  • 可维护性:具备良好的可读性
  • 进程分离
  • 速度

讨论哪个编辑器/IDE 是一件没意义的事。

只有自己挖的坑才是好的。

我行我上。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 phodal 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 最近的几个月里,我一直在寻找一种合适的方式来构建底层应用。可能是 Web、App 应用已经缺乏了一些新鲜感;也可能是受受国际局势的影响,我开始思考构建底层应用架构的能力。
    • 1. 无 UI 式:命令行编辑器
      • 2. UI 式:进程分离
        • Emacs 架构:M-V-C 架构
      • IDE:IDEA 的插件化
        • 隔离层:独立二进制
        • 语言扩展
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档