CodeMirrorのModeを作る
CodeMirror 用の独自の Mode の作り方を紹介します。この記事では、SimpleMode を使わない方法を紹介します。
大枠
CodeMirror.defineModeメソッドに、モード名と、token 関数をメンバに持つオブジェクトを返す関数を渡すとモードが定義できます。CodeMirror についているモードのソースには、CommonJS や AMD モジュール用のコードも付いていますが、この辺りはなくても大丈夫でした。
返すオブジェクトに startState を含めると、字句解析中の状態を保持するためのオブジェクトを設定できます。この関数で返したオブジェクトが、token 関数の第二引数に渡されるため、そちらのオブジェクトに値を設定することで、状態の保存なども可能になります。
token 関数
token 関数では、第一引数の stream オブジェクトからから文字を読み取り、渡されたところから読み進めたところまでのトークンの種類を文字列で返します。返すトークンの種類は任意の文字列で良いようで、トークンが設定された部分には、スタイルシートの
cm-トークンの種類クラスが適用されます。null を返すと何も設定されないようです。また、stream オブジェクトから一文字も読み出さずに関数を抜けてしまうと、エラーになります。
stream オブジェクトの詳細は公式ドキュメントをご覧いただければと思いますが、ここでは、よく使うメソッドをまとめておきます。
メソッド | 動作 |
---|---|
peek() → string | ストリームを進めずに次の一文字を読み取ります。終端の場合 null を返します。 |
next() → string | 次の一文字を読み取り、ストリームを 1 文字進めます。終端の場合 null を返します。 |
sol() → boolean | 行頭の場合 true を返します。 |
skipToEnd() | ストリームを行末へ進めます。 |
column() → integer | 行の何文字目かを返します。 |
match(pattern: string, ?consume: boolean, ?caseFold: boolean) → boolean | 文字列が一致したら true を返し、consume に true を渡すか値を渡さない場合、一致した分ストリームを進めます。 |
match(pattern: regexp, ?consume: boolean) → array<string> | 文字列が一致したら true を返し、consume に true を渡すか値を渡さない場合、一致した分ストリームを進めます。一致しない場合、null を返します。 |
- match に渡る文字列は、行単位のようです
- デフォルトでは、空行はスキップされるようです
簡単な例
以下のようなモードを作って読み込ませます。if, for, int をキーワード、数値部分を数字、// 以降をコメントにするモードです。
これを適用させると、以下のような感じになります。
他にもインデントの情報など色々と返せるようですが、コードに色付けするだけであれば、これで十分そうです。