首发于Better Naming
基于 VSCode/Monaco 的 iOS 编辑器(一)

基于 VSCode/Monaco 的 iOS 编辑器(一)

// 本文首发于专栏 Better Naming,聊一聊编辑器与 IDE 的开发

经常有朋友问我能不能把 VSCode 跑在某个他们心爱的平台上,包括并不见限于树莓派、 iPhone、iPad、Windows Phone,再或者上 Windows Store (UWP)。有点想法着实有趣,比如在 iPad Pro 上编辑代码或者 Markdown 文本。而最近 SourceGraph (就是垠神的前前...前公司) 把整个 VSCode 剪裁了放到了浏览器当中,让我对 port 到其他平台这件事情产生了兴趣,做了一点小小的尝试。

# VSCode 的架构

移植 VSCode 的想法由于过于狂野,为了避免一些不切实际的妄想,我还是要先冷静下来回顾一下 VSCode 的架构,这样才知道哪些是可以操作的,而哪些基本属于扯淡。

首先按照 UI 结构来划分

  • VSCode 中的编辑区域是 Monaco Editor,是完全基于浏览器的 Code/Text Editor,塞到 WebView 里就好了。
  • 左侧 Sidebar
    • File Explorer 虽然 iOS 应用操作文件的方式跟 PC 区别比较大,但是模拟一下没啥问题。SourceGraph 就把文件 API 替换成了 Rest 服务。
    • Search VSCode 用 ripgrep,只能用别的方案实现了。
    • Git 必须得用 iOS 平台的 Git 方案来代替。
    • Debug 这个咱还是先不要在这个上面浪费脑细胞了。
    • Extension VSCode 的插件都是运行在 node 上的,不过 Monaco 本身也有一套 extension api。所以把换一整套插件中心 (逃
  • 底侧 Panel
    • Terminal 在 iOS 上一个 Terminal Emulator 除了支持 ssh 比较有优势以外,其他干不了太多事情。
    • Task/Output/Errors 这些都跟语言功能和插件功能有关,UI 肯定能 port,但是功能有待商榷。

我表示很尴尬,Sidebar 和 Panel 里的功能,要么是假设你在 PC 上 (Explorer, Terminal, ripgrep),要么就跟语言的支持有关。做起来比较无痛的只有

Monaco Editor

当然还有半个 Extension Viewlet,但是整个生态得换成 Monaco 的插件体系。接着我们来看下 Language 的支持情况:

  • Intellisense 无论一门语言是使用 LSP 还是别的方式,提供真的抑或是假的 Intellisense 如果要搬上 iOS,这就意味着这套代码分析的工具得运行在 iOS 上。
    • TypeScript Monaco 自带 TypeScript/JavaScript Intellisense 支持,方法是把 TypeScript 的 LSP 跑在 Web Worker 里。不过这个 LSP 只处理单个文件,放在浏览器里还是比较合理的,但是在 iOS 上,用户应该更希望能够处理本地的整个项目。需要一定的魔改。
    • Ruby、C#、Java 等可以把 VM 一起 ship 到应用里语言,难度参考楼上。
    • 其他。我都不敢想。
  • Auto Complete
    • 同上,如果没有 JavaScript 实现的代码分析,那么只有 word base auto complete。
  • Tokenization
    • VSCode 支持 TextMate 的 Grammar,但是这套系统的 Regex Engine 还没法 Port 到浏览器里(WebAssembly 可能能解决问题)。
    • Monaco 有一套自己的语法方案 Monaco Editor Monarch 。现在只有 TypeScript、Markdown、JSON 和 XML 的语法,不确定社区有没有别的语言支持。当然可以把 TextMate 的 Grammar 降维到 Monarch。


# 我们退一步

如果你没兴趣看上面的分析也没关系,结论其实很简单。现阶段,就我们已有的代码和框架,我们能够做的是

  • 把 Monaco Editor 移植到 iOS 上,使用某种 WebView 方案加载。
  • 用 Swift 实现一套文件管理
  • 做一个 JavaScript 和 Swift 代码之间的 Bridge
  • 优化 Markdown、TS/JS、HTML、JSON/XML 的书写

虽然从来没有写过 iOS 应用,但我花了一个周末尝试了一下,做出了下面这个代码/文本编辑应用

## Markdown

Monaco on iOS Markdown—在线播放—优酷网,视频高清在线观看http://v.youku.com/v_show/id_XMjg0NTY1MDAxMg==.html?spm=a2h3j.8428770.3416059.1

## TypeScript


# 结果只能说差强人

拿着这个简单的 demo,我比对了一下 钟颖Cyan - 知乎 老师在他的文章 实现简易的代码编辑器 - 知乎专栏 中提到的一个可被接受的代码编辑器需要具备的条件

  • 实时代码高亮
  • 自动折行
  • 自动保持缩进
  • 自动插入花括号
  • 方便输入符号

前四个都实现了,最后一个由于我使用了 WKWebView,暂时没有找到添加 inputAccessoryView 的正确方法。

但是真正令人略有沮丧的是,Monaco Editor 并没有处理对 Touch 进行处理。大家知道,VSCode/Monaco 在编辑代码时那个跳动的光标还有文本选择(selection),都是我们手动绘制出来的,而真正的 textarea 只是一个肉眼不可见的 1px by 1px 的点。在这种情况下,Monaco 不仅无法进行长按选择文字这种操作,更别说什么 3D touch 了,2D 都没有。此外,iOS Safari 里一个 hidden 的 textarea 无法接收到 Tab/Arrows 等 event,这就意味着在你的 iPad 上暂时没法使用方向键来操控光标。


# 下一步

相比 钟颖 老师在他的 iOS 代码编辑器里使用的方案则很有意思,直接 JSCore 来处理 JavaScript 操作,然后利用 TextKit 绘制原生的编辑器。也许我们可以把 Monaco 的 Rendering Layer 和 Model 完全分开,然后在 iOS 上把 Rendering Layer 换成原生 TextKit,Model 和 View Coordinates 的计算依然放在 JSCore 中。这是一个值得尝试的思路。

此外,由于 Monaco 的可扩展性,这样的编辑器是可以做到允许用户使用 JavaScript 去改变编辑器行为的。比如改变高亮、修改 Markdown 语法等等。简言之,这个编辑器可以有一个自己的插件中心。

Stay tuned.

编辑于 2017-06-26 05:55