延续之前的一篇文章
Cirru Project in 2015
Cirru 演进历程: 2012 ~ 2016
大致从 2017 年以后, Cirru 在图形探索上面就比较少了, 还是基于原来的方案.
主要在 Stack Editor 基础上设计了新的 Calcit Editor.
另外围绕 Calcit Editor 做了一些辅助工具.
大多想法还是用 Calcit Editor 维护以前整理出来的这些小的应用.
尝试 Nim 是最近的想法了, 想用静态类型语言再尝试一下以前做的.
Calcit Editor
项目地址 https://github.com/Cirru/calc...
大致上就是以前的 Stack Editor 的功能改进. 整体界面功能相似.
项目最开始的时候用的 cumulo-editor 这个名字, 所以记录有写分开的,
Calcit Editor 当中最核心的算法是 bisection-key 的算法, 用来计算插入节点的位置.
比如这样一段 Clojure 代码, 包含简单的嵌套的数据:
(if (coord-contains? focus child-coord) focus nil)
用 Cirru 的数据形态表示出来, 就是数组的嵌套:
["if" ["coord-contains?" "focus" "child-coord"] "focus" "nil"]
当有两个客户端在同时编辑中间嵌套的表达式的时候, 数组的位置是 1
,
那么, 比如客户端 A 的 1
的前面插入了新的节点, 并且修改, 那么也是 1
,
然后 A
修改 1
的时候, 对应的 B
当中的数据就已经过时了.
总体上就是很难控制中间的逻辑不会发生明显的冲突.
bisection-key
模块的方案是给每一个节点增加 id, 并且 id 用的字符顺序,
再细节就不说了, 至少大幅缩小了发生冲突的可能性, 最终的到这样的一个结构:
{
:type :expr, :data {
"T" {:type :leaf, :text "if"}
"j" {
:type :expr, :data {
"T" {:type :leaf, :text "coord-contains?"}
"j" {:type :leaf, :text "focus"}
"r" {:type :leaf, :text "child-coord"}
}
}
"r" {:type :leaf, :text "focus"}
"v" {:type :leaf, :text "nil"}
}
}
作为 Calcit Editor 的存储格式(实际使用当中包含更多的节点信息).
基于 Calcit Editor 就可以实现多个客户端实时协作的功能了.
不过实际上来说这方面做的探索还是不够, 绝大部分时候还是单机使用的.
另外加入的功能有比如实时显示光标位置, 全局通知, 连接 nrepl 之类的功能.
以及专门优化了在 Git 切换分支的时候文件重载的问题.
为了方便使用, 增加快捷键, 处理复制剪切粘贴, 原始存储格式修改等等功能.
对于 Clojure 开发来说, 在文本的基础上, Calcit Editor 有一定的结构化方案,
但相对来说, 由于不是 IDE 那样集成的环境, 很多功能还是缺失的.
对于推广来说不是好的事情. 只能说对于 Cirru 本身的探索做了延伸.
另外生成 Clojure 代码的模块也逐渐有调整: sepal.clj.
编辑器相关组件
除了主体的编辑器, 还衍生一些相关的工具:
由于 Cirru 的文本格式比较特殊, Snippets 需要单独处理.
所以做了一个简单的服务, 将用到的几个 Snippets 存放在专门的页面上.
这是一个快速查看 calcit.edn
存储文件的小工具,
功能比较简单, 就是讲代码渲染出来, 一次性全部展开, 方便直接查看.
实际使用来说应该再加入更多功能的..
一个单独高亮显示代码的模块, 提供类似 calcit-editor 的局部.
可以用在 Snippets 预览的场景当中, 以及处理类似的需求.
这个基于之前 Stack Editor 的编辑器组件制作的, 用于网页上直接编辑.
存储格式比较简单, 直接就是数组的形式, 操作习惯大体上跟 Calcit Editor 相似.
现在 Cirru.org 页面当中编辑预览就是用的这个工具.
Clojure EDN 美化的函数运行有一些性能开销, Calcit Editor 存储信息又可能比较大.
慢的主要原因应该是布局的问题, 各种对齐要求比较特殊.
我的场景当中需求有限, 所以写了一个简单的生成数据文件的工具.
同时我需要代码换行而且大致可读, 能被 Git 自动 merge, 甚至极端时手动调整.
Parser in Nim
parser.nim 和 interpreter.nim 是近期想到所以开始做的尝试.
以前版本的 Parser 都比较慢, 主要还是因为是动态语言.
当时最快的版本应该是 Go 的, 但是 Go 的问题, 包管理, 动态特性, 都有影响.
所以我考虑试一下 Nim, 一来是简单, 二来性能方面能尝试些不一样的方案.
Nim 版本的 Parser 做了 Lexing, 之前的版本都比较粗暴直接逐字解析的.
然后也处理了一下行号和报错方面的问题, 方便在具体的场景当中用.
虽然目前解析的代码体积都比较小, 但是明显能感受到跟 JavaScript 版本的提升.
至于 interpreter 也是基于此前 Go 版本的写法做尝试.
目前没有想好, 但是希望能做出来一些能用在日常工作中的工具.
其他
毕竟要工作, 纯粹的 Cirru 的探索已经很少了, 也过了那样的年纪.
对我来说图形布局已经超出当初想要的效果了, 至少在便利性上面.
所以我没有多少欲望说要去再做破坏式的改进的, 基本上都是微调.
短期看来, interpreter 部分做一下定制能够派上点用场.
日常开发当中还是需要一些脚本的, 用来执行短平快的一些任务.
用 Bash 写长了不好处理, 用通用编程语言, 又有一些模块化和 API 的限制.
Cirru 最初就是为了方便设计的书写, 非常灵活, 也适合继续定制.
我觉得这方面会再尝试一下, 希望能帮到日常开发.
远的先不会去想了, 精力不够的.