textbringer はネットワーク応用通信研究所の 前田修吾 氏の作成した Emacs ライクな Ruby 製テキストエディタです。

Emacs 使いであり Ruby 好きな自分にとっては夢のようなエディタが誕生しました。
備忘録として textbringer の使い方をまとめます。

対象の textbringer は 0.2.2 (2017-04-21) のβ版です。今後の開発により設定方法やコマンド等が変更になる可能性があります。

text-bringer

textbringer の特徴

  • ターミナルで動作するテキストエディタ
  • Emacs ライクな考え方とコマンド形態
  • pure Ruby
  • Ruby で拡張できる(!)

実装済みの機能(抜粋)

  • UTF-8(日本語含む)ファイルの読み込み/保存
  • 設定ファイル
  • プラグイン
  • コマンド定義
  • キーバインド定義
  • eval-buffer
  • ウィンドウ(X window のウィンドウではなく Emacs のウィンドウ)
  • undo/redo
  • マクロ
  • メジャーモード(c-mode, ruby-mode)

これから実装される予定の機能

  • マイナーモード: #11

ドキュメントの想定環境

このドキュメントでは以下の環境を想定しています

  • Debian 9.0
  • ruby-2.4.1
  • textbringer-0.2.2

インストール

// 日本語(UTF-8)対応
$ sudo apt install libncursesw5-dev
$ gem install curses

// textbringer のインストール
$ gem install textbringer

mlterm の設定

ターミナルに mlterm を使っている場合は、Alt(Meta)キーを有効にするため以下の設定を追加します。

$ vi  ~/.mlterm/main
mod_meta_key = alt
mod_meta_mode = esc

基本的な使い方

基本的な概念(window, buffer)やコマンド(find-file, next-line)は Emacs を踏襲しているので、Emacs 使いの方は問題なく使えると思います。

起動

$ textbringer <filename>

基本操作

基本操作は Emacs のそれとほぼ同じです。
キーバインドによる操作を行わなくても M-x で呼び出せます。

キーバイド コマンド名 説明
C-xC-f find_file ファイルを開く
C-xC-s save_buffer 現在のバッファを保存
C-xC-w write_file ファイル名を指定してバッファを保存
C-xk kill_buffer 現在のバッファを削除
C-xC-c exit_textbringer textbringer を終了
C-s isearch-forward バッファ内を検索
C-/ undo アンドゥ
C-xC-_ redo_command リドゥ (アンドゥの取り消し)
C-n next_line 次の行に移動
C-p previous_line 前の行に移動
C-x2 split_window ウィンドウを横に分割
C-xo other_window 別のウィンドウに移動
M-x (command_name) - コメンド名を指定して実行
M-x eval_buffer - バッファの内容を Ruby コードとして評価

C は Ctl、 M は Meta(Alt) です。
C-x は 「C を押しならがら x を押下」を示します。

設定

全体の設定

各種エディタ/IDE の設定を一元管理する EditorConfig に対応しています。

$ textbringer ~/.editorconfig
# top-most EditorConfig file
root = true

[*]
end_of_line = lf

[*.rb]
indent_style = space
indent_size = 2

textbringer 固有の設定

textbringer 固有の設定は ~/.textbringer.rb に記述します。
拡張子が示すように純粋な Ruby スクリプトです。

$ textbringer ~/.textbringer.rb
# キーバインド
GLOBAL_MAP.define_key("\C-xn", :next_line)

コマンドを定義する

textbringer に独自のコマンドを定義するには ~/.textbringer.rb 内(またはプラグイン内)で define_command メソッドを使います。

$ textbringer ~/.textbringer.rb
# hello world コマンドを定義
define_command(:helloworld,
               doc: "hello world in textbringer") do
  insert "hello world"
  newline
end
$ textbringer
// M-x hellworld で hello world がバッファに挿入される

また、 eval_buffer に対応しているので textbringer 内でコードを書きながら評価することもできます。
eval_buffer のデモ

メジャーモードを定義する

textbringer でメジャーモードを定義するには ~/.textbringer.rb (またはプラグイン内)で FundamentalMode を継承したクラスを作成します。

# メジャモードは FundamentalMode を継承する
# sample_mode コマンドが自動で生成される
class SampleMode < FundamentalMode

  # モード内のコマンド定義
  # クラス内に def でメソッドを定義し define_generic_command でコマンド化する
  # メソッド名+_commad のコマンドを生成 (以下では sample_world メソッドを元に sample_world_command コマンドを生成する)
  define_generic_command :sample_world

  # モード用のキーバインド
  SAMPLE_MODE_MAP = Keymap.new
  SAMPLE_MODE_MAP.define_key("\C-x\C-h", :sample_world_command)

  # 初期化
  def initialize(buffer)
    super(buffer)
    buffer.keymap = SAMPLE_MODE_MAP
  end

  # define_generic_command でコマンドにするためのメソッド
  def sample_world
    insert "sample world!"
    newline
  end
end

これで sample_mode と sample mode 用の sample_world_command コマンド が作成できました。
textbringer を起動し M-x sample_mode でメジャーモードを変更し、 M-x sample_world_command (または C-xC-h)でコマンドを実行できます。

プラグインを定義する

textbringer v0.2.2 からプラグインファイルが、これまでの Gem パッケージに加え ~/.textbringer/plugins からも読み込まれるようになりました。66f8ee

~/.textbringer/plugins 以下に textbringer_plugin.rb ファイルがあれば起動時にそれを読み込むようになっています。

ここではカーソルのある行の Ruby を評価する(Emacs の eval-last-sexp のようなもの。ベタ実装なので既存のリージョンを破壊します) 「eval-line プラグイン」を作成します。

// プラグイン用のディレクトリを作成
$ mkdir -p ~/.textbringer/plugins/eval-line/lib
$ cd ~/.textbringer/plugins/eval-line/lib

// プラグインを作成 (ファイル名が textbringer_plugin.rb であること)
$ cat << EOL > textbringer_plugin.rb
define_command(:eval_line) do
  beginning_of_line
  set_mark_command
  end_of_line
  eval_region
end
GLOBAL_MAP.define_key("\C-x\C-e", :eval_line)
EOL

プラグイン(eval_line) の実行

読み込んだプラグインの eval_line コマンドは M-x eval_line で実行できます。
バッファの適当な個所に Ruby コードを書き、M-x eval_line (または C-xC-e)でその行を評価します。

下記例では Time.now にカーソルを合わせて、 [M-x eval_line] で エコー領域(一番下の行)に 2017-03-22 17:33:57 +0900 のような時刻が表示されます。

$ textbringer
Time.now

eval_line のデモ

Gem パッケージによるプラグインの作成は「「textbringer」のプラグインを Gem パッケージで作成する」を参照してください。

特定の Ruby ファイルで機能を拡張する

textbringer にはプラグイン機能が用意されているので比較的簡単に機能を拡張することができます。しかし、textbirnger は Ruby 製なので、Ruby のファイルを直接 require してベタに機能を拡張ことも可能です。

ここでは公式の方法ではないですが、Ruby ファイルを呼び出して機能を拡張する方法を紹介します。

// 機能拡張用のファイルを置くディレクトリ
$ mkdir ~/.textbringer

// 機能拡張ファイルを作成
$ cat << EOL > ~/.textbringer/experimental.rb
define_command(:experimental_command) do
  insert "this command is experimental"
  newline
end
EOL

// .textbringer.rb で設定
$ textbringer ~/.textbringer.rb
$LOAD_PATH.unshift "~/.textbringer"     # ロードパスを追加
require "experimental"                  # ファイルを読み込み

M-x eval_buffer でバッファを評価すると M-x experimental_command でコマンドを呼び出すことができます。

参考リンク