これはemacs Advent Calendar 2021 24日目の記事です。


偏見かもしれないが、いまの時代にEmacsを使っている人の90%はOrg Modeがあるから使っているのだと思う。少なくとも自分はそうだ。
2019年にこのOrg Modeに1つの不具合を見つけ、パッチを送った。これは自分にとって初めてのOSS活動だった。パッチの送り方がやや特殊で、かなり悩みながら送った。
そのため、時間が経ってしまっているのだがここにメモとして残しておく。

以下、Org Modeをorg-modeと書く(公式を見ると"Org Mode"というのが正式表記らしいが、"org-mode"の方が見慣れているため)。

org-mode

org-modeは膨大な機能を持つ巨大なモードで、すべてを紹介するのは無理。

自分はEmacsはもっぱら日本語の文書やメモを書く用に使っている。(コードはVimやIDEで書く。)
このときorg-modeはアウトライナーとして使える。Markdownのようなものだが、階層構造の修正や移動が簡単にできる。

今回はorg-modeの中のorg-babelという機能の話。

org-babel

orgファイルで <s と入力してTABを押すと、コードブロックに展開できる。そしてその中で使う言語などを書き、 C-' と押すと別バッファが開いて、その中でコードブロックを編集できる。もう一度 C-' と押すと、コードブロック用バッファが閉じて元に戻る。この機能がorg-babelの一部。 C-c C-c でコードブロックの実行もできたりする。

[2021/12/26 追記]
<s TAB でコードブロックに展開するのは古いバージョンの話だった。新しいバージョンでは C-c C-, でやる。
Structure Templates (The Org Manual)
9.2から変わったようだ。
org-mode/ORG-NEWS at main · bzg/org-mode · GitHub

どういうときに使うかというと、プログラミングのTipsメモでサンプルコードを書くのに使ったり、読んだWeb記事の抜粋をしたいときに使っている(抜粋部分がはっきりするため)。

GIFで使っているorg-modeはやや古く、バージョン9.1.9。
プログラミング支援のプラグインを入れていれば、コードブロックバッファでの編集がもう少しかっこよくなるはず。 org-babelサンプル

どんな不具合を見つけたか

org-babelで日本語を書いていると、 C-' でコードブロックに入るとき、どんどんインデントが増えていくことがあった。

インデントがおかしい

半角文字だと問題ない。

コードブロックの中にいろいろ書いて試してみると、コードブロックの中に入るときに、不要なインデントが削除されることがわかった。つまり全体がn文字インデントされて、左側n列分が真っ白だと、そのn文字分のインデントは削除される。これは合理的な挙動だと思う。
ところが インデントの最も少ない行がすべて全角文字で始まっている場合 はインデント削除が正常に機能しない。

問題の出方の比較

どう直したか

まずこの問題が自分の環境でだけ起きているのかを調べた。
init.elを読まないように emacs -q で起動し、これでも同じ問題が起きることを確かめた。

次に、いまも直っていないのかを調べた。
最新のリリースと、リポジトリにある開発版を調べた。直っていないようだった。
後述のメーリングリストで、この不具合を報告・修正着手している人がいないかも調べた。

あとはコードを修正する。
M-x describe-key を使って C-' のときに呼ばれる関数を調べてみると、コードブロックに入るときは org-edit-src-code という関数が呼ばれている。このコードを読んだり、少し変えて挙動の変化を見たりして調べまくった。

結果、 org-do-remove-indentation を修正すればよさそうだと思った。
この関数はバッファ内の全行に共通でかかっているインデントを消す。処理としてはバッファ内の最小のインデント min-ind を計算し、そのあと各行のインデント ind を見て、インデントを削除する。もちろん普通は ind >= min-ind になる。が、全角文字の場合は min-ind の処理がうまくいかず、 ind < min-ind になることがある。これが原因らしい。(記憶が曖昧だがそんな話だったと思う…。)

これは1行直せばよかった。この直し方で問題ないか、動作確認をした。
確認中に、どういう経緯で見つけたのか忘れたが、「曖昧幅文字」というものの存在を知った。環境によって、全角になったり半角になったりする文字のことらしい。これは今回の修正にダイレクトに関わってくるので、曖昧幅文字があってもこの修正でうまくいくか調べた。

パッチを送る

コードの修正方法はわかったので、パッチを送る。

Contributing to Org
ここにコントリビュートの方法が書いてある。パッチの送り方も書いてある。これを熟読する。
パッチはメーリングリストに送ればいいとのことなので、メーリングリストに登録した。メーリングリストについては以下のページに書いてあり、登録ページへのリンクもここにある。
Org mailing list
メーリングリストに登録しなくても問題はないはず。アーカイブはemacs-orgmode Archivesにある。

パッチを送る際の作法的なことも上記ページに書いてある。
コミットメッセージについては例とともに詳しくルールが書いてあるので、その通りに書く。
あと、いきなりパッチを送っていいのかも少し確認した。まず問題を報告してからパッチを送らなければいけないというような作法がある可能性もあった。上記のページを読んで、おそらくそのような決まりはないと判断した。なのでパッチを送ることにした。(問題報告してからパッチを送る方がマナーは良いのかもしれない…?)

リポジトリ

GitHubにbzg/org-modeというリポジトリがあるが、これはミラーであり、ここにPull Requestをしてはいけない。
真のリポジトリはここ。(パッチを送った当時はここだった。現在ここにアクセスすると下記にリダイレクトされる。)
emacs/org-mode.git - Emacs Org mode

TINYCHANGEについて

これまでの累積の変更が15行未満(less than 15 lines)で、かつFree Software Foundation(FSF)のcopyright assignmentにサインしていない人は、コミットメッセージの最後にTINYCHANGEと書くことになっている。
15行というのは厳密な数字なのかよくわからない。
いずれにせよ今回の変更は1行だけなので、TINYCHANGEと書く。

これを超えるとFSFに著作権譲渡をする手続きが必要らしい。この手続きは昔はサインした書類を郵送するらしかったが、いま調べると普通にオンラインで完結するようだ。

やったこと

2019年当時の話。

  1. 最新のmasterブランチからブランチを切る
    現在ではmainブランチかbugfixブランチから切るとドキュメントに書いてある
  2. コードを修正
  3. コミットする
    コミットメッセージはちゃんとしたものにするが、あとでも変えられる。
  4. authorを変える[不要だった]
    過去のコミットログを見ると本名で書いている人が多かったので、自分もそうした。 git commit --amend --author='名前 <メールアドレス>' で変えられる。これもあとで変えられるので不要だった。
  5. git format-patch master
    (これも現在はmasterのところが違うはず。)
    これを実行して作成されるパッチファイルを送ることになる。パッチファイルは単なるテキストなので、コミットメッセージやauthorを変えたい場合はこのタイミングで変えられる。
  6. パッチをメーリングリストに送る
    git send-email を使う方法が紹介されていたが、自分はThunderbirdかブラウザのgmailから送ったと思う。

[O] [PATCH] org-macs: Fix indentation for fullwidth characters
これが実際に送ったパッチ。この本文には、送ったメールの本文がそのまま入った。
メールのタイトルは "[PATCH] org-macs: Fix indentation for fullwidth characters" だった。なので [O] が先頭についている。いまではないようだが、2019年10月までは自動的にタイトルにこれがつくようになっていた。(送る前は、もしかしてこれは自動でつくのではなく、メールのタイトルに [O] をつけて送るのだろうかと悩んだ。これを見つけて、つけなくていいとわかった。)
末尾の 2.23.0 にいま気付いたが、 git format-patch のときにGitのバージョンが出たのをそのまま書いていたらしい。不要。

その後

1週間ほどして、メールが来た。
Re: [O] [PATCH] org-macs: Fix indentation for fullwidth characters

修正箇所はよかったようだが、内容を変えて取り込まれた形。なので自分はauthorではない。
コミットはこれ。
emacs/org-mode.git - Emacs Org mode

そしていまはコードブロックに日本語を書いても、インデントがずれるようなこともない。
この箇所にバグがあって再度変更があったということも起きていないようだ。
(この変更は悪影響がないと思うが、人知れず被害を受けている人がいないことを祈る…。)

おわりに

たった1行変えただけ、しかも結局マージされなかったという話なのに、ずいぶん長々と書いてしまった。

authorになれなかったのは残念だが、関数を把握していなかったのでしょうがない。
Emacsやorg-modeにどういう関数があるか、もっと調べておくべきだった。

いま見るとひどいパッチだ。
だがこんなものでも世界中の人が使っているものに貢献することはできた…のだろうか。
また機会があれば、org-modeに限らず、なにかやりたいと思う。

変更履歴

  • 2021/12/26
    新しいバージョンでのコードブロック展開方法について追記。他字句修正など。