🔖

Lem Advent Calendar 2023 - editor stream

2023/12/14に公開

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

ユーザーがストリームを定義できるようにする仕組みとして、gray streamsがあります。
これはストリームクラスを継承したクラスとストリーム用の各メソッドを定義することで使うことが出来ます。
Common Lispの仕様を決める段階では含まれませんでしたが、メジャーな処理系ではこの機能に対応しており、trivial-gray-streamsという処理系毎の違いを吸収するライブラリが存在します。

Lemでもこの仕組みを使って、エディタ用のstreamを定義しています。
これによってエディタの入出力を既存のストリームの機能を使って行うことが可能です。

例として現在のバッファ内の単語数を数えるコマンドcount-wordsを定義してみました。

(defun count-words-in-stream (stream)
  (loop :for line := (read-line stream nil)
        :while line
        :sum (ppcre:count-matches "\\w+" line)))

(define-command count-words () ()
  (with-open-stream (stream (make-buffer-input-stream
                             (buffer-start-point
                              (current-buffer))))
    (message "~A" (count-words-in-stream stream))))

count-wordsコマンド内のmake-buffer-input-streamでバッファを読み込むストリームを作成し、そのストリームをcount-words-in-streamに渡しています。

おわりに

gray streamsを使ってエディタ用のストリームを定義することで、streamを扱う汎用的な処理とエディタ固有の処理を切り離すことが出来ました。
他にもbuffer-output-stream, editor-input-stream, editor-output-stream, editor-io-streamを用意していますが使い勝手が悪く、あまり使われていません。
ここはそのうち改善したいです。

Discussion