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

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

このコミットは、Go言語のドキュメンテーションツールであるgodocに、ディレクトリリストを「フラット」(非インデント)形式で表示する新機能を追加するものです。これにより、特に大規模なディレクトリツリーを閲覧する際の視認性と操作性が向上します。

コミット

commit 9859af879bb303acfb37300e314d3057e98a5eaf
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Nov 17 14:47:49 2011 -0800

    godoc: provide mode for flat (non-indented) directory listings

    This feature should make it easier to look at very large
    directory trees.

    - a new mode (URL: /pkg/?m=flat) shows directory listings w/o
      indentation and entries with full path (html and text mode)
    - in text mode, hierarchical (non-flat) directory listings are
      now presented with indentation (/pkg/?m=text)
    - in html mode, hierarchical (non-flat) directory listings are
      presented with slightly less indentation
    - there is an internal hook for programmatic control of the
      display mode (for specialized versions of godoc).

    R=bradfitz
    CC=golang-dev, rsc
    https://golang.org/cl/5410043

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

https://github.com/golang/go/commit/9859af879bb303acfb37300e314d3057e98a5eaf

元コミット内容

godoc: フラット(非インデント)なディレクトリリスト表示モードを提供

この機能は、非常に大きなディレクトリツリーを閲覧するのを容易にするはずです。

  • 新しいモード(URL: /pkg/?m=flat)は、インデントなしで、かつエントリをフルパスで表示するディレクトリリストを提供します(HTMLおよびテキストモード)。
  • テキストモードでは、階層的な(フラットではない)ディレクトリリストがインデント付きで表示されるようになりました(/pkg/?m=text)。
  • HTMLモードでは、階層的な(フラットではない)ディレクトリリストが、以前よりもわずかに少ないインデントで表示されます。
  • 表示モードをプログラムで制御するための内部フックが追加されました(godocの特殊なバージョン向け)。

変更の背景

godocはGo言語のパッケージドキュメンテーションを生成・表示するためのツールであり、Webサーバーとしても機能します。既存のディレクトリリスト表示は、サブディレクトリがインデントされて階層的に表示される形式でした。しかし、非常に多くのサブディレクトリや深い階層を持つ大規模なプロジェクトの場合、このインデント表示はかえって視認性を損ね、目的のファイルやディレクトリを見つけにくくするという問題がありました。

このコミットは、この問題を解決するために、インデントをなくし、各エントリをフルパスで表示する「フラット」な表示モードを導入しました。これにより、ユーザーは大規模なディレクトリツリーでも、より効率的に情報をスキャンし、目的の項目にアクセスできるようになります。また、既存の階層表示モードについても、テキストモードでのインデント追加やHTMLモードでのインデント調整が行われ、全体的な表示の一貫性と利便性が向上しています。

前提知識の解説

godocとは

godocは、Go言語のソースコードからドキュメンテーションを抽出し、整形して表示するためのツールです。Go言語のコードは、コメントの書き方によって自動的にドキュメンテーションが生成されるように設計されており、godocはそのコメントを解析してHTMLページやプレーンテキスト形式で表示します。

godocは主に以下の2つの方法で利用されます。

  1. コマンドラインツールとして: ターミナルからgodoc <package_path>のように実行することで、指定されたパッケージのドキュメンテーションをプレーンテキストで表示します。
  2. Webサーバーとして: godoc -http=:6060のように実行することで、ローカルマシン上でドキュメンテーションサーバーを起動し、Webブラウザを通じてドキュメンテーションを閲覧できます。Go言語の公式ドキュメンテーションサイトであるpkg.go.dev(旧golang.org/pkg)も、このgodocをベースに構築されています。

ディレクトリリストの表示

godocがWebサーバーとして動作している場合、/pkg/パスにアクセスすると、Goの標準ライブラリやGOPATH/GOROOT内のパッケージのディレクトリ構造が表示されます。これまでの表示は、サブディレクトリが視覚的にインデントされて表示される階層的なものでした。

フラット表示とインデント表示

  • インデント表示(階層表示): ディレクトリ構造を視覚的に表現するために、サブディレクトリが親ディレクトリに対して右にずれて表示される形式です。ツリー構造を直感的に理解しやすい反面、階層が深くなると横幅を取りすぎたり、項目数が多くなると全体を把握しにくくなることがあります。
  • フラット表示: 全てのディレクトリやファイルがインデントなしで、同じレベルでリストされる形式です。各項目はフルパスで表示されるため、どのディレクトリに属しているかが明確になります。大規模なリストでも縦に長く表示されるだけで、横方向のスクロールが不要になり、一覧性が向上します。

技術的詳細

このコミットは、godocのWebサーバー機能におけるディレクトリリストの表示方法を拡張するために、主に以下の技術的変更を加えています。

  1. 新しい表示モードの導入:

    • URLクエリパラメータm=flatが導入されました。ユーザーがhttp://localhost:6060/pkg/?m=flatのようにアクセスすると、フラット表示モードが有効になります。
    • このモードは、src/cmd/godoc/godoc.go内のPageInfoModeというビットフラグ列挙型にflatDirという新しいフラグを追加することで実装されています。
    • getPageInfoMode関数がURLのmパラメータを解析し、対応するPageInfoModeフラグを設定します。
  2. テンプレートの条件分岐:

    • lib/godoc/package.htmllib/godoc/package.txtというGoテンプレートファイルが変更されました。これらのテンプレートは、godocがWebページやテキスト形式の出力を生成する際に使用されます。
    • テンプレート内で、新しく追加された$.DirFlatというコンテキスト変数(PageInfo構造体のDirFlatフィールドに対応)の真偽をチェックする条件分岐が導入されました。
    • $.DirFlattrueの場合(フラットモードの場合)は、インデントを生成するrepeat関数がスキップされ、代わりにフルパスが表示されるように変更されています。
    • $.DirFlatfalseの場合(従来の階層モードの場合)は、HTMLモードではインデント幅が25から20ピクセルにわずかに減らされ、テキストモードではインデントが明示的に追加されるようになりました。
  3. 内部フックの追加:

    • src/cmd/godoc/godoc.goadjustPageInfoModeという変数(関数ポインタ)が追加されました。これは、getPageInfoModeが計算したPageInfoModeを、godocの特殊なバージョンがプログラム的に調整できるようにするためのフックです。これにより、godocを組み込む他のアプリケーションが、独自のロジックで表示モードを制御できるようになります。
  4. ドキュメンテーションの更新:

    • src/cmd/godoc/doc.go内のgodocコマンドのヘルプドキュメントに、flatモードに関する説明が追加されました。これにより、ユーザーはこの新機能の存在と使い方を公式ドキュメントで確認できるようになります。

これらの変更により、godocはユーザーのニーズに応じて、ディレクトリリストの表示形式を柔軟に切り替えられるようになりました。

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

このコミットで変更された主要なファイルは以下の通りです。

  • lib/godoc/package.html: HTML形式のパッケージディレクトリリスト表示テンプレート。
  • lib/godoc/package.txt: テキスト形式のパッケージディレクトリリスト表示テンプレート。
  • src/cmd/godoc/doc.go: godocコマンドのドキュメンテーション。
  • src/cmd/godoc/godoc.go: godocコマンドの主要なロジック、特にWebサーバー関連の処理。

コアとなるコードの解説

lib/godoc/package.html

このファイルは、godocがWebブラウザに表示するディレクトリリストのHTML構造を定義しています。

@@ -141,17 +141,25 @@
  	<p>
  	<table class="layout">
  	<tr>
-	<th align="left" colspan="{{html .MaxHeight}}">Name</th>
-	<td width="25">&nbsp;</td>
+	{{if $.DirFlat}}
+		<th align="left">Name</th>
+	{{else}}
+		<th align="left" colspan="{{html .MaxHeight}}">Name</th>
+	{{end}}
+	<th width="25"></th>
  	<th align="left">Synopsis</th>
  	</tr>
  	<tr>
-	<th align="left"><a href="..">..</a></th>
+	<td align="left"><a href="..">..</a></td>
  	</tr>
  	{{range .List}}
  	\t<tr>
-\t\t{{repeat `<td width=\"25\"></td>` .Depth}}\
-\t\t<td align=\"left\" colspan=\"{{html .Height}}\"><a href=\"{{html .Path}}\">{{html .Name}}</a></td>
+\t\t{{if $.DirFlat}}
+\t\t\t<td align=\"left\"><a href=\"{{html .Path}}\">{{html .Path}}</a></td>
+\t\t{{else}}
+\t\t\t{{repeat `<td width=\"20\"></td>` .Depth}}\
+\t\t\t<td align=\"left\" colspan=\"{{html .Height}}\"><a href=\"{{html .Path}}\">{{html .Name}}</a></td>
+\t\t{{end}}\
  	\t<td></td>
  	\t<td align=\"left\">{{html .Synopsis}}</td>
  	\t</tr>
  • {{if $.DirFlat}}ブロックが追加され、DirFlattrueの場合(フラットモード)とfalseの場合で表示を切り替えています。
  • フラットモードでは、<th>タグのcolspan属性が削除され、Name列の幅が固定されます。
  • 各ディレクトリ/ファイルの行(<tr>)内で、フラットモードの場合は{{html .Path}}(フルパス)が表示され、インデントを生成する{{repeat ... .Depth}}がスキップされます。
  • 非フラットモードの場合、インデント用の<td>width25から20に減らされ、インデントがわずかに小さくなっています。

lib/godoc/package.txt

このファイルは、godocがテキスト形式で出力するディレクトリリストのフォーマットを定義しています。

@@ -76,7 +76,8 @@ OTHER PACKAGES

  */}}{{with .Dirs}}\
  SUBDIRECTORIES
--
-{{range .List}}\
-\t{{.Name}}{{end}}\
-{{end}}\
+{{if $.DirFlat}}{{range .List}}\
+\t{{.Path}}{{end}}\
+{{else}}{{range .List}}\
+\t{{repeat `. ` .Depth}}{{.Name}}{{end}}\
+{{end}}{{end}}\
  • ここでも{{if $.DirFlat}}による条件分岐が導入されています。
  • フラットモードでは、{{.Path}}(フルパス)がそのまま表示されます。
  • 非フラットモードでは、{{repeat . .Depth}}によって、. (ドットとスペース)をDepthの回数だけ繰り返すことで、視覚的なインデントが生成されるようになりました。

src/cmd/godoc/doc.go

このファイルは、godocコマンドの組み込みドキュメンテーションを定義しています。

@@ -134,10 +134,11 @@ The presentation mode of web pages served by godoc can be controlled with the
  	all\tshow documentation for all (not just exported) declarations
  	src\tshow the original source code rather then the extracted documentation
  	text\tpresent the page in textual (command-line) form rather than HTML
+\tflat\tpresent flat (not indented) directory listings using full paths

 -For instance, http://golang.org/pkg/big/?m=all,text shows the documentation for
 -all (not just the exported) declarations of package big, in textual form (as
 -it would appear when using godoc from the command line: "godoc -src big .*").
 +For instance, http://golang.org/pkg/math/big/?m=all,text shows the documentation
 +for all (not just the exported) declarations of package big, in textual form (as
 +it would appear when using godoc from the command line: "godoc -src math/big .*").
  • flat\tpresent flat (not indented) directory listings using full pathsという行が追加され、m=flatモードの説明が公式ドキュメントに記載されました。
  • 例のURLもbigからmath/bigに変更されていますが、これはこのコミットの主要な変更とは直接関係ありません。

src/cmd/godoc/godoc.go

このファイルはgodocの主要なロジックを含んでいます。

@@ -825,6 +825,7 @@ const (
  	noFiltering PageInfoMode = 1 << iota // do not filter exports
  	showSource                           // show source code, do not extract documentation
  	noHtml                               // show result in textual form, do not generate HTML
+\tflatDir                              // show directory in a flat (non-indented) manner
  )

  // modeNames defines names for each PageInfoMode flag.
@@ -832,18 +833,26 @@ var modeNames = map[string]PageInfoMode{
  	"all":  noFiltering,
  	"src":  showSource,
  	"text": noHtml,
+\t"flat": flatDir,
  }

  // getPageInfoMode computes the PageInfoMode flags by analyzing the request
  // URL form value "m". It is value is a comma-separated list of mode names
  // as defined by modeNames (e.g.: m=src,text).\
 -func getPageInfoMode(r *http.Request) (mode PageInfoMode) {
 +func getPageInfoMode(r *http.Request) PageInfoMode {
 +\tvar mode PageInfoMode
  \tfor _, k := range strings.Split(r.FormValue("m"), ",") {
  \t\tif m, found := modeNames[strings.TrimSpace(k)]; found {
  \t\t\tmode |= m
  \t\t}\
  \t}\
 -\treturn
+\treturn adjustPageInfoMode(r, mode)
+}\
+\
+// Specialized versions of godoc may adjust the PageInfoMode by overriding
+// this variable.
+var adjustPageInfoMode = func(_ *http.Request, mode PageInfoMode) PageInfoMode {
+\treturn mode
  }

  // remoteSearchURL returns the search URL for a given query as needed by
@@ -868,8 +877,9 @@ type PageInfo struct {
  	Examples []*doc.Example  // nil if no example code
  	Dirs     *DirList        // nil if no directory information
  	DirTime  int64           // directory time stamp in seconds since epoch
+\tDirFlat  bool            // if set, show directory in a flat (non-indented) manner
  	IsPkg    bool            // false if this is not documenting a real package
-\tErr      error           // directory read error or nil
+\tErr      error           // I/O error or nil
  }

  func (info *PageInfo) IsEmpty() bool {
@@ -1105,7 +1115,19 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
  \t\ttimestamp = time.Seconds()
  \t}\

-\treturn PageInfo{abspath, plist, fset, past, pdoc, examples, dir.listing(true), timestamp, h.isPkg, nil}\
+\treturn PageInfo{\
+\t\tDirname:  abspath,\
+\t\tPList:    plist,\
+\t\tFSet:     fset,\
+\t\tPAst:     past,\
+\t\tPDoc:     pdoc,\
+\t\tExamples: examples,\
+\t\tDirs:     dir.listing(true),\
+\t\tDirTime:  timestamp,\
+\t\tDirFlat:  mode&flatDir != 0,\
+\t\tIsPkg:    h.isPkg,\
+\t\tErr:      nil,\
+\t}\
  }

  func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  • PageInfoMode定数にflatDirが追加され、modeNamesマップに"flat": flatDirが追加されました。これにより、URLのm=flatflatDirフラグに対応付けられます。
  • getPageInfoMode関数が変更され、adjustPageInfoModeという新しい関数ポインタを呼び出すようになりました。これは、godocのカスタムバージョンがモードを調整するための拡張ポイントです。
  • PageInfo構造体にDirFlat boolフィールドが追加されました。このフィールドは、現在のページがフラットモードで表示されるべきかどうかを示すブール値です。
  • getPageInfo関数内で、PageInfo構造体の初期化時にDirFlatフィールドがmode&flatDir != 0flatDirフラグがセットされているか)に基づいて設定されるようになりました。
  • PageInfo構造体のErrフィールドのコメントがより汎用的な「I/O error or nil」に変更されています。

これらの変更により、godocはURLパラメータを通じて表示モードを切り替え、そのモードに応じてHTMLおよびテキストテンプレートのレンダリングを動的に調整できるようになりました。

関連リンク

参考にした情報源リンク