Merge pull request #64 from zimmski/ini-comment-defaults

Add ini option for commenting out default values
diff --git a/help_test.go b/help_test.go
index deeb6a5..fe77f6d 100644
--- a/help_test.go
+++ b/help_test.go
@@ -44,13 +44,14 @@
 	Verbose          []bool       `short:"v" long:"verbose" description:"Show verbose debug information" ini-name:"verbose"`
 	Call             func(string) `short:"c" description:"Call phone number" ini-name:"call"`
 	PtrSlice         []*string    `long:"ptrslice" description:"A slice of pointers to string"`
+	Default          string       `long:"default" default:"Some value" description:"Test default value"`
 	EmptyDescription bool         `long:"empty-description"`
 
 	OnlyIni string `ini-name:"only-ini" description:"Option only available in ini"`
 
 	Other struct {
-		StringSlice []string       `short:"s" description:"A slice of strings"`
-		IntMap      map[string]int `long:"intmap" description:"A map from string to int" ini-name:"int-map"`
+		StringSlice []string       `short:"s" default:"some" default:"value" description:"A slice of strings"`
+		IntMap      map[string]int `long:"intmap" default:"a:1" description:"A map from string to int" ini-name:"int-map"`
 	} `group:"Other Options"`
 
 	Command struct {
@@ -84,11 +85,12 @@
   -v, --verbose            Show verbose debug information
   -c=                      Call phone number
       --ptrslice=          A slice of pointers to string
+      --default=           Test default value (Some value)
       --empty-description
 
 Other Options:
-  -s=                      A slice of strings
-      --intmap=            A map from string to int
+  -s=                      A slice of strings (some, value)
+      --intmap=            A map from string to int (a:1)
 
 Help Options:
   -h, --help               Show this help message
@@ -145,6 +147,9 @@
 \fB--ptrslice\fP
 A slice of pointers to string
 .TP
+\fB--default\fP
+Test default value
+.TP
 \fB--empty-description\fP
 .TP
 \fB-s\fP
diff --git a/ini.go b/ini.go
index ce95d13..6952cac 100644
--- a/ini.go
+++ b/ini.go
@@ -38,6 +38,10 @@
 	// when writing options to an ini file.
 	IniIncludeDefaults = 1 << iota
 
+	// IniCommentDefaults indicates that if IniIncludeDefaults is used
+	// options with default values are written but commented out.
+	IniCommentDefaults
+
 	// IniIncludeComments indicates that comments containing the description
 	// of an option should be written when writing options to an ini file.
 	IniIncludeComments
diff --git a/ini_private.go b/ini_private.go
index 0371b87..9f56657 100644
--- a/ini_private.go
+++ b/ini_private.go
@@ -96,11 +96,16 @@
 
 		oname := optionIniName(option)
 
+		commentOption := ""
+		if (options&(IniIncludeDefaults|IniCommentDefaults)) == IniIncludeDefaults|IniCommentDefaults && reflect.DeepEqual(val.Interface(), option.defaultValue.Interface()) {
+			commentOption = "; "
+		}
+
 		switch val.Type().Kind() {
 		case reflect.Slice:
 			for idx := 0; idx < val.Len(); idx++ {
 				v, _ := convertToString(val.Index(idx), option.tag)
-				fmt.Fprintf(writer, "%s = %s\n", oname, v)
+				fmt.Fprintf(writer, "%s%s = %s\n", commentOption, oname, v)
 			}
 
 			if val.Len() == 0 {
@@ -111,7 +116,7 @@
 				k, _ := convertToString(key, option.tag)
 				v, _ := convertToString(val.MapIndex(key), option.tag)
 
-				fmt.Fprintf(writer, "%s = %s:%s\n", oname, k, v)
+				fmt.Fprintf(writer, "%s%s = %s:%s\n", commentOption, oname, k, v)
 			}
 
 			if val.Len() == 0 {
@@ -121,9 +126,9 @@
 			v, _ := convertToString(val, option.tag)
 
 			if len(v) != 0 {
-				fmt.Fprintf(writer, "%s = %s\n", oname, v)
+				fmt.Fprintf(writer, "%s%s = %s\n", commentOption, oname, v)
 			} else {
-				fmt.Fprintf(writer, "%s =\n", oname)
+				fmt.Fprintf(writer, "%s%s =\n", commentOption, oname)
 			}
 		}
 
diff --git a/ini_test.go b/ini_test.go
index b3b8a8b..7f78907 100644
--- a/ini_test.go
+++ b/ini_test.go
@@ -32,6 +32,9 @@
 ; A slice of pointers to string
 ; PtrSlice =
 
+; Test default value
+Default = Some value
+
 EmptyDescription = false
 
 ; Option only available in ini
@@ -39,7 +42,8 @@
 
 [Other Options]
 ; A slice of strings
-; StringSlice =
+StringSlice = some
+StringSlice = value
 
 ; A map from string to int
 int-map = a:2
@@ -62,6 +66,64 @@
 	}
 }
 
+func TestWriteIniCommentDefaults(t *testing.T) {
+	var opts helpOptions
+
+	p := NewNamedParser("TestIni", Default)
+	p.AddGroup("Application Options", "The application options", &opts)
+
+	_, err := p.ParseArgs([]string{"command"})
+
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+
+	inip := NewIniParser(p)
+
+	var b bytes.Buffer
+	inip.Write(&b, IniDefault|IniIncludeDefaults|IniCommentDefaults)
+
+	got := b.String()
+	expected := `[Application Options]
+; Show verbose debug information
+; verbose =
+
+; A slice of pointers to string
+; PtrSlice =
+
+; Test default value
+; Default = Some value
+
+; EmptyDescription = false
+
+; Option only available in ini
+; only-ini =
+
+[Other Options]
+; A slice of strings
+; StringSlice = some
+; StringSlice = value
+
+; A map from string to int
+; int-map = a:1
+
+[command.A command]
+; Use for extra verbosity
+; ExtraVerbose =
+
+`
+
+	if got != expected {
+		ret, err := helpDiff(got, expected)
+
+		if err != nil {
+			t.Errorf("Unexpected ini, expected:\n\n%s\n\nbut got\n\n%s", expected, got)
+		} else {
+			t.Errorf("Unexpected ini:\n\n%s", ret)
+		}
+	}
+}
+
 func TestReadIni(t *testing.T) {
 	var opts helpOptions
 
@@ -79,6 +141,9 @@
 ; A slice of pointers to string
 ; PtrSlice =
 
+; Test default value
+Default = Some value
+
 [Other Options]
 # A slice of strings
 # StringSlice =