Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 11422] ファイルの概要

このコミットは、Goコマンドラインツールのdoc.goファイルを、go helpコマンドの出力から自動生成されるテキストで更新することを目的としています。これにより、Goコマンドのヘルプドキュメントが常に最新かつ正確に保たれるようになります。

コミット

commit 29dbd988b83e3cb43ca034916e52d030f150c7e1
Author: Andrew Gerrand <adg@golang.org>
Date:   Fri Jan 27 08:19:43 2012 +1100

    cmd/go: update doc.go with text generated from the usage strings
    
    Fixes #2783.
    
    R=bsiegert, rsc
    CC=golang-dev
    https://golang.org/cl/5570069

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/29dbd988b83e3cb43ca034916e52d030f150c7e1

元コミット内容

cmd/go: update doc.go with text generated from the usage strings

このコミットは、goコマンドのdoc.goファイルを、各コマンドの利用方法(usage strings)から生成されたテキストで更新します。これにより、手動での更新作業を減らし、ドキュメントの正確性を向上させます。

Fixes #2783.

このコミットは、GoプロジェクトのIssue #2783を修正します。

変更の背景

Go言語のコマンドラインツール(goコマンド)は、go build, go run, go testなど、多くのサブコマンドを提供しています。これらのサブコマンドにはそれぞれ詳細なヘルプドキュメントが存在し、go help <command>で参照できます。

このコミット以前は、src/cmd/go/doc.goファイルにGoコマンド全体の概要と各サブコマンドの簡単な説明が手動で記述されていました。しかし、各サブコマンドのヘルプテキストはsrc/cmd/go/main.go内のCommand構造体に定義されたUsageLineLongフィールドから生成されていました。

この状況では、サブコマンドの機能やオプションが変更された際に、main.go内の定義とdoc.go内の説明の両方を手動で更新する必要があり、ドキュメントの不整合や陳腐化のリスクがありました。特に、go helpコマンドの出力とdoc.goの内容が一致しないという問題(Issue #2783)が発生していました。

このコミットの背景にあるのは、ドキュメントの自動生成と一貫性の確保です。go helpコマンドが生成する詳細なヘルプテキストを直接doc.goに書き込むことで、ドキュメントのメンテナンスコストを削減し、常に最新の正確な情報を提供できるようにすることが目的です。

前提知識の解説

  • Goコマンド (cmd/go): Go言語のビルド、テスト、パッケージ管理などを行うための主要なコマンドラインツールです。go build, go run, go test, go getなどのサブコマンドを持ちます。
  • doc.goファイル: Goパッケージのドキュメントを記述するための慣習的なファイルです。パッケージレベルのコメントや、パッケージ内の主要な型、関数、変数などの概要を記述します。godocツールによって解析され、ドキュメントとして表示されます。このコミットでは、cmd/goパッケージのdoc.goが対象です。
  • go helpコマンド: goコマンドのヘルプ情報を表示するためのコマンドです。go helpでコマンド一覧と概要を、go help <command>で特定のサブコマンドの詳細なヘルプを表示します。
  • text/templateパッケージ: Go言語の標準ライブラリで提供されるテキストテンプレートエンジンです。プレースホルダーを含むテキストを定義し、データ構造を渡すことで動的にテキストを生成できます。goコマンドのヘルプ出力もこのテンプレートエンジンを使用して生成されています。
  • gofmt: Go言語のコードフォーマッタです。Goの標準的なコーディングスタイルに沿ってコードを自動的に整形します。このコミットでは、生成されたdoc.goファイルを整形するために使用されます。
  • mkdoc.sh: シェルスクリプトで、このコミットで新しく追加されます。go help documentationコマンドを実行し、その出力をdoc.goにリダイレクトし、さらにgofmtで整形する役割を担います。
  • Issue #2783: GoプロジェクトのIssueトラッカーで報告された問題です。具体的には、「go helpの出力とdoc.goの内容が一致しない」というドキュメントの不整合に関する問題でした。

技術的詳細

このコミットの主要な技術的変更点は、go help documentationという新しい内部コマンドを導入し、そのコマンドがgoコマンド全体のヘルプドキュメントを生成するようにしたことです。

  1. documentationTemplateの導入: src/cmd/go/main.godocumentationTemplateという新しいtext/templateが追加されました。このテンプレートは、goコマンドの各サブコマンドのShort(短い説明)とLong(詳細な説明)フィールドを整形し、doc.goファイルの形式に合うように出力します。特に、Shortフィールドの最初の文字を大文字にするcapitalize関数がテンプレート関数として追加されています。

  2. go help documentationコマンドの追加: src/cmd/go/main.gohelp関数内に、引数が"documentation"の場合の特別な処理が追加されました。この処理では、まずprintUsage関数を呼び出してgoコマンド全体の概要(コマンド一覧など)をバッファに書き込みます。次に、この概要と既存のcommandsスライス(各サブコマンドの定義)をdocumentationTemplateに渡し、その結果を標準出力に出力します。

  3. mkdoc.shスクリプトの追加: src/cmd/go/mkdoc.shという新しいシェルスクリプトが追加されました。このスクリプトは以下の2つのコマンドを実行します。

    • go help documentation > doc.go: go help documentationコマンドの出力をsrc/cmd/go/doc.goファイルにリダイレクトします。これにより、doc.goの内容が自動生成されます。
    • gofmt -w doc.go: 生成されたdoc.goファイルをgofmtで整形し、Goの標準的なコーディングスタイルに準拠させます。

これらの変更により、doc.goファイルは手動で編集されるのではなく、mkdoc.shスクリプトを実行することで、main.go内のCommand構造体の定義に基づいて自動的に生成されるようになりました。これにより、go helpコマンドの出力とdoc.goの内容の同期が保証され、ドキュメントのメンテナンス性が大幅に向上しました。

また、src/cmd/go/doc.goの既存の内容は、この自動生成された内容に置き換えられています。変更前は手動で記述されていた各コマンドの簡単な説明が、main.goで定義されている詳細なヘルプテキストから抽出されてdoc.goに反映される形になります。

コアとなるコードの変更箇所

src/cmd/go/doc.go

このファイルは、手動で記述されていたGoコマンドの概要と各サブコマンドの説明が、自動生成される内容に完全に置き換えられています。変更前は簡潔な説明だったものが、go helpコマンドが提供する詳細な説明文に置き換わっています。

--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -9,13 +9,14 @@ Usage: go command [arguments]
 
 The commands are:
 
-    build       compile and install packages and dependencies
-    clean       remove intermediate objects
+    build       compile packages and dependencies
+    doc         run godoc on package sources
     fix         run gofix on packages
-    fmt         run gofmt -w on packages
+    fmt         run gofmt on package sources
     get         download and install packages and dependencies
-    install     install packages and dependencies
+    install     compile and install packages and dependencies
     list        list packages
+    run         compile and run Go program
     test        test packages
     version     print Go version
     vet         run govet on packages
@@ -27,8 +28,573 @@ Additional help topics:
     gopath      GOPATH environment variable
     importpath  description of import paths
     remote      remote import path syntax
+    testflag    description of testing flags
+    testfunc    description of testing functions
 
 Use "go help [topic]" for more information about that topic.
+\n+\n+Compile packages and dependencies
+... (以下、各コマンドの詳細なヘルプテキストが続く)

src/cmd/go/main.go

このファイルには、documentationTemplateの定義、capitalizeヘルパー関数、そしてgo help documentationコマンドの処理ロジックが追加されています。

--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -5,6 +5,7 @@
 package main
 
 import (
+\t"bytes"
 \t"flag"
 \t"fmt"
 \t"go/build"
@@ -17,6 +18,8 @@ import (
 \t"regexp"
 \t"strings"
 \t"text/template"
+\t"unicode"
+\t"unicode/utf8"
 )
 
 // A Command is an implementation of a go command
@@ -141,16 +144,44 @@ var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}\n
 {{end}}{{.Long | trim}}\n
 `
 
+var documentationTemplate = `// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+\n/*
+{{range .}}{{if .Short}}{{.Short | capitalize}}
+\n{{end}}{{if .Run}}Usage:
+\n\tgo {{.UsageLine}}
+\n{{end}}{{.Long | trim}}
+\n\n
+{{end}}*/
+package documentation
+\n// NOTE: cmdDoc is in fmt.go.
+`
+\n // tmpl executes the given template text on data, writing the result to w.\n func tmpl(w io.Writer, text string, data interface{}) {\n \tt := template.New("top")\n-\tt.Funcs(template.FuncMap{"trim": strings.TrimSpace})\n+\tt.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})\n \ttemplate.Must(t.Parse(text))\n \tif err := t.Execute(w, data); err != nil {\n \t\tpanic(err)\n \t}\n }\n \n+func capitalize(s string) string {\n+\tif s == "" {\n+\t\treturn s\n+\t}\n+\tr, n := utf8.DecodeRuneInString(s)\n+\treturn string(unicode.ToTitle(r)) + s[n:]\n+}\n+\n func printUsage(w io.Writer) {\n \ttmpl(w, usageTemplate, commands)\n }\n@@ -173,6 +204,16 @@ func help(args []string) {\n \t}\n \n \targ := args[0]\n+\n+\t// 'go help documentation' generates doc.go.\n+\tif arg == "documentation" {\n+\t\tbuf := new(bytes.Buffer)\n+\t\tprintUsage(buf)\n+\t\tusage := &Command{Long: buf.String()}\n+\t\ttmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))\n+\t\treturn\n+\t}\n+\n \tfor _, cmd := range commands {\n \t\tif cmd.Name() == arg {\n \t\t\ttmpl(os.Stdout, helpTemplate, cmd)\n```

### `src/cmd/go/mkdoc.sh`

この新しいシェルスクリプトは、`doc.go`を自動生成するためのビルドステップを定義しています。

```diff
--- /dev/null
+++ b/src/cmd/go/mkdoc.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# Copyright 2012 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.\n
+go help documentation > doc.go
+gofmt -w doc.go
+\n

コアとなるコードの解説

  • documentationTemplate: このtext/templateは、doc.goファイルの内容を生成するための「設計図」です。Goのソースコードコメントブロック(/* ... */)内に、各Goコマンドの短い説明(Short)と長い説明(Long)を整形して埋め込みます。{{range .}}で渡されたコマンドのリストをイテレートし、それぞれのコマンドに対してShortLongフィールドを処理します。 {{.Short | capitalize}}の部分では、Shortフィールドの最初の文字を大文字に変換するcapitalize関数が適用されます。これは、doc.goのコメントとして自然な見た目にするためです。

  • capitalize関数: text/template内で使用されるカスタム関数です。引数として受け取った文字列の最初のUnicodeルーン(文字)を大文字に変換し、残りの文字列と結合して返します。これにより、Shortフィールドが常に大文字で始まるようになります。

  • help関数内の"documentation"引数処理: main.gohelp関数は、go help <topic><topic>部分を処理します。このコミットでは、<topic>"documentation"の場合に特別なロジックが実行されます。

    1. buf := new(bytes.Buffer): 出力先となる一時的なバッファを作成します。
    2. printUsage(buf): goコマンド全体の基本的な使用方法(コマンド一覧など)をこのバッファに書き込みます。
    3. usage := &Command{Long: buf.String()}: printUsageで生成されたテキストを、あたかも一つの長いドキュメントであるかのようにCommand構造体のLongフィールドに格納します。これは、documentationTemplateが期待するデータ形式に合わせるためです。
    4. tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...)): documentationTemplateを使用して、usage(全体の概要)とcommands(各サブコマンドの詳細)を結合したデータから最終的なドキュメントを生成し、標準出力(os.Stdout)に出力します。この出力がmkdoc.shによってdoc.goにリダイレクトされます。
  • mkdoc.sh: このシェルスクリプトは、go help documentationコマンドを実行し、その出力をdoc.goファイルに書き込みます。その後、gofmt -w doc.goを実行して、生成されたdoc.goファイルがGoの標準的なフォーマットに準拠するように自動整形します。これは、ビルドプロセスの一部として実行されることを想定しており、開発者が手動でdoc.goを更新する手間を省きます。

これらの変更により、Goコマンドのヘルプドキュメントは、コード内の定義から自動的に生成されるようになり、ドキュメントの正確性とメンテナンス性が大幅に向上しました。

関連リンク

参考にした情報源リンク