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

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

このコミットは、Go言語の初期開発段階において、コードの整形(特にタブとスペースの変換)を目的とした新しいコマンドラインユーティリティ untab を導入するものです。同時に、このユーティリティが利用する tabwriter パッケージの内部構造にも変更が加えられ、TabWriter 型とそのコンストラクタ MakeTabWriter が外部から利用可能(エクスポート)になっています。これは、Goのコードベースにおける整形ツールの基盤を構築する一環として行われた変更と考えられます。

コミット

- untab app (snapshot - not quite complete)

R=r
OCL=19558
CL=19558

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

https://github.com/golang/go/commit/127c65b400ef27c3c02242ffd9809f91069218e5

元コミット内容

commit 127c65b400ef27c3c02242ffd9809f91069218e5
Author: Robert Griesemer <gri@golang.org>
Date:   Tue Nov 18 18:44:17 2008 -0800

    - untab app (snapshot - not quite complete)

    R=r
    OCL=19558
    CL=19558
---
 usr/gri/pretty/Makefile     |  6 +++++
 usr/gri/pretty/tabwriter.go | 17 +++++++--------
 usr/gri/pretty/untab.go     | 53 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 9 deletions(-)

変更の背景

このコミットの主な背景は、Go言語のソースコードの整形と標準化の必要性です。特に、タブとスペースの扱いに関する一貫性を確保するため、untab という新しいユーティリティが開発されました。コミットメッセージにある「snapshot - not quite complete」という記述から、これは開発途中のスナップショットであり、将来的にさらに機能が追加される可能性が示唆されています。

Go言語では、gofmt のような自動整形ツールが非常に重視されており、コードの可読性と一貫性を高める文化があります。この untab アプリケーションは、その初期段階における整形ツールの一つとして位置づけられます。tabwriter パッケージの変更は、この新しい untab ツールが tabwriter の機能を利用できるようにするための前提条件であったと考えられます。

また、OCL (Open Change List) と CL (Change List) は、Google内部で使用されていたPerforceバージョン管理システムにおける変更セットの識別子であり、このコミットがGoogle内部のGo開発プロセスの一部として行われたことを示しています。

前提知識の解説

このコミットを理解するためには、以下の概念が役立ちます。

  • Go言語のパッケージとエクスポート: Go言語では、パッケージ内の識別子(変数、関数、型など)が外部からアクセス可能かどうかは、その識別子の最初の文字が大文字であるかどうかで決まります。大文字で始まる識別子は「エクスポート」され、他のパッケージから利用できます。小文字で始まる識別子はパッケージ内部でのみ利用可能です。このコミットでは、tabwriter.go 内の TabWriter 型と MakeTabWriter 関数が export キーワード(当時のGoの構文)によってエクスポートされています。
  • Makefile: Makefile は、ソフトウェアのビルドプロセスを自動化するためのファイルです。make コマンドによって解釈され、ソースコードのコンパイル、リンク、テストなどのタスクを実行します。このコミットでは、新しい untab アプリケーションをビルドするためのルールが Makefile に追加されています。
  • tabwriter パッケージ: Go言語の標準ライブラリには、テキストを整形してタブ位置を揃えるための text/tabwriter パッケージが存在します。このコミットで変更されている usr/gri/pretty/tabwriter.go は、その初期バージョンまたはプロトタイプであると考えられます。tabwriter は、複数の行にわたるテキストの列を自動的に揃える「elastic tabstops」の概念に基づいています。
  • コマンドライン引数とフラグ: untab.go はコマンドラインユーティリティであり、Flag パッケージ(現在の flag パッケージに相当)を使用してコマンドライン引数を解析しています。--tabwidth フラグは、タブの幅を指定するために使用されます。
  • IO.CopynOS.Stdin/OS.Stdout: IO.Copyn は、入力ソースから出力先へバイトをコピーする関数です。OS.Stdin は標準入力、OS.Stdout は標準出力を表し、コマンドラインユーティリティで一般的な入出力ストリームです。

技術的詳細

このコミットは主に3つのファイルに影響を与えています。

  1. usr/gri/pretty/Makefile の変更:

    • all: untab pretty という行が追加され、untab がデフォルトのビルドターゲットに含まれるようになりました。
    • untab: untab.6$(L) -o untab untab.6 というルールが追加され、untab.go から生成されるオブジェクトファイル untab.6 をリンクして実行可能ファイル untab を作成するようになりました。
    • untab.6: tabwriter.6 という依存関係が追加され、untab.gotabwriter.go に依存していることが明示されました。
  2. usr/gri/pretty/tabwriter.go の変更:

    • type TabWriter struct {export type TabWriter struct { に変更されました。これにより、TabWriter 型がパッケージ外部からアクセス可能になりました。当時のGoの構文では export キーワードが使用されていましたが、後に識別子の大文字/小文字でエクスポートが制御されるようになりました。
    • export func MakeTabWriter(writer IO.Write, tabwidth int) IO.Write {export func MakeTabWriter(writer IO.Write, tabwidth int) *TabWriter { に変更されました。MakeTabWriter 関数の戻り値の型が IO.Write インターフェースから具体的なポインタ型 *TabWriter に変更されました。これにより、MakeTabWriter の呼び出し元は、TabWriter の具体的なメソッドにアクセスできるようになり、より柔軟な操作が可能になります。
    • panic();panic("internal error"); に変更されました。これは、パニック発生時に具体的なエラーメッセージを出力するように改善されたものです。
  3. usr/gri/pretty/untab.go の新規追加:

    • このファイルは、新しいコマンドラインユーティリティ untab のソースコードです。
    • package main であり、実行可能ファイルとしてビルドされることを示します。
    • OS, IO, Flag, Fmt, TabWriter といったパッケージをインポートしています。
    • tabwidth というグローバル変数が Flag.Int を使って定義されており、コマンドライン引数 --tabwidth でタブの幅を設定できるようになっています。デフォルト値は4です。
    • Error 関数は、エラーメッセージを出力してプログラムを終了させるヘルパー関数です。
    • Untab 関数は、指定された入力ファイル (src) の内容を TabWriter (dst) を通して処理するコアロジックを含んでいます。IO.Copyn を使用して入力から出力へデータをコピーしています。
    • main 関数は、プログラムのエントリポイントです。
      • Flag.Parse() でコマンドライン引数を解析します。
      • TabWriter.MakeTabWriter を使用して TabWriter のインスタンスを作成し、標準出力 (OS.Stdout) に書き込むように設定します。
      • コマンドライン引数にファイル名が指定されている場合は、それらのファイルを順に開き、Untab 関数で処理します。
      • ファイル名が指定されていない場合は、標準入力 (OS.Stdin) を処理します。

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

usr/gri/pretty/Makefile

--- a/usr/gri/pretty/Makefile
+++ b/usr/gri/pretty/Makefile
@@ -5,6 +5,11 @@
 G=6g
 L=6l
 
+all: untab pretty
+
+untab: untab.6
+	$(L) -o untab untab.6
+	
 pretty: pretty.6
 	$(L) -o pretty pretty.6
 
@@ -34,6 +39,7 @@ platform.6:	 utils.6
 
 printer.6:	 scanner.6 ast.6 tabwriter.6
 
+untab.6:	tabwriter.6
 
 %.6:	%.go
 	$(G) $(F) $<\ndiff --git a/usr/gri/pretty/tabwriter.go b/usr/gri/pretty/tabwriter.go

usr/gri/pretty/tabwriter.go

--- a/usr/gri/pretty/tabwriter.go
+++ b/usr/gri/pretty/tabwriter.go
@@ -85,7 +85,7 @@ func (b *ByteArray) Append(s *[]byte) {\n // of adjacent cells have the same width (by adding padding). For more\n // details see: http://nickgravgaard.com/elastictabstops/index.html .\n \n-type TabWriter struct {\n+export type TabWriter struct {\n \t// configuration\n \twriter IO.Write;\n \ttabwidth int;\n@@ -232,26 +232,25 @@ func (b *TabWriter) Tab() {\n \n func (b *TabWriter) Newline() {\n \tb.Tab();  // add last cell to current line\n-\t\n+\n \tif b.LastLine().Len() == 1 {\n \t\t// The current line has only one cell which does not have an impact\n \t\t// on the formatting of the following lines (the last cell per line\n \t\t// is ignored by Format), thus we can print the TabWriter contents.\n \t\tif b.widths.Len() != 0 {\n-\t\t\tpanic();\n+\t\t\tpanic(\"internal error\");\n \t\t}\n-\t\t//b.Dump();\n \t\tb.Format(0, 0, b.lines.Len());\n \t\tif b.widths.Len() != 0 {\n-\t\t\tpanic();\n+\t\t\tpanic(\"internal error\");\n \t\t}\n-\t\t\n-\t\t// reset the TabWriter\n+\n+\t\t// reset TabWriter\n \t\tb.width = 0;\n \t\tb.buf.Clear();\n \t\tb.lines.Reset();\n \t}\n-\t\n+\n \tb.AddLine();\n }\n \n@@ -278,7 +277,7 @@ func (b *TabWriter) Write(buf *[]byte) (i int, err *OS.Error) {\n }\n \n \n-export func MakeTabWriter(writer IO.Write, tabwidth int) IO.Write {\n+export func MakeTabWriter(writer IO.Write, tabwidth int) *TabWriter {\n \tb := new(TabWriter);\n \tb.Init(writer, tabwidth);\n \treturn b;\ndiff --git a/usr/gri/pretty/untab.go b/usr/gri/pretty/untab.go

usr/gri/pretty/untab.go (新規追加)

// Copyright 2009 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.

package main

import (
	OS "os";
	IO "io";
	Flag "flag";
	Fmt "fmt";
	TabWriter "tabwriter";
)


var (
	tabwidth = Flag.Int("tabwidth", 4, nil, "tab width");
)


func Error(fmt string, params ...) {
	Fmt.printf(fmt, params);
	sys.exit(1);
}


func Untab(name string, src *OS.FD, dst *TabWriter.TabWriter) {
	n, err := IO.Copyn(src, dst, 2e9 /* inf */);  // TODO use Copy
	if err != nil {
		Error("error while processing %s (%v)", name, err);
	}
	//dst.Flush();
}


func main() {
	Flag.Parse();
	dst := TabWriter.MakeTabWriter(OS.Stdout, int(tabwidth.IVal()));
	if Flag.NArg() > 0 {
		for i := 0; i < Flag.NArg(); i++ {
			name := Flag.Arg(i);
			src, err := OS.Open(name, OS.O_RDONLY, 0);
			if err != nil {
				Error("could not open %s (%v)\n", name, err);
			}
			Untab(name, src, dst);
			src.Close();  // ignore errors
		}
	} else {
		// no files => use stdin
		Untab("/dev/stdin", OS.Stdin, dst);
	}
}

コアとなるコードの解説

Makefile の変更

Makefile の変更は、新しい untab 実行可能ファイルをビルドするための手順を定義しています。all ターゲットに untab が追加されたことで、make コマンドを実行すると untab もビルドされるようになります。untab: untab.6untab.6: tabwriter.6 の行は、untabuntab.go からコンパイルされたオブジェクトファイル untab.6 に依存し、さらに untab.6tabwriter.go からコンパイルされた tabwriter.6 に依存することを示しています。これは、untab アプリケーションが tabwriter パッケージの機能を利用しているため、ビルド時にその依存関係を解決する必要があることを意味します。

tabwriter.go の変更

tabwriter.go の変更は、untab アプリケーションが TabWriter の機能を利用できるようにするための重要なAPI変更です。

  • type TabWriter struct { から export type TabWriter struct { への変更は、TabWriter 型がこのパッケージの外部からアクセス可能になったことを示します。これにより、untab.go のような別のパッケージから TabWriter をインスタンス化して利用できるようになります。
  • export func MakeTabWriter(...) IO.Write { から export func MakeTabWriter(...) *TabWriter { への変更は、MakeTabWriter 関数が IO.Write インターフェースではなく、具体的な *TabWriter 型のポインタを返すようになったことを意味します。これにより、untab.goTabWriter の具体的なメソッド(例えば、コメントアウトされている dst.Flush() のようなもの)を呼び出すことが可能になります。インターフェースを返すよりも、具体的な型を返すことで、より多くの機能にアクセスできるようになります。
  • panic(); から panic("internal error"); への変更は、デバッグの際に役立つ具体的なエラーメッセージを提供するように改善されたものです。

untab.go の新規追加

untab.go は、Go言語で書かれた新しいコマンドラインユーティリティです。

  • package main は、このファイルが独立した実行可能プログラムであることを示します。
  • import セクションでは、ファイル操作 (os, io)、コマンドライン引数解析 (flag)、フォーマット出力 (fmt)、そしてこのコミットで変更された tabwriter パッケージをインポートしています。
  • tabwidth 変数は、--tabwidth コマンドラインフラグを通じてユーザーがタブの幅を指定できるようにします。これは、タブをスペースに変換する際に何個のスペースを使用するかを制御するために重要です。
  • Untab 関数は、入力ストリーム (src) から読み込み、TabWriter (dst) を介して処理し、結果を出力ストリームに書き込みます。IO.Copyn は、このデータ転送を実行します。コメントアウトされた // TODO use Copy は、将来的に IO.Copy 関数を使用するようにリファクタリングされる可能性があることを示唆しています。
  • main 関数は、プログラムの実行フローを制御します。コマンドライン引数を解析し、ファイルが指定されていればそれらを処理し、そうでなければ標準入力を処理します。これにより、untab ツールはパイプラインの一部として使用したり、特定のファイルを処理したりすることができます。

全体として、このコミットはGo言語の初期段階におけるコード整形ツールの開発と、そのための基盤となるライブラリのAPI改善を示しています。

関連リンク

参考にした情報源リンク

  • 提供されたコミットデータ (./commit_data/1170.txt)
  • Go言語のパッケージとエクスポートに関する一般的な知識
  • Makefile の基本的な構文と機能に関する知識
  • Go言語の flag パッケージに関する知識
  • Go言語の os および io パッケージに関する知識
  • Go言語の歴史と初期開発に関する一般的な知識 (特に export キーワードの変遷など)# [インデックス 1170] ファイルの概要

このコミットは、Go言語の初期開発段階において、コードの整形(特にタブとスペースの変換)を目的とした新しいコマンドラインユーティリティ untab を導入するものです。同時に、このユーティリティが利用する tabwriter パッケージの内部構造にも変更が加えられ、TabWriter 型とそのコンストラクタ MakeTabWriter が外部から利用可能(エクスポート)になっています。これは、Goのコードベースにおける整形ツールの基盤を構築する一環として行われた変更と考えられます。

コミット

- untab app (snapshot - not quite complete)

R=r
OCL=19558
CL=19558

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

https://github.com/golang/go/commit/127c65b400ef27c3c02242ffd9809f91069218e5

元コミット内容

commit 127c65b400ef27c3c02242ffd9809f91069218e5
Author: Robert Griesemer <gri@golang.org>
Date:   Tue Nov 18 18:44:17 2008 -0800

    - untab app (snapshot - not quite complete)

    R=r
    OCL=19558
    CL=19558
---
 usr/gri/pretty/Makefile     |  6 +++++
 usr/gri/pretty/tabwriter.go | 17 +++++++--------
 usr/gri/pretty/untab.go     | 53 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 9 deletions(-)

変更の背景

このコミットの主な背景は、Go言語のソースコードの整形と標準化の必要性です。特に、タブとスペースの扱いに関する一貫性を確保するため、untab という新しいユーティリティが開発されました。コミットメッセージにある「snapshot - not quite complete」という記述から、これは開発途中のスナップショットであり、将来的にさらに機能が追加される可能性が示唆されています。

Go言語では、gofmt のような自動整形ツールが非常に重視されており、コードの可読性と一貫性を高める文化があります。この untab アプリケーションは、その初期段階における整形ツールの一つとして位置づけられます。tabwriter パッケージの変更は、この新しい untab ツールが tabwriter の機能を利用できるようにするための前提条件であったと考えられます。

また、OCL (Open Change List) と CL (Change List) は、Google内部で使用されていたPerforceバージョン管理システムにおける変更セットの識別子であり、このコミットがGoogle内部のGo開発プロセスの一部として行われたことを示しています。

前提知識の解説

このコミットを理解するためには、以下の概念が役立ちます。

  • Go言語のパッケージとエクスポート: Go言語では、パッケージ内の識別子(変数、関数、型など)が外部からアクセス可能かどうかは、その識別子の最初の文字が大文字であるかどうかで決まります。大文字で始まる識別子は「エクスポート」され、他のパッケージから利用できます。小文字で始まる識別子はパッケージ内部でのみ利用可能です。このコミットでは、tabwriter.go 内の TabWriter 型と MakeTabWriter 関数が export キーワード(当時のGoの構文)によってエクスポートされています。
  • Makefile: Makefile は、ソフトウェアのビルドプロセスを自動化するためのファイルです。make コマンドによって解釈され、ソースコードのコンパイル、リンク、テストなどのタスクを実行します。このコミットでは、新しい untab アプリケーションをビルドするためのルールが Makefile に追加されています。
  • tabwriter パッケージ: Go言語の標準ライブラリには、テキストを整形してタブ位置を揃えるための text/tabwriter パッケージが存在します。このコミットで変更されている usr/gri/pretty/tabwriter.go は、その初期バージョンまたはプロトタイプであると考えられます。tabwriter は、複数の行にわたるテキストの列を自動的に揃える「elastic tabstops」の概念に基づいています。
  • コマンドライン引数とフラグ: untab.go はコマンドラインユーティリティであり、Flag パッケージ(現在の flag パッケージに相当)を使用してコマンドライン引数を解析しています。--tabwidth フラグは、タブの幅を指定するために使用されます。
  • IO.CopynOS.Stdin/OS.Stdout: IO.Copyn は、入力ソースから出力先へバイトをコピーする関数です。OS.Stdin は標準入力、OS.Stdout は標準出力を表し、コマンドラインユーティリティで一般的な入出力ストリームです。

技術的詳細

このコミットは主に3つのファイルに影響を与えています。

  1. usr/gri/pretty/Makefile の変更:

    • all: untab pretty という行が追加され、untab がデフォルトのビルドターゲットに含まれるようになりました。
    • untab: untab.6$(L) -o untab untab.6 というルールが追加され、untab.go から生成されるオブジェクトファイル untab.6 をリンクして実行可能ファイル untab を作成するようになりました。
    • untab.6: tabwriter.6 という依存関係が追加され、untab.gotabwriter.go に依存していることが明示されました。
  2. usr/gri/pretty/tabwriter.go の変更:

    • type TabWriter struct {export type TabWriter struct { に変更されました。これにより、TabWriter 型がパッケージ外部からアクセス可能になりました。当時のGoの構文では export キーワードが使用されていましたが、後に識別子の大文字/小文字でエクスポートが制御されるようになりました。
    • export func MakeTabWriter(writer IO.Write, tabwidth int) IO.Write {export func MakeTabWriter(writer IO.Write, tabwidth int) *TabWriter { に変更されました。MakeTabWriter 関数の戻り値の型が IO.Write インターフェースから具体的なポインタ型 *TabWriter に変更されました。これにより、MakeTabWriter の呼び出し元は、TabWriter の具体的なメソッドにアクセスできるようになり、より柔軟な操作が可能になります。
    • panic();panic("internal error"); に変更されました。これは、パニック発生時に具体的なエラーメッセージを出力するように改善されたものです。
  3. usr/gri/pretty/untab.go の新規追加:

    • このファイルは、新しいコマンドラインユーティリティ untab のソースコードです。
    • package main であり、実行可能ファイルとしてビルドされることを示します。
    • OS, IO, Flag, Fmt, TabWriter といったパッケージをインポートしています。
    • tabwidth というグローバル変数が Flag.Int を使って定義されており、コマンドライン引数 --tabwidth でタブの幅を設定できるようになっています。デフォルト値は4です。
    • Error 関数は、エラーメッセージを出力してプログラムを終了させるヘルパー関数です。
    • Untab 関数は、指定された入力ファイル (src) の内容を TabWriter (dst) を通して処理するコアロジックを含んでいます。IO.Copyn を使用して入力から出力へデータをコピーしています。
    • main 関数は、プログラムのエントリポイントです。
      • Flag.Parse() でコマンドライン引数を解析します。
      • TabWriter.MakeTabWriter を使用して TabWriter のインスタンスを作成し、標準出力 (OS.Stdout) に書き込むように設定します。
      • コマンドライン引数にファイル名が指定されている場合は、それらのファイルを順に開き、Untab 関数で処理します。
      • ファイル名が指定されていない場合は、標準入力 (OS.Stdin) を処理します。

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

usr/gri/pretty/Makefile

--- a/usr/gri/pretty/Makefile
+++ b/usr/gri/pretty/Makefile
@@ -5,6 +5,11 @@
 G=6g
 L=6l
 
+all: untab pretty
+
+untab: untab.6
+	$(L) -o untab untab.6
+	
 pretty: pretty.6
 	$(L) -o pretty pretty.6
 
@@ -34,6 +39,7 @@ platform.6:	 utils.6
 
 printer.6:	 scanner.6 ast.6 tabwriter.6
 
+untab.6:	tabwriter.6
 
 %.6:	%.go
 	$(G) $(F) $<\ndiff --git a/usr/gri/pretty/tabwriter.go b/usr/gri/pretty/tabwriter.go

usr/gri/pretty/tabwriter.go

--- a/usr/gri/pretty/tabwriter.go
+++ b/usr/gri/pretty/tabwriter.go
@@ -85,7 +85,7 @@ func (b *ByteArray) Append(s *[]byte) {\n // of adjacent cells have the same width (by adding padding). For more\n // details see: http://nickgravgaard.com/elastictabstops/index.html .\n \n-type TabWriter struct {\n+export type TabWriter struct {\n \t// configuration\n \twriter IO.Write;\n \ttabwidth int;\n@@ -232,26 +232,25 @@ func (b *TabWriter) Tab() {\n \n func (b *TabWriter) Newline() {\n \tb.Tab();  // add last cell to current line\n-\t\n+\n \tif b.LastLine().Len() == 1 {\n \t\t// The current line has only one cell which does not have an impact\n \t\t// on the formatting of the following lines (the last cell per line\n \t\t// is ignored by Format), thus we can print the TabWriter contents.\n \t\tif b.widths.Len() != 0 {\n-\t\t\tpanic();\n+\t\t\tpanic(\"internal error\");\n \t\t}\n-\t\t//b.Dump();\n \t\tb.Format(0, 0, b.lines.Len());\n \t\tif b.widths.Len() != 0 {\n-\t\t\tpanic();\n+\t\t\tpanic(\"internal error\");\n \t\t}\n-\t\t\n-\t\t// reset the TabWriter\n+\n+\t\t// reset TabWriter\n \t\tb.width = 0;\n \t\tb.buf.Clear();\n \t\tb.lines.Reset();\n \t}\n-\t\n+\n \tb.AddLine();\n }\n \n@@ -278,7 +277,7 @@ func (b *TabWriter) Write(buf *[]byte) (i int, err *OS.Error) {\n }\n \n \n-export func MakeTabWriter(writer IO.Write, tabwidth int) IO.Write {\n+export func MakeTabWriter(writer IO.Write, tabwidth int) *TabWriter {\n \tb := new(TabWriter);\n \tb.Init(writer, tabwidth);\n \treturn b;\ndiff --git a/usr/gri/pretty/untab.go b/usr/gri/pretty/untab.go

usr/gri/pretty/untab.go (新規追加)

// Copyright 2009 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.

package main

import (
	OS "os";
	IO "io";
	Flag "flag";
	Fmt "fmt";
	TabWriter "tabwriter";
)


var (
	tabwidth = Flag.Int("tabwidth", 4, nil, "tab width");
)


func Error(fmt string, params ...) {
	Fmt.printf(fmt, params);
	sys.exit(1);
}


func Untab(name string, src *OS.FD, dst *TabWriter.TabWriter) {
	n, err := IO.Copyn(src, dst, 2e9 /* inf */);  // TODO use Copy
	if err != nil {
		Error("error while processing %s (%v)", name, err);
	}
	//dst.Flush();
}


func main() {
	Flag.Parse();
	dst := TabWriter.MakeTabWriter(OS.Stdout, int(tabwidth.IVal()));
	if Flag.NArg() > 0 {
		for i := 0; i < Flag.NArg(); i++ {
			name := Flag.Arg(i);
			src, err := OS.Open(name, OS.O_RDONLY, 0);
			if err != nil {
				Error("could not open %s (%v)\n", name, err);
			}
			Untab(name, src, dst);
			src.Close();  // ignore errors
		}
	} else {
		// no files => use stdin
		Untab("/dev/stdin", OS.Stdin, dst);
	}
}

コアとなるコードの解説

Makefile の変更

Makefile の変更は、新しい untab 実行可能ファイルをビルドするための手順を定義しています。all ターゲットに untab が追加されたことで、make コマンドを実行すると untab もビルドされるようになります。untab: untab.6untab.6: tabwriter.6 の行は、untabuntab.go からコンパイルされたオブジェクトファイル untab.6 に依存し、さらに untab.6tabwriter.go からコンパイルされた tabwriter.6 に依存することを示しています。これは、untab アプリケーションが tabwriter パッケージの機能を利用しているため、ビルド時にその依存関係を解決する必要があることを意味します。

tabwriter.go の変更

tabwriter.go の変更は、untab アプリケーションが TabWriter の機能を利用できるようにするための重要なAPI変更です。

  • type TabWriter struct { から export type TabWriter struct { への変更は、TabWriter 型がこのパッケージの外部からアクセス可能になったことを示します。これにより、untab.go のような別のパッケージから TabWriter をインスタンス化して利用できるようになります。
  • export func MakeTabWriter(...) IO.Write { から export func MakeTabWriter(...) *TabWriter { への変更は、MakeTabWriter 関数が IO.Write インターフェースではなく、具体的な *TabWriter 型のポインタを返すようになったことを意味します。これにより、untab.goTabWriter の具体的なメソッド(例えば、コメントアウトされている dst.Flush() のようなもの)を呼び出すことが可能になります。インターフェースを返すよりも、具体的な型を返すことで、より多くの機能にアクセスできるようになります。
  • panic(); から panic("internal error"); への変更は、デバッグの際に役立つ具体的なエラーメッセージを提供するように改善されたものです。

untab.go の新規追加

untab.go は、Go言語で書かれた新しいコマンドラインユーティリティです。

  • package main は、このファイルが独立した実行可能プログラムであることを示します。
  • import セクションでは、ファイル操作 (os, io)、コマンドライン引数解析 (flag)、フォーマット出力 (fmt)、そしてこのコミットで変更された tabwriter パッケージをインポートしています。
  • tabwidth 変数は、--tabwidth コマンドラインフラグを通じてユーザーがタブの幅を指定できるようにします。これは、タブをスペースに変換する際に何個のスペースを使用するかを制御するために重要です。
  • Untab 関数は、入力ストリーム (src) から読み込み、TabWriter (dst) を介して処理し、結果を出力ストリームに書き込みます。IO.Copyn は、このデータ転送を実行します。コメントアウトされた // TODO use Copy は、将来的に IO.Copy 関数を使用するようにリファクタリングされる可能性があることを示唆しています。
  • main 関数は、プログラムの実行フローを制御します。コマンドライン引数を解析し、ファイルが指定されていればそれらを処理し、そうでなければ標準入力を処理します。これにより、untab ツールはパイプラインの一部として使用したり、特定のファイルを処理したりすることができます。

全体として、このコミットはGo言語の初期段階におけるコード整形ツールの開発と、そのための基盤となるライブラリのAPI改善を示しています。

関連リンク

参考にした情報源リンク

  • 提供されたコミットデータ (./commit_data/1170.txt)
  • Go言語のパッケージとエクスポートに関する一般的な知識
  • Makefile の基本的な構文と機能に関する知識
  • Go言語の flag パッケージに関する知識
  • Go言語の os および io パッケージに関する知識
  • Go言語の歴史と初期開発に関する一般的な知識 (特に export キーワードの変遷など)