技術メモ、Tips、忘備録

技術系のメモ、試してみたこと、その他

【失敗談】Gitのコマンドとオプションを補完するコンソールアプリケーションを作ろうとした話

前置き

gitのコマンドとオプションを補完するコンソールアプリケーションを作ろうとしていましたが、失敗しました。
何がだめだったか、どうすべきだったかを自戒も込めて記事にします。

何がしたかったか

作りたかったものはタイトルの通りです。
手順としては、
1. gitの公式サイトのコマンド一覧からコマンドとオプションをスクレイピングする
2. 1でスクレイピングしたものをもとに、補完するための仕組みを作成する。
です。

コマンド、オプション、synopsisのスクレイプ

まず、スクレイプするにあたり以下のことを考えなければいけません。
1. 対象のコマンドは?
2. スクレイプのルールは?

1については、command_list.txt公式サイトの一覧をベースに、いらないもの(コマンドではないもの等)を除外してスクレイプ対象のコマンドを決めました。

2について、それぞれ以下のように決めました。
■ URL & command
https://git-scm.com/docs/git-{command}」という形式でコマンドごとのリファレンスがあります。
例えばaddコマンドだとhttps://git-scm.com/docs/git-addといった感じです。

■ synopsis
ざっくりいうと、コマンドごとのリファレンスのHTMLを見ると、シノプシス_synopsisというidに属しています。

■ options
ざっくりいうと、コマンドごとのリファレンスのHTMLを見ると、オプションはすべて_optionsというidとhdlist1というクラスに属していることがわかります。

ここまでそろえば簡単ですね。...と思っていましたが実は少しめんどくさかったです。

スクレイプで躓いたこと

結論から言うと、スクレイプのルールの前提が甘かったです。甘かったといってもほとんどはルール通りスクレイプできましたが、一部のドキュメントがルールに沿わない構造となっていたため、個別ルールを追加してスクレイプしました。
そもそもの目標の1つとして「gitのアップデートに柔軟に対応する」というのがありました。
しかし、上記のような「例外(ルールを外れたスクレイプ)」を許してしまうと、gitのアップデートのたびにスクレイプ用のアプリを改修しなければいけない可能性があるので、あまりよくない状況になりました。

ともあれスクレイプはひとまず完了

自分のプロジェクトに実際にスクレイプしたものがあります。ご参考までに

スクレイプしたものを解析する。

上のセクションで、synopsisもスクレイプしました。このセクションで使うためです。
まずはそれぞれのオプションがどのように使われるかを知る必要があります。そこで、synopsisを解析し、オプション一つ一つにメタデータ(値を持つか、他のオプションと同時に指定できるか、等)を付けようと考えました。

sinopsis解析のパターン

まずはsynopsisの記法についてです。
調べてみましたが、あまり参考になるものを見つけられませんでした。正規表現の概念に依存するというようなことはあったのですが.....

まぁでも、何となくsynopsisの記法は直感的に理解していたので、適当にやってみるか!となりました。

...が、これが思ったより難しい。当たり前ですが、人が見れば普通に分かることでも、機械的に解析しようと思うと大変です。解析するにあたり、いろいろ考えなければいけませんでした。最も頭を悩まされたことは「そもそもコマンドによってsynopsisの書き方のクセが異なる」ということでした。
またスクレイプした時のように個別ルールが必要になるのでは…
まさにそうでした。1つの共通ルールでの解析は(私の能力では)無理そうでした。

だんだんと当初の考えとずれてきたので、1度原点回帰することに。

そもそも前提が間違っていた

当時(今もですが)、Powershellの補完機能に魅了されてました。従来のshellは「ヘルプを見て、すべてタイピングする」というのが基本ですが、Powershellは「途中までタイプすれば保管してくれる」ので初めてでも割と感覚だけで使えました。また特性としてコマンドが「動詞-名詞」の形式かつ、オプションも正式な英語(従来のshellのように略語ではない)なので、コマンド名、オプション名から何がしたいかを予測可能なのです。
例えば、PowershellGet-ChildItem - Fileとcmd.exeのdir /a-dは同じ挙動をします。Powershell、cmd.exeを知らない人(例えば開発者ではない事務の人とか)が上記を見た場合、前者は「あぁ、なんか子アイテムのファイル取ろうとしてるわ」と容易に予想できますが、後者は予測不可能でしょう。

従来のshellの場合、その特性から「コマンド名、オプション名は短く、タイピングしやすいこと」が重要な要素だったと考えます。現にgitも主要なオプションに短い形式が用意されていました。 一方でPowershellは「わかりやすさ」に重きを置いている気がします。なので、逆に普通にシェルとしてプロンプトから利用するのは少し面倒くささもあります。(エイリアス使えば別ですが)

上記を踏まえて、「もともとタイピングを減らすために設計されているので初見では分かりにくいものを補完したところで、補完されたものの意味を予測できないので結局ヘルプ見るしかない」ことに考えが及ばなかったことが敗因だと思いました。

また、「GitのHelpページはひな形こそあれど、別に厳密なルールで構造化されているわけではない」、「synopsisも別に明確なルールがあるわけではなく、人にわかりやすい記法(≒機械にはわかりにくい)である」ということに気づけなかったのも良くなかったと思います。たしかにgit開発のチュートリアルとか見てもそんな感じですね。。

結局、ここで考えるのをやめて、アプリ作りも終わりました。 

結論

今回のことで、
■ 公式ドキュメントを読め。
■ 根拠のない決めつけで物事を進めるな

ということを痛感させられました。ただ、経験としては良かったです。

ここまで読んでいただきありがとうございました。

・免責事項

当方は、当記事にコンテンツを掲載するにあたって、その内容、機能等について細心の注意を払っておりますが、コンテンツの内容が正確であるかどうか、最新のものであるかどうか、安全なものであるか等について保証をするものではなく、何らの責任を負うものではありません。また、当方は通知することなく当記事に掲載した情報の訂正、修正、追加、中断、削除等をいつでも行うことができるものとします。また、当記事、またはコンテンツのご利用により、万一、ご利用者様に何らかの不都合や損害が発生したとしても、当方は何らの責任を負うものではありません。