HN 日本語サマリー

← 一覧へ戻る
プログラミング

e: Chez Schemeで書かれた、カスタマイズ可能で自己認識的なEmacs風エディタ

e is a customizable self-aware Emacs-like editor written in Chez Scheme (github.com)

11 pointsby p4bl05 コメント

要約

eはChez Schemeで書かれた、Emacsに似た精神を持つ軽量なコンソールテキストエディタです。Emacsの機能を取り入れつつ、小さく保つことに重点を置いています。エディタ自体がSchemeシステムとして機能し、モジュールのホットリロードや、エディタ内でのSchemeコード評価など、高度なカスタマイズ性と自己拡張性を備えています。依存関係はChez Schemeのみで、インストール不要で即座に実行可能です。

全文翻訳

e Chez Schemeで書かれた、小さなコンソールテキストエディタです。 バッファ、ウィンドウ、キルリング、インクリメンタルサーチ、Schemeトップレベルなど、Emacs風の精神を持っていますが、Emacsのクローンではありません。小さく保つというアイデアを取り入れ、それ以上のことはしません。 エディタはSchemeシステムです。すべてがR6RSライブラリです。公開された不変のAPIを持つ最小限のコアと、その上に構築された拡張モジュール(シンタックスモード、ブラケットマッチング、編集ヘルパー、M-x自体)です。 コアは規律ではなく言語によって境界を強制します。内部は不可視で、エクスポートは再割り当てできません。 M-xは、シンボル補完、入力中のパラメータヒント、履歴、トランスクリプトバッファを備えた、エディタのライブトップレベルに対してSchemeを評価します。 モジュールはホットリロードされます。エディタ内でモジュールのソースを保存すると、実行中のセッションにリロードされます。外部で編集されたソースはreload-module!で検出されます。登録は置き換えられ、依存モジュールは再コンパイルされ、バッファはそのまま保持されます。 eはそれ自体の中から開発されています。 Chez SchemeとUnixライクなターミナル以外の依存関係はありません。 ビルドやインストールのステップはありません。チェックアウトすればそのまま実行できます。 最初の起動時にライブラリがコンパイルされます。それ以降の起動は約100ミリ秒です。 Undoは、Undo insert "hello"、Undo (replace-all! "xx" "yy") のように、何を取り消したかを報告します。 入力された文字は一連の操作としてまとまり、ペーストは単一のステップ、M-xコマンドはラベル付きの1つのステップになります。 クイックスタート 日常のエディタとして、~/.e にクローンします。 git clone https://github.com/paveluv/e ~/.e ~/.e/e file.txt # 単純な`e`のために~/.eをPATHに追加 またはプロジェクト内にベンダーとして組み込むことで、プロジェクトをクローンした誰もが動作するエディタを入手できます。 git clone https://github.com/paveluv/e ~/git/your_project/.e rm -rf ~/git/your_project/.e/.git # リポジトリの通常のファイルにする ~/git/your_project/.e/e file.txt すべてのインストールは自己完結型です。ローダーはスクリプト自体の隣にあるlib/のみを厳密に使用し、コンパイルされたオブジェクトはeo/内にローカルに留まり、ソースはそれら(またはそれらがインポートするもの)が変更されると自動的に再コンパイルされます。 ベンダー化されたチェックアウトのlib/にドロップされたプロジェクト固有のモジュールは、そのプロジェクトにローカルに留まります。 ターミナルサイズはioctl経由で検出され、リサイズ時に追跡されます。それが利用できない場合は、LINESとCOLUMNSを設定します。 FreeBSDでは、Chezポートがscheme-scriptインタプリタの名前を変更するため、shebangを#! /usr/bin/env -S chez-scheme --script に変更するか、chez-scheme --script e を実行します(詳細はローダーのヘッダーコメントを参照)。 キーバインディング ファイルと終了 キー アクション C-x C-s 保存(名前のないバッファで名前をプロンプト表示) C-x C-w 名前を付けて保存:パスをプロンプト表示し、バッファがそれを訪問します C-x C-f ファイルを独自のバッファで訪問(必要なら作成) C-x C-c 終了(バッファがファイルと異なる場合にのみ質問) バッファとウィンドウ キー アクション C-x b バッファを切り替え(デフォルト:直前の他のバッファ;新しい名前はバッファを作成) C-x C-b *buffers*を開く:上下で移動、Enterで選択;クリックで即時選択 M-Up アルファベット順で前のバッファに切り替え M-Down アルファベット順で次のバッファに切り替え C-x k バッファをキル(デフォルト:カレント;変更されている場合は質問) C-x 2 現在のウィンドウを2つに分割(スタック) C-x 3 現在のウィンドウを2つに分割(横並び) C-x 1 他のすべてのウィンドウを削除 C-x 0 現在のウィンドウを削除 C-x o 次のウィンドウに移動 C-x t このウィンドウで長い行のソフトラップをトグル 各ウィンドウには独自のステータスライン、ポイント、スクロール位置があります。同じバッファを複数のウィンドウに同時に表示できます。 バッファにはバッファごとの履歴とマークがあり、ウィンドウには独立したポイント、スクロール、ラップ、ステータスがあります。 デフォルトでは右側にスクロールバーが表示されます。C-x l はバッファ所有の行番号ガターをトグルします。 バッファの切り替え、*buffers*、ファイル整合性、ターゲットウィンドウ、マウス動作、スクロールバー、ラップ、分割、公開APIについては、Buffersを参照してください。 移動 キー アクション C-b / C-f / arrows 左 / 右に1文字 C-p / C-n / arrows 上 / 下に1行 C-a / C-e, Home/End 行の先頭 / 末尾 C-v / M-v, PgDn/PgUp ページダウン / アップ M-< / M-> バッファの先頭 / 末尾 編集 キー アクション C-d, Delete ポイントの後の文字を削除 Backspace ポイントの前の文字を削除 C-o ポイントをその場に残して下の行を開く C-k 行末までキル(繰り返しで累積) C-@ (C-Space) マークを設定 C-w マークとポイントの間の領域をキル C-y 直前のキルをヤンク C-_ Undo C-M-_ Redo TAB モードのルールに従って行をインデント M-% ポイントからクエリ置換:y/SPCで置換、n/DELでスキップ、q/RET/C-gで停止 M-. ポイントのシンボルを説明(Schemeバッファ;以下参照) C-x C-e 現在のバッファをSchemeとして評価 C-l 画面を再描画し、サイズを再読み込み C-g キャンセル(プロンプト、検索、マーク、実行中の評価) C-h k キーとそのバインディングの出所を説明 キーカスタマイズ すべてのキーボードコマンドはconfig.eで再バインドできます。 ユーザーバインディングは組み込みおよびモジュールのデフォルトをオーバーライドし、C-h kはキー、そのソース、およびコンテキスト上の意味を説明します。 (bind-key! "C-c s" save!!) (unbind-key! "C-v") キー構文、コンテキストマップ、利用可能なアクション、優先順位、バインド解除、モジュールのデフォルトについては、Key binding configurationを参照してください。 検索 C-s はインクリメンタルサーチを開始します。入力してニードルを拡張し、再度C-sを押すと次のマッチにジャンプします(ラップアラウンド)、Backspaceでニードルを短縮、RET/ESCでサイレントに受け入れ、C-gでキャンセルしてポイントを検索開始位置に戻します。 新しく空の検索で、C-sは前のニードルを呼び出して検索します。ポイントは現在のマッチのすぐ後ろに位置するため、検索前に設定されたマークは、見つかったテキストをリージョン内に残します。 検索中は、現在のウィンドウでのニードルのマッチがハイライトされます。 マッチングはEmacsのようにスマートにケースを無視します。ニードルがすべて小文字の間はケースを無視し、1文字の大文字を入力すると正確になります(プロンプトはI-search (exact):と表示されます)。 M-c は現在の検索をどちらかの方向にトグルし、config.eの(search-fold-case #f)はすべての検索を正確にします。 すべてその他(M-%クエリ置換を含む)は常に正確にマッチします。 インデントとフォーマット インデントは強制される唯一のものです。行内のスペースは作者のものです(テーブル、アラインメント、手作業のレイアウトが構造を伝えます)。行は結合されたり分割されたりしません。 SchemeのルールはEmacs風です。ボディフォーム(define、lambda、letファミリー、whenなど)は、ボディをオープナーの2列後ろにインデントします。単独のクローザーはオープナーの下に配置され、アプリケーションの継続行には2つの停止位置があります:オープナーの2列後ろ、またはオープナーと同じ行にある最初の引数の下にアラインされた位置です。 作者が選択します。 (very-long-function-name param1 param2 param3) (very-long-function-name param1 param2 param3) TAB は現在の行を、その停止位置を循環させながら(右側の最も近い停止位置、ラップアラウンド)、ポイントをインデントに配置します(空行がそれにパディングされます)。モードはインデンターを登録する際にオプトインし、scheme-modeもそうします。 indent-region! および indent-buffer! は、上から順に行ごとに1つのUndoステップとしてインデントし、各行は現在のインデントに最も近い停止位置に落ち着きます。停止位置にある場合はそこに留まり、最初の位置の前にある場合は最初の位置を取り、最後の位置の後ろにある場合は最後の位置を取ります。 format-region! および format-buffer! は、さらに文字列の外側のタブをスペースに広げます((scheme-tab-width 2); #fはタブを保持します)、末尾の空白をトリムし、末尾の空行を削除してファイルが正確に1つの改行で終わるようにし、ブラケットの規則を適用します。letファミリー、do、parameterize、with-syntaxのバインディング、およびcond、case、case-lambda、guard、syntax-rules、syntax-caseの句には[ ]を使用し、それ以外はすべて( )を使用します。scheme-format-bracketsパラメータはそれをオフにします。 リージョンフォーマットは、完全に含むブラケットペアのみを書き換えるため、バッファのバランスを崩すことは決してありません。文字列の内部とマージンコメントは決して触られません。 モジュールは、register-indenter! および register-formatter! を使用して、モードごとにルールを提供します。 Schemeエンジンは純粋な(scheme-format)ライブラリであり、これはtools/scheme-formatも駆動します。シェルからscheme-format [-i] [file ...] で同じ処理を行うか、引数なしで標準入力から標準出力に処理します。(scheme-format-on-save #t)(デフォルトでオン)を使用すると、Schemeバッファのすべての保存時にまずフォーマットされます。