node.js+socket.ioでcodemirror editorを同時編集してみる

node.jsでchatアプリっぽいもの作るメモ - すぎゃーんメモ
node.js+socket.ioでライブコーディング的なものを作るメモ - すぎゃーんメモ
node.js+socket.io+oauth+SessionWebSocketでログイン付きチャットを作るメモ - すぎゃーんメモ
に引き続き、第4弾。


js製editorで編集情報をSocket.IOで送りつつ、他から送られてきた編集情報を反映する、複数人同時編集エディター的なもの。
sample: http://www1216u.sakura.ne.jp:3002/
source: https://github.com/sugyan/node-editor


エディタはcodemirrorというものを持ってきて使用した。
CodeMirror
コードの内容変更のイベントが取れたり局所的な変更も可能で、plugin的にparserを定義することで多言語でのSyntax highlightが可能。良いエディタだと思う。


以前ライブコーディング的なものを作ったときは、textareaのvalueを定期的に全部送信してviewerに反映させていたけど、さすがに非効率な気がしたのローカルで変更があったときだけ差分を送るようにしてみた。
差分(diff)の抽出のためのjsライブラリは探してみたのだけどgoogle-diff-match-patchくらいしか見つからず。これはdiffを取ってpatchとして適用させたりできて便利なのだけど、どうも文字列と文字列の差分を取るもので、「何文字目を消して何文字目にコレを挿入すれば差分が埋まる」という形式のdiffしか取れないようだった。今回使っているcodemirrorは主に"行"単位での編集APIが提供されていて、"何文字目"のような編集がしにくい。欲しいのはdiffコマンドのような"行単位"の差分…。
ということで行単位のdiffをとるために、PerlのAlgorithm::Diffからdiffサブルーチンの処理を丸パクリしてjsで実装した。
Algorithm::Diff - search.cpan.org
各クライアントからは自分が編集した差分をサーバーに送り、node.jsサーバーではその差分をそのまま他のクライアントにbroadcastしつつ、メモリ上に持つマスタとしてのコードに差分を反映させておき、定期的に同期をとるために発信する。各クライアントは編集できる状態でありながらもサーバーから来る差分情報や同期のためのマスタコードを勝手に反映させていく。
という仕組み。

なんとなくこれでうまくいくかなーと思っていたのだけど、複数人が編集しているとたびたび差分を受けて反映、同期が行われ、その度にカーソルが末尾の方に強制移動されてしまう… このへんの制御の仕方は残念ながらよく分からなかった。日本語を打つときも変なタイミングで勝手に確定されてしまったりで非常に不便。
あとiPhoneからは閲覧はできるけど編集はできないようだ。


まぁ仕組みがある程度あればエディタは(編集時のイベントが取れて、jsから書き換えることができれば)何でも良いかなと思っているので、今日話題になったEclipse Orionのエディタを試してみようかな。
Planet Eclipse
http://0-9.sakura.ne.jp/pub/orion/samples/demo.html


あと複数人同時編集エディタは既にあるので そこまで頑張って再発明するほどのものじゃなかったり…
online text editor - collabedit