KDOC 13: make2helpを読む

makefileはMakeの設定ファイルである。make2helpはそのMakefileのヘルプを表示するGoパッケージである。Makefileのコメントから自動生成してくれる。ミニマルな機能で読みやすかった。

流れ

  • コマンドライン処理
  • ファイルをパース
  • 固定のキーワードは無視
  • タスクとコメントを抽出
  • いい感じに表示

ファイル分け

rules

表示を扱うmap構造とメソッド集。

make2help

ファイルのスキャンしてrulesを生成する。

cli

コマンドライン引数を処理する。

cmd/main

cli構造体のメソッドを実行する。

一般的に使えそうなmemo

cliが呼び出す部分

r := rules{} for _, f := range argv { tmpRule, err := scan(f) if err != nil { fmt.Fprintln(cli.ErrStream, err) return exitCodeErr } r = r.merge(tmpRule) } fmt.Fprint(cli.OutStream, r.string(all, colorful)) return exitCodeOK

  • CLIがiotaでOKや各種Errorを返す。すべて正常実行の扱いで、panicを使わない
  • ruleを作成して、それぞれバッファに書き込む

引数をparseする

func parseFlags(argv []string) (restArgv []string, isHelp, isAll bool) { for _, v := range argv { if helpReg.MatchString(v) { isHelp = true return } if allReg.MatchString(v) { isAll = true continue } restArgv = append(restArgv, v) } return }

直に受け取ったargvをパースする。

正規表現 MustCompile を使う

動的ではなく、コンパイル前に実行する。

var ( helpReg = regexp.MustCompile(`^–?h(?:elp)?\(`) allReg = regexp.MustCompile(`^--?all\)`) )

定数で扱う

文字列が、キーワードに含まれるどうかを判定する。

const ( builtInTargetPhony = “.PHONY” builtInTargetSuffixes = “.SUFFIXES”

それをmapにする。

var ( ruleReg = regexp.MustCompile(`^([^\s]+)\s*:`) isBuiltInTargets = map[string]bool{ builtInTargetPhony: true, builtInTargetSuffixes: true,

使用例。targetにキーワードが含まれていれば、trueを返す。

if isBuiltInTargets[target] {

cmd/main.goでは構造体の初期化と1メソッドを呼び出すだけ

1行だけでシンプル。

os.Exit((&make2help.CLI{ErrStream: os.Stderr, OutStream: os.Stdout}).Run(os.Args[1:]))

同じことを検証する

if !reflect.DeepEqual(r, expect) { t.Errorf(“somthing went wrong\n got: %#v\nexpect: %#v”, r, expect) }

rulesのメソッド

type rules map[string][]string

rulesに定義されているメソッドはmerge, string, indentAndRules。シンプルな定義と、一般的な操作として定義されている。