Journal InTime


2017-03-20 (Mon) [長年日記]

_ 大江戸Ruby会議06で発表してきた

大江戸Ruby会議06に参加してきたが、とても楽しかった。スタッフ・参加者のみなさんありがとうございました。

何となく技術よりのイベントなのかなと思っていたが、思ったよりエモーショナルな発表が多かったような気がする。 自分の発表は感動的なトークの後だときつい内容だったので、順番が最初の方*1でよかった。

mlterm上のTextbringerでプレゼンしたのだが、事前のプロジェクタチェックでモードラインが切れてるのに気付いていなくて、本番中にウィンドウサイズの調整に手間取ってしまった。 普段タッチパッド使わないので…。

Vimmerばかりだったらどうしようかと思ったが、Emacsユーザが多数派(主観)でよかった。

後でいただいた質問の回答をいくつか。

  • Q1. なぜ数ある実装方式の中でバッファギャップを採用したのか。

    A1. 行のリストみたいな方式だと、Rubyの場合たくさんオブジェクトができるのがつらいし、行をまたいだ検索の実装コストも実行コストも高くなりそうだから。 バッファギャップなら一つのStringオブジェクトで済むし、組み込みの検索機能が使える。 Stringはランダムアクセス向けの作りではないけど、Rubyで自前のデータ構造を作るよりは速い。

  • Q2. どれくらい使えるのか。

    A2. メールの読み書き以外はTextbringerを使っている。 Textbringer自体もRubyモードを実装したあたりからほとんどTextbringerで書いているが、Textbringer::Windowあたりを壊すとまったく使えなくなるので一時的にVimを使ったりする。 環境EDITORもtextbringerにしている。

  • Q3. MUAは本当に作るのか。

    A3. RubyKaigiまでに作りたい。 IMAPライブラリとかも前に自分で書いたので、簡単なものならすぐにできると思う。 問題はTextbringrのバックグラウンド処理APIをどうするかだけど、スレッド(将来はGuild?)+Control.Invoke()/BeginInvoke()的なものはどうかなとか考えている(要はなるべく同期的に書きたい)。 Emacsの欠点はバックグラウンド処理がバッファに依存した設計になっているところだと思う(最近のEmacs知らないけど)ので、このあたりを上手く作れば差別化できるのではという目論見。

なお、ネットワーク応用通信研究所はこういう話に興味のある人を募集しています。 Vimmerでも大丈夫です。

*1  どうやら人外枠だったらしい(怒)。


2017-03-13 (Mon) [長年日記]

_ Textbringer 0.1.9

Textbringer 0.1.9をリリースした。

変更点:

  • Support registers.
  • Support plugins.
  • Support global mark ring.
  • Support keyboard macro.
  • Support help (describe_bindings, describe_command, and describe_key).
  • Add tbtags.
  • Add the commands back_to_indentation, indent_region, delete_indentation, shrink_window, and shrink_window_if_larger_than_buffer.

さて大江戸のスライド書くか。


2017-02-19 (Sun) [長年日記]

_ Textbringer 0.1.8

Textbringer 0.1.8をリリースした。

0.1.7からの変更点:

  • シンタックスハイライトのサポート
  • grep, gsub, enlarge_windowコマンドの追加
  • CRをLFに変換しないよう修正。

asciicastは8色(正確にはA_BOLDを使った暗黙の色指定を合わせて16色)モードだが、256色の端末にも 対応していて以下のようにRGB値を指定するとカラーパレットから一番近い色を選択する。

# ~/.textbringer.rb
if Window.colors == 256
  Face.define :mode_line, foreground: "#ffffff", background: "#75507b"
  Face.define :link, foreground: "#8ae234"
  Face.define :comment, foreground: "#c4a000"
  Face.define :preprocessing_directive, foreground: "#4e9a06"
  Face.define :keyword, foreground: "#af87af", bold: true
  Face.define :string, foreground: "#729fcf"
end

デフォルトの前景色・背景色は以下のように変更できるが、このあたりの設定方法は変えるかも。

Window.set_default_colors("#ffffff", "#262626")

Curses.init_colorを使えばより正確な色表現ができるはずだが、tmuxとかだとCurses.can_change_color?が falseを返すのでそこまで頑張っていない。


2017-02-12 (Sun) [長年日記]

_ Textbringer 0.1.7

Textbringer 0.1.7をリリースした。変更点は、

  • EditorConfigのサポート。
  • CONFIG[:ambiguos_east_asian_width]を追加。 詳細はREADME参照。
  • Cモードの追加。
  • *Completions*バッファの追加。
  • 複数文字コマンドをエコーエリアに表示。

久々に以下のように長い正規表現を書いた。

TOKEN_REGEXP = /\G(?:
(?<preprocessing_directive>
  ^[ \t\f\v]*(?:\#|%:).*(?:\\\n.*)*[^\\]\n
) |
(?<comment>
  (?<multiline_comment> \/\* (?> (?:.|\n)*? \*\/ ) ) |
  (?<singleline_comment> \/\/ .*(?:\\\n.*)*(?<!\\)\n )
) |
(?<partial_comment>
  (?<multiline_comment> \/\* (?:.|\n)* ) |
  (?<singleline_comment> \/\/ .*? \\\n (?:.|\n)* )
) |
(?<keyword>
  (?:
    auto | break | case | char | const | continue | default | double | do |
    else | enum | extern | float | for | goto | if | inline | int | long |
    register | restrict | return | short | signed | sizeof | static | struct |
    switch | typedef | union | unsigned | void | volatile | while | _Bool |
    _Complex | _Imaginary
  ) \b
) |
(?<constant>
  (?<floating_constant>
    (?<decimal_floating_constant>
      (?<fractional_constant>
        (?<digit_sequence> [0-9]+ )? \. \g<digit_sequence> |
        \g<digit_sequence> \. )
          (?<exponent_part> [eE] [+\-]? \g<digit_sequence> )?
          (?<floating_suffix> [flFL] )?
    ) |
    (?<hexadecimal_floating_constant>
      (?<hexadecimal_prefix> 0x | 0X )
          (?<hexadecimal_fractional_constant>
            (?<hexadecimal_digit_sequence> [0-9a-fA-F]+ )? \.
                \g<hexadecimal_digit_sequence> |
            \g<hexadecimal_digit_sequence> \. )
          (?<binary_exponent_part> [pP] [+\-]? \g<digit_sequence> )
          \g<floating_suffix>? |
      \g<hexadecimal_prefix> \g<hexadecimal_digit_sequence>
          \g<binary_exponent_part> \g<floating_suffix>?
    )
  ) |
  (?<integer_constant>
    (?<decimal_constant> [1-9][0-9]* )
    (?<integer_suffix>
      (?<unsigned_suffix> [uU] ) (?<long_suffix> [lL] )?
      \g<unsigned_suffix> (?<long_long_suffix> ll | LL )?
      \g<long_suffix> \g<unsigned_suffix>?
      \g<long_long_suffix> \g<unsigned_suffix>?
    )? |
    (?<hexadecimal_constant>
      \g<hexadecimal_prefix> \g<hexadecimal_digit_sequence> )
          \g<integer_suffix>? |
    (?<octal_constant> 0 (?<octal_digit> [0-7] )* )
        \g<integer_suffix>?
  ) |
  (?<character_constant>
    ' (?<c_char_sequence>
        (?<c_char>
          [^'\\\r\n] |
          (?<escape_sequence>
            (?<simple_escape_sequence> \\ ['"?\\abfnrtv] ) |
            (?<octal_escape_sequence> \\ \g<octal_digit>{1,3} ) |
            (?<hexadecimal_escape_sequence>
              \\x \g<hexadecimal_digit_sequence> ) |
            (?<universal_character_name>
              \\u[0-9a-fA-F]{4} |
              \\U[0-9a-fA-F]{8} )
          )
        )+
      ) ' |
    L' \g<c_char_sequence> '
  )
) |
(?<string_literal>
  " (?<s_char_sequence>
      (?<s_char> [^"\\\r\n] | \g<escape_sequence> )+ ) " |
  L" \g<s_char_sequence>? "
) |
(?<identifier>
  (?<identifier_nondigit>
    [_a-zA-Z] |
    \g<universal_character_name> )
        (?: \g<identifier_nondigit> | [0-9] )*
) |
(?<punctuator>
  \[   |   \]   |   \(   |   \)   |   \{   |   \}   |
  \.\.\.   |   \.   |
  \+\+   |   \+=   |   \+   |
  ->   |   --   |   -=   |   -   |
  \*=   |   \*   |
  \/=   |   \/   |
  &&   |   &=   |   &   |
  \|\|   |   \|=   |   \|   |
  !=   |   !   |
  ~   |
  ==   |   =   |
  \^=   |   \^   |
  <:   |   <%   |   <<=   |   <<   |   <=   |   <   |
  >>=   |   >>   |   >=   |   >   |
  \?   |   ;   |
  :>   |   :   |
  ,   |
  \#\#   |   \#   |
  %>   |   %:%:   |   %:   |   %=   |   %
) |
(?<space>
  \s+
) |
(?<unknown>.)
    )/x

田中哲スペシャルのおかげでC99のBNFを書き写すだけだと思ったのも束の間、左再帰を避けたり、最左最長マッチに合わせて順番を入れ替えるのが結構大儀であった。

インデントの設定項目は(使ったことのない)xyzzyを参考に以下のようなものを用意した。

CONFIG[:c_indent_level] = 4
CONFIG[:c_indent_tabs_mode] = true
CONFIG[:c_continued_statement_offset] = 4
CONFIG[:c_case_label_offset] = -4
CONFIG[:c_label_offset] = -2

以下のように~/.textbringer.rbに設定するとRubyのソースとだいたい同じスタイルになるはず(バッファローカルの設定はindent_levelとindent_tabs_modeはc_が付かないので注意)。

add_hook :c_mode_hook, -> {
  buf = Buffer.current
  if buf.file_name &&
      File.dirname(buf.file_name).end_with?("/ruby")
    buf[:indent_level] = 4
    buf[:tab_width] = 8
    buf[:indent_tabs_mode] = true
    buf[:c_continued_statement_offset] = 4
    buf[:c_case_label_offset] = -2
    buf[:c_label_offset] = -2
  end
}

K&Rスタイルに対応してないのは仕様である。

_ ストームブリンガー

ストームブリンガー 永遠の戦士エルリック(マイクル ムアコック/井辻 朱美)

新訳版で読み進めていたがようやく第4巻の『ストームブリンガー』まで読了した。

第3巻所収の『薔薇の復讐』以外は旧訳で読んでいるはずだったが、記憶以上に呪われている感じだったので、Textbringerを使う時はバックアップに気を付けようと思う。

Tags:

2017-01-29 (Sun) [長年日記]

_ Textbringer 0.1.4

Textbringer 0.1.4をリリースした。 変更点は以下のとおり。

  • dabbrev_expand (M-/) の追加。
  • find_tag (M-.) と pop_tag_mark (M-*) の追加。
  • toggle_test_command (C-c t) の追加。
  • Windowsのためにbinmodeを使用するよう修正。

Textbringerのコード自体Textbringerで書いているが、壊してVimのお世話になることが大分少なくなったような気がする。

その代り、機能追加のコードを書く→別の機能不足でイライラ→別の機能追加のコードを書く→また別の機能不足でイライラ→また別の機能追加のコードを書く、の無限ループであっという間に時間が経つので定命の者にはつらい。 コードも<混沌の神々>の影響が強くなってきているように思われる。

0.1.2からは再び呪われし太古の秘法cursesの力を得たが、この先の道のりは長い。