ltmemo

Rustでテキストエディターを作る記事をやった

tags:
2021-11-10

ToC

Rustでテキストエディターを作る記事をやった

記事はこれ

単純な興味と、基礎的な部分が学べそうなところとvimの理解に通ずる点がありそうだったのでやってみた

感想

  • terminalにも色やカーソル移動を指示するエスケープシーケンスが存在することを知れた
    • 色付けもこれで行う。特定の色にセットするエスケープシーケンスと合わせて文字をprint!するイメージ
  • 改行だったり、行末でdeleteしたときの挙動など、普段気にせず使っている挙動の実装について知れた
  • めちゃくちゃ高度なことをするというよりは、ひたすら場合分けして実装という感じだった
    • もっと難しいアルゴリズムとかでてくるのかと思ったけど意外と質素

Raw モード, Canonical モード

  • terminalにはモードの概念がある
    • デフォルトはcanonicalで始まる。これはcookedモードとも呼ばれる
  • canonicalモードではエンターが押下されるまで入力を受け付ける
  • 逆にrawモードにすることで入力を即時で受け取る
    • 厳密には非canonicalモードがあり、入力されたキーが画面に表示されず、
      C-cのような強制終了が効かなくなるんだとか

使ったcrate

  • termion
    • terminalに関する操作をあれこれ提供してくれるクレート
    • 標準入出力の代わりに使う
    • terminalは自分のstateを持っていて、そこでやり取りする
  • unicode-segmentation
    • 書記素クラスタを正しく扱うために必要。これがないとカーソルが移動するとき、マルチバイト文字で正しく移動できない
      • Stringはu8[]のラッパのようなものだが、文字は2byteのものがあったりするので、単純にchars()で一つ次に移動溶かしても思ったとおりに動いてはくれない

1章

環境構築なので割愛

2章

  • byteコードとcharに変換した結果を眺める
    • Enterがバイトコードだと13とかそういうの
    • C-[のバイトコードがEscと同じで、だからvimだとこれでinsert抜けれるというのはどこかで読んだことがあったんだけど、実際にどちらも27で一致していた
    • Ctrl+a-zが1-26にマップされている
  • is_control関数
    • プリントできない文字がcontrol character
    • とりあえずASCII以外って理解でよさそう

3章

Raw input/outputを扱う

  • idiomatic codeとは慣用的な表現をちゃんと使おうって事

    • clippyに従おう!
  • structとかnewの説明がなされてる。この辺りは初心者向き

  • escapeシークエンスをprint!("\x1b[2J")のようにしてておもろい

    • termionにはこれらのシーケンスがわかりやすく定義されてる
    • termion::clear::Allとか
  • termion回りが一番おもろかったな

  • editorでカーソル移動するところまで作った

4章

  • ファイルの読み込みからの表示を実装した
  • カーソルで読み込んだファイルの中を自由に移動するためにoffsetを導入する
    • offsetは、可視の範囲にカーソルが入っているかどうかを判定するのにも使う
  • マルチバイト文字対応
    • unicode-segmentationなるクレートを使う
    • Grapheme(書記素)
      • 文字として区別できる最小単位
  • 色付けはTermionの関数経由で行う。これもどうやらエスケープシーケンスがあるようだ
  • statusbarの表示までやるので見た目がそれっぽくなってきて楽しい

5章

ここからようやくファイルを編集できるようにする

  • deleteやbackspace、文字の入力に対応して楽しい
  • 削除や追加、enterは地味に考えることが多い
    • 行の途中でenter押したら改行するので、Rowの情報を前後に分けるとか
    • 行の右端でdelete押したら下の行が上がってくるとか
    • 普段何気なく使っている挙動について再認識できて面白い
  • 保存時の処理も作る

6章

検索を作る

  • シンプルな検索は、線形探索
    • graphemeで文字のindexを正しく受け取らないといけない
  • インクリメンタルサーチも作る
    • Promptでclosureを受けるようにして、loop後にcallbackを呼ぶようだ
    • 検索結果の移動は、現在より後ろに検索範囲を限定して再度検索を呼ぶという形になっている
      • 一覧を保持しているのかと思ったけど確かにこれでも動くなー
  • 検索方向を変えるのは結構大変

7章

シンタックスハイライトを作る
あまり乗り気になれなかった...

  • lexerのような構造体はでてこない
    • 行のstringを保持するRow構造体がhighlightの処理も行う
    • rustの構文に色付けしていく

最終更新: 2021-11-10