🔖

Lem Advent Calendar 2023 - モジュール構成

2023/12/01に公開

これは Lem Advent Calendar の記事です。

Prologue

Lemを作りはじめて8年の月日が流れました。
https://github.com/lem-project/lem

かつて、5000行程度の簡素なプログラムに過ぎなかったこのエディタは、時を経て、その機能を飛躍的に進化させました。

最初のバージョンでは70年代のスクリーンエディタと似たような簡素なプログラムでしたが、今日ではコードベースは8万行に及ぶほどになり、Common Lisp IDEとなりうるための数多くの機能追加やアーキテクチャの改善、Language Server Protocol、30以上の言語のサポート、度重なるUIの改善、さらにはSDL2によるグラフィックス機能を実現しています。

Lemは単なるテキストエディタではなくCommon Lispによるマルチメディアプラットフォーム開発環境としての変貌を遂げつつあります。

ここでは、そんなLemについて、各機能や内部実装についての紹介をしていきます。

Lemとは

LemはEmacsやneovimにインスパイアされたCommon Lisp Editor/IDEです。
日常的に使えるテキストエディタをスクラッチから開発し、日々ドッグフーディングしています。

始まりはLinus Torvaldsも使っているMicro Emacs

Lemを作り始める前、Micro Emacsというテキストエディタを使っていた時期がありました。

https://ja.wikipedia.org/wiki/MicroEMACS

wikipediaにも書いてある通り、linus torvaldsが使っているという話を聞き、それに影響されていました。
このエディタを自分なりに変更し、日本語の文字幅に対応したり、S式単位の操作を出来るように機能を追加していましたが、80年代のCのソースコードということもあり、すぐに辛くなってしまいました。

設定ファイルも独自のマクロ言語っぽくてよくわかりません。
https://github.com/cxxxr/uemacs/blob/master/emacs.rc

そこで自分で全部作ろうと思い、出来たのがLemです。
名前の由来はMicro Emacsの実行ファイルがemで、そこにlispのlを付けてlemにしました。
後にLem Editor Modulesの略となります。

Overview

Lemの大まかなモジュール構成を図にしました。

LemはLem Editor Modulesの略ですが、エディタの機能をモジュールとして提供できることを理想としています。

プリミティブな要素としてBuffer, Point, Syntaxなどを持ったbaseモジュール、
Window, Keymap, Commands, その他エディタに必要な機能を持ったcoreモジュール、
各言語をサポートする拡張機能等が入ったextensionsモジュール、
それらをバックエンドと呼び、キーボードやマウスからの入力と画面への出力を担うフロントエンド等で構成されています。

base

エディタの最もプリミティブな機能を提供するモジュールです。
ファイルに関連付いたバッファを作り、編集し、保存する一連の機能があります。

これらの機能だけをもったモジュールに分離した理由として、Language Server Protoclの実装上のメリットがあるからです。

Language ServerはClientからのリクエストによって、ファイルを開き、指定された位置に文字列の挿入と削除を行い、テキスト情報を同期する仕組みとなっています。
そのため、エディタの機能が必要になります。
Language Serverのモジュール側でbaseというモジュールのみに依存させることで、他の多くのエディタの機能から切り離せるような設計になっています。

core

baseを拡張する形のモジュールです。
baseで提供された機能の他にwindowやkeymap、各種コマンドなどテキストエディタとして使う場合に必要な要素が含まれています。

extensions

Lisp Mode や Go Modeなど、各言語用の拡張機能が含まれています。
その他、coreとは分離したい拡張を含めるようにしています。

frontend

lemはFrontendとBackendから構成されており、Frontendにはターミナル用の実装やSDL2があります。
今はメンテナンスできてないですがjsonrpcを使ったElectronの実装もありました。

おわりに

一日目の紹介はこれで終わりです。
今後はこれらのモジュールの詳細や、Lemの他の機能について深掘りしていきます。

Discussion