ハクソク

世界を動かす技術を、日本語で。

Ki Editor - AST上で動作するエディタ

概要

  • First-class syntax node interactionによる直感的なコード操作
  • Multiple cursorsで並列編集とリファクタリングの効率化
  • Redefine modal editingで統一された選択モードと柔軟な操作性
  • コーディング意図とアクションのギャップ解消
  • 一貫性と柔軟性を両立した編集体験

コーディング意図とアクションのギャップ解消

  • First-class syntax node interactionにより、構文ノードを直接操作可能
  • キーボードやマウスの複雑な操作を排除し、意図した編集を即座に実現
  • コード構造を保ったまま、柔軟なリファクタリングや編集が可能
  • 開発者の思考とエディタの動作をシームレスに接続

並列編集とリファクタリングの効率化

  • Multiple cursors機能で、複数箇所を同時に編集
  • 構文ノード単位での並列操作により、大規模なコード変更も迅速に対応
  • バルク編集や一括リファクタリングの時間短縮
  • コード品質維持と生産性向上の両立

統一された選択モードと柔軟な操作性

  • Redefine modal editingにより、Selection Modesを標準化
  • 単語、行、構文ノードなど、さまざまな単位での選択が可能
  • 一貫した操作性で、編集作業の混乱を最小化
  • 柔軟性と直感性を兼ね備えた新しいモーダル編集体験

Hackerたちの意見

シンタックスベースのナビゲーションを重視したVimライクな(ターミナルとVSCodeの拡張)エディタ。VimとHelixとの比較はこちら: https://ki-editor.org/docs/comparison#user-content-fn-1
あの比較表は変だし、時々間違ってることもある。例えば、Neovimはデフォルトで外部ファイルの変更を検出して更新するし。Kiのキーバインディングの一貫性は「素晴らしい」。bit vim/helix: > 「見ての通り、これらのキーマップには単一の論理的な分類がない。小文字-大文字、ノーマル-オルト、左右のブラケット、あるいは全く説明できないものもある。」Word、End、Back、Change Word、さらにはChange Inner(など)は僕には非常に論理的に感じるし、編集してるときにエディタと話してるような気分になる。別のやり方を学んだ人には意味がわからないかもしれないけど、理解しようとする努力をすれば全く意味があるんだ。自動運転を学んでずっと運転してから、マニュアルを「全く説明できない」と呼ぶようなもんだよ。単に別のやり方を学んで、それが唯一の正しい方法だと信じ込んでるだけなんだ。作成者がVSCode出身だってことがわかるね(マルチカーソルは無駄な機能、s/search/replaceを使ってマクロに慣れれば全く新しい世界が開けるよ)。
僕のエディタの分類はこんな感じかな。1. オーソドックス。見た目や統合に主に焦点を当ててる。2. モーダル、Vimの改善。基本的なVimのキーバインディングを維持しつつ、ちょっとした改善を加えてる。3. モーダル、Vimのアプローチを再考。Kiはこの3番目のカテゴリーに入ってて、常にチェックしてる。
4. 上記の全て。つまりEmacsだね。
Vimの改善。Edのビジュアルモードが改善された!
それなら、面白いかもしれないモーダルコードエディタのプロジェクトに取り組んでるよ。これもASTに直接操作してて、UIノードとして表現されてるから、普通のテキストレイアウトに近い感じになってる。もし試してみたいなら、プロフィールにメールしてね。早めのフィードバックももらえると嬉しい(まだ初期開発中だけど)。
私も全く同じだよ。今まで多くの挑戦者がいたけど、同じチャンピオンがいる(主観的なのは分かってるけど)。
「ファーストクラスの構文選択」は、Jetbrains IDEでよく使うショートカットを思い出させるな。選択を拡張/縮小するやつ。Ctrl + W Ctrl + Shift + W https://www.jetbrains.com/help/idea/working-with-source-code... ファイルの「テキスト」とのやり取りに対する見方が本当に変わった。VS CodeやZedなんかも似たような操作があるけど、僕の経験では、拡張と縮小がちょっと粗すぎる。
Neovimでもtree-sitterを使って`インクリメンタル選択`が利用可能だよ。
IntelliJの一番好きな機能はこれだな、あのバカみたいなコンテキストアクションメニューと一緒に。
同意する、最高の機能だよね。「メソッドを抽出する」みたいな機能と組み合わせると、地味なリファクタリングが超早くなる。
自分もhelixで常に使ってるよ。vscodeのは微妙だけど。GitHubでtree-sitterに切り替える話を見たことがあるけど、それがAST関連のアクションを改善するはずだった。結局、何も進展しなかったと思うけど。ASTを意識した編集が大好きなんだ。Lispを編集するのがいつも楽しい理由の一つだと思う。JavaScriptで説明するのが複雑なもの(LSPサポートがないもの)は、ほぼ全てASTパーサーが必要だけど、Lispだと単純なリスト操作で済むからね。Clojureの週末を過ごした後にTypeScriptに戻ると、slurp!や他のpareditコマンドがすごく恋しくなるよ。
そうだね、JavaのIDEは2000年代のどこかからこれを持ってたよ。
Emacsのパッケージが出るまで待つよ。
https://github.com/mickeynp/combobulate
これのためにVSCodeの統合を作ったんだ。あんまり貢献できてないのが申し訳ないけど、すごくクールなプロジェクトだよね。個人的には、私たちの技術の基盤となるツール(エディタ、言語、ツール、OSなど)で革新を試みることが大事だと思う。Kiはそれをやってる。
これ? https://marketplace.visualstudio.com/items?itemName=ki-edito...
早く試してみたいな。キーボードレイアウトに依存しないのがいいね。ドキュメントには他にも良さそうなアイデアがたくさんある。特に、Emacsからのインスピレーションで、すべてが編集可能なバッファになってるのが面白い。でも、エディタ間には常に大きなトレードオフがあるから、どうなるか見てみないとね。
編集モデルに基づいてエディタが作られてるのは残念だよね。すごく時間を無駄にして、すべてを再作成する羽目になる。Neovimは多くの面で完璧なエディタだけど、編集モデルはその中には入らないと思う。Neovimがvimの部分をプラグインで完全に置き換えられたら、HelixやKiは必要ないんじゃないかな。
レイアウトに依存しないエディタを目指すのは、キーボード自体でレイアウトを設定している僕みたいな人にはほぼ確実に悪夢だね。エディタをダウンロードしたんだけど(今はWindows使ってる)、Dvorakに設定したキーボードで試してみたら、明らかに壊れてた。マッピングを修正する方法があると思うけど、ソフトウェアが自分より賢いと思ってると、すごくバカにされた気分になるよね。
例を見て初めて完全には理解できた > 一級の構文修正 > 現在のノードと次のノードの間のカンマも削除されることに注意 > カンマが自動的に追加されることに注意。これすごい!論理的には少ないロジックでできるんじゃないかな。面白いね。今、ZedにKiの統合(または少なくともASTファーストの書き直し)を入れるのにどれくらいの労力がかかるか気になってる。
AST編集に関しては、時々自分が無知だなって感じる。コンピュータサイエンス的にはASTが何かは理解してるけど、大規模なソフトウェアのリファクタリングで直接ASTのテキストオブジェクトを編集したことはないんだ。自分のスキルレベルの指標かもね…。使い方としては、(neo)vimにはないarglistsや関数と簡単にやり取りできるテキストオブジェクトがあるくらい。関数のどこかに「daf」って書くだけで「そのまま削除」できるのはすごく可愛いし便利だよね。基本的なマクロと組み合わせて、正規表現を検索して「daf」って感じで使ったりもする。目の前にないものや、すごくシンプルじゃない変更(名前の変更とか)を編集するのは難しいな。少なくとも、自分が理解できる基本的なこと(正規表現で探してテキストオブジェクトで削除するみたいな)じゃないと。LSPについては、定義に移動したり、すべての参照をリネームする機能は使ってるけど、それ以外のLSP機能はあまり使ってないな…基本的に、エディタのスキルを上げないといけないな。
同じ気持ちだよ。Elixirを学んでマクロを書くようになったのは本当に役立った。Lispも同じだけど、Elixirの構文の方が自分には合ってたかな。目的地に行くための道はいろいろあるけど、誰かの役に立つかもしれないと思ってシェアしてみた。
正直、思ってるほど難しくないよ。大体の時は、全体の構文ノードを選択して削除したり、コピーしたり、置き換えたりするだけ。実際にASTの構造を理解する必要があるのは20%くらいかな。
> 「目の前にないものや、すごく簡単な変更(名前の変更とか)じゃないと編集するのが難しいんだよね。少なくとも、正規表現で探してテキストオブジェクトで削除するみたいな、基本的なことは理解できるけど。これがast-grepみたいなツールのいいところなんだ。パターン言語がほぼコードそのものみたいに読めるから、目の前で変換が見える(少なくとも小規模なケースでは)し、それについて考えることができる。」 TypeScriptの例: # ガード句をオプショナルチェイニングに変換 `ast-grep -pattern '$A && $A.$B' --rewrite '$A?.$B' -lang ts` # 自己代入をヌリッシュコアレッシング代入に変換 `ast-grep -pattern '$X = $X ?? $Y' --rewrite '$X ??= $Y' -l ts` # アロー関数を関数宣言に変換(asyncや戻り値の型注釈用に別のパターンが必要だけど) `ast-grep -pattern 'const $NAME = ($$$PARAMS) => { $$$BODY }' --rewrite 'function $NAME($$$PARAMS) { $$$BODY }' -l ts` # indexOfチェックを.includes()に変換 `ast-grep -pattern '$A.indexOf($B) !== -1' --rewrite '$A.includes($B)' -l ts` $Xや$Aは任意のASTノードにマッチするメタ変数で、同じメタ変数が2回出てくると(例えば$X = $X ?? $Y)、その2つの出現が同じコードにバインドされる必要があるから、`x = x ?? y`はマッチするけど、`x = y ?? z`はマッチしない。yamlルールを使えばもっと高度なこともできるけど、視覚的には直感的じゃない。残念ながら、コーディングエージェントはast-grepパターンを書くのがまだかなり下手だと思う。おそらくトレーニングデータが少ないからだろうね。これが改善されるといいな。このツール自体はしっかりしてるよ!
数週間前にASTを使ったVCS/diffに関するShow HNがあったけど、名前覚えてる人いる?
Diffsitterとかweaveかな?
ポジショナルキーのバインディングは好きじゃないな。QwertyやDvorak用にプロファイルで設定した通常のキー配置と本質的には変わらないし。実際には、キーボードに描かれたものを探したり、ターミナルやどこでもすぐに使うのが難しいだけなんだよね。「ライン」キーはどこ?描画を探してみて! (ああ…左上の隅にあるけど、どのキーか正確にはわからないし。)リストの方が好きだな。だから、実際にはプレゼンテーション以外はそんなに「特別なこと」でもないんだよね。