by shigemk2

当面は技術的なことしか書かない

fish shellのコマンドマニュアルでコマンド名が二度表示されるのを直したい→直した

www.shigemk2.com

コピーのテスト。

直したプルリク

取り込まれるかどうかは知らない→取り込まれた。 github.com

概要

fish shellで、abbr --help とか man abbr を実行すると、以下のような結果が得られる。

       abbrabbr - manage fish abbreviations
        -

   Synopsis
       abbr --add [SCOPE] WORD EXPANSION
       abbr --erase word
       abbr --rename [SCOPE] OLD_WORD NEW_WORD
       abbr --show
       abbr --list

最初のセクションでabbrが2つ続いている。2つ続いてはダメでしょう。

バグの原因

Doxygenの生成元のファイルの書き方の問題。

man pageもwebのドキュメントも、doc_srcディレクトリのテキストファイルからDoxygenで生成している。以下は実際のテキストファイルdoc_src/abbr.txtのいちぶ。

\section abbr abbr - manage fish abbreviations

\subsection abbr-synopsis Synopsis
\fish{synopsis}
abbr --add [SCOPE] WORD EXPANSION
abbr --erase word
abbr --rename [SCOPE] OLD_WORD NEW_WORD
abbr --show
abbr --list
\endfish

\sectionではセクション名とセクションタイトルを続けて書かないといけないが、セクション名とセクションタイトルが同名で続いているために、manで表示するとabbrabbrで表示されてしまう。 ちなみに、abbr.txtの中身はwebドキュメント上ではcommands.htmlのなかで表示されるが、HTMLではこのように生成される。

 <h1><a class="anchor" id="abbr"></a>
abbr - manage fish abbreviations</h1>
<h2><a class="anchor" id="abbr-synopsis"></a>
Synopsis</h2>
 
 <pre class="fish synopsis">
<span class="command">abbr</span> <span class="argument">--add</span> <span class="argument">[SCOPE]</span> <span class="argument">WORD</span> <span class="argument">EXPANSION</span>
<span class="command">abbr</span> <span class="argument">--erase</span> <span class="argument">word</span>
<span class="command">abbr</span> <span class="argument">--rename</span> <span class="argument">[SCOPE]</span> <span class="argument">OLD_WORD</span> <span class="argument">NEW_WORD</span>
<span class="command">abbr</span> <span class="argument">--show</span>
<span class="command">abbr</span> <span class="argument">--list</span>

\sectionでセクション名はa#idとして、セクションタイトルはh1の本文として表示されている。 \sectionでセクション名とセクションタイトルを別名にしてしまえばmanでabbrabbrと表示されるバグは回避出来るが、今度はHTMLが正しく表示されない。

マニュアル生成の実体

マニュアル生成はこのスクリプトで行っており、通常のDoxygenから、かなりカスタマイズしたものになっている。 fish-shell/build_documentation.sh at master · fish-shell/fish-shell · GitHub

マニュアル生成の部分についてざっくりまとめると

  1. tmpディレクトリを作成
  2. 1で作成したディレクトリのなかに、doc_srcのtxtを一部コメントをくっつけて、.doxygen拡張子にリネームしてコピー(このディレクトリはマニュアルを生成するためだけのファイルしか置かれていない)
  3. 2でdoxygenを実行(実行するときはマニュアル生成のための設定ファイルDoxyfile.helpを読み込む)
  4. doxygenで生成したマニュアルについて一部文言を修正

というふうになっている。2と4でちょっとしたシェル芸が使われていて、単にtxtファイルを修正したら影響範囲がでかすぎるけど、ここのシェル芸を弄ればうまい具合にバグを回避できそうなので、2と4の修正でバグ回避を試みた。

(そもそもDoxygenで\sectionでセクション名とセクションタイトルが同じ名前だとうまく出力されないことは確認できているので、Doxygen自体を修正することも考えたけどC++わからないし時間がかかりすぎるからやめた)

シェル芸の修正

あとはsedと正規表現の領域。Gistにまとめたけど、\sectionのセクション名とセクションタイトルが同じにならないようにtmpのテキストファイルを修正しつつ、下の例でand.1.organd.1のように書き換えるシェル芸を書いた。

改行コードはzオプションで書かないといけないとか、そもそもオリジナルのsedシェル芸(コマンド名を太字にする "s/^$CMD_NAME * \\\- \([^ ]*\) /\\\fB\1\\\fP -/")が失敗しているとか、-e-zは組み合わせることができないとか、"もちゃんと消さないといけないとかいろいろ工夫してシェル芸を書いた。工夫になっているかどうか知らないけど。 gist.github.com

なお、修正してもらうのに時間がかかりそうだしIssue自体あんまり捌けてなさそうだから、Issueは投げてない。あれこれ考えつつアズールレーンをプレイしながらコードを書いていた。

コメントレビュー

Macだとsedの-zオプションが使えないということを言われた。たしかにそうだ。でも-zを使わないで改行を置換するにはどうしたらいいか。というところをあれこれいろいろ考えていたら、Perlに行き着いた

まとめ

Doxygenの問題なのかfish shellの問題なのかよく分からなくて若干苦戦した。関数のヘッダーの情報をDoxygenでHTML表示するのはかなり前にやったことがあるけど、man pageを生成するのは初めてだったしやり方も書式もよく分からなかったのが原因だと思う。

この修正でさえも良い修正とは思っていない。Issueも投げておくべきだったかなーとは思う。manの書き方は少しだけ理解したし、ソースコードを1行1行読んで何をやっているか把握して文章にするのはすごく大事だと思う。