一个简单的 .Net Vim 引擎 LibNVim 开发记录 (二)

来源:互联网 发布:unblockcn mac打不开 编辑:程序博客网 时间:2024/05/29 19:41

之前介绍了开发的起因, 目标, 下面将转入实际的设计过程.

 

初始架构

 

设计一个可移植的插件引擎, 有一个思路比较好:

预先定义一个抽象的目标环境(IVimHost), 这个环境中包含了一组行为明确的操作接口(即 API).

引擎通过访问这些接口与外界环境交互, 从而避免对某个具体环境的依赖.

 

LibNVim 的整体架构, 即是按照这个原则组织.

 

模块划分

 

程序目前有 2 个模块, 一个是 LibNVim 引擎(LibNVim), 另一个是引擎在 VS 2010 中的宿主(VsNVim, 很可耻的抄袭了一下 VsVim ;).

从道理上来讲, 设计一个跨平台系统, 在开始时就针对 2 个或更多平台同时开发比较好, 这样可以及早纠正设计中的错误, 保证设计的质量.

但是因为精力有限, 现在只能以自己常用的 VS 2010 作为目标模型.

因此必须在设计时必须小心, 尽量保证抽象的通用性, 而不要依赖某些 VS 特有的东西, 机制, 以免之后移植其他平台出现问题.

 

输入的解析

 

Vim 接收的键盘输入种类繁多, 规则也比较复杂.

所以, 把输入的解析独立出来, 交给状态机(VimKeyInputEvaluation)去处理, 是个不错的选择.

 

插入时输入的文本如何重现?

 

插入模式(ModeInsert)时的文本输入的重现, 即 '.', 如果要精确重现所有键盘动作, 不仅实现起来麻烦, 从概念模型上来说也很复杂: 比如光标跳转(如上下左右)导致编辑区域的变化, 区域内删除操作的记录, 区域边界处删除操作的处理...如此等等

 

没有必要做一个精确, 但是复杂, 难用的重现功能, 只要为最常见的场景, 提供一个简单的重现规则即可.

 

所以这里对重现能力做了一个很大的删减, 只记录从起始位置开始的, 连贯的文本输入, 包括三个特殊的编辑操作 Key.Enter, Key.Backspace, Key.Tab, 其他诸如方向键, Key.PageUp, "Ctrl+Home" 操作统统忽略, 因此大大降低了实现的难度.

 

插入模式时还有些地方值得注意:

1. VS 2010 中, 文本编辑器(TextEditor)有些键盘输入事件无法读取, 比如 Key.Escape, Key.Enter, Key.ArrowUp...

2. 文本输入事件的处理, 用的是 TextInput() 事件, 这个事件, 发生在文本变化之前

 

ModeInsert 对 VS 2010 这 2 点的依赖, 很可能会导致移植其他平台出现问题, 因此, 实现时, 需要小心避开这些地雷

 

Span 的引入?

 

编辑中, 经常会遇到一些区域性的操作, 之前都是提供参数 (from, to), 搞得比较麻烦, 最主要的原因在于, 有些操作会依赖区域的开闭集合属性(比如 "ce" 跟 "cw").

所以后来引入了区间 (Span) 概念, 同时提供了两端的开闭属性(参考 yzis), 很好的解决了这类问题.

 

原创粉丝点击