スペースでインデントされたソース ファイルで使用されるタブ幅を特定したいと考えています。これは、先頭のスペースがインデントにのみ使用され、常にタブ幅の倍数であり、インデントが一度に 1 レベルずつ増加する、特に規則的なインデントを持つファイルでは難しくありません。しかし、多くのファイルは、通常、何らかの形式の垂直方向の配置のために、この種の通常のインデントとは多少異なります。したがって、不規則なインデントの可能性を考慮して、使用されたタブ幅を推定するための優れたヒューリスティックを探しています。
これの動機は、SubEthaEdit エディターの拡張機能を作成することです。残念ながら、SubEthaEdit ではタブ幅をスクリプトで使用できないため、テキストに基づいて推測します。
適切なヒューリスティックは次のようにする必要があります。
- インタラクティブな使用に十分なパフォーマンス。これが問題になるとは思いません。必要に応じて、テキストの一部だけを使用できます。
- 言語に依存しない。
- 適切な最長のタブ幅を返します。たとえば、タブ幅が 4 スペースのファイルは、すべてのインデントが実際には 2 倍のレベルである場合、2 スペース タブのファイルである可能性もあります。明らかに、4 つのスペースが正しい選択です。
- インデントが完全に規則的である場合は、常に正しくします。
いくつかの単純化要因:
- 少なくとも 1 行はインデントされていると見なすことができます。
- タブの幅は、少なくとも 2 つのスペースであると見なすことができます。
- インデントはスペースのみで行われると想定しても安全です。タブに反対しているわけではありません---逆に、インデントに使用されているタブがあるかどうかを最初に確認し、個別に処理します。これは、タブとスペースが混在するインデントが適切に処理されない可能性があることを意味しますが、重要ではないと考えています。
- 空白のみを含む行はないと考えられます。
- すべての言語を正しく処理する必要があるわけではありません。たとえば、lisp や go などの言語では、通常は手作業でインデントを行うことはないため、成功または失敗はまったく関係ありません。
- 完璧は必要ありません。数行を手動で調整する必要がある場合でも、世界が終わることはありません。
どのようなアプローチを採用し、その長所と短所は何だと思いますか?
回答で動作するコードを提供したい場合、最善の方法はおそらく、ソース ファイルを から読み取り、stdin
タブ幅を に書き込むシェル スクリプトを使用することstdout
です。擬似コードまたは言葉による明確な説明でも問題ありません。
いくつかの結果
さまざまな戦略をテストするために、言語ディストリビューションの標準ライブラリ内のファイルにさまざまな戦略を適用できます。おそらく、言語の標準的なインデントに従っているからです。Python 2.7 ライブラリと Ruby 1.8 ライブラリ (システム フレームワークは Mac OS X 10.7 にインストールされます) を検討します。これらのライブラリのタブ幅は、それぞれ 4 と 2 であると予想されます。タブ文字で始まる行があるファイル、または少なくとも 2 つのスペースで始まる行がないファイルは除外されます。
パイソン:
Right None Wrong
Mode: 2523 1 102
First: 2169 1 456
No-long (12): 2529 9 88
No-long (8): 2535 16 75
LR (changes): 2509 1 116
LR (indent): 1533 1 1092
Doublecheck (10): 2480 15 130
Doublecheck (20): 2509 15 101
ルビー:
Right None Wrong
Mode: 594 29 51
First: 578 0 54
No-long (12): 595 29 50
No-long (8): 597 29 48
LR (changes): 585 0 47
LR (indent): 496 0 136
Doublecheck (10): 610 0 22
Doublecheck (20): 609 0 23
これらの表で、「正しい」は言語標準のタブ幅の決定、「正しくない」は言語標準の幅と等しくないゼロ以外のタブ幅、「なし」はタブ幅がゼロまたはないものとして解釈する必要があります。答え。「モード」は、インデントで最も頻繁に発生する変更を選択する戦略です。「最初」は、最初のインデントされた行のインデントを取ります。"No-long" は、大きなインデントのある行を除外してモードを取る FastAl の戦略であり、数字はインデントの最大許容変更を示します。「LR」は、線形回帰に基づく Patrick87 の戦略であり、行間のインデントの変化と行の絶対インデントに基づくバリアントがあります。"Doublecheck" (だじゃれに抵抗できなかった!) は、FastAl の Mark の修正です。