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。シンプルな定義と、一般的な操作として定義されている。