Store default literal value before parsing

Fixes #143.
diff --git a/command_private.go b/command_private.go
index 82ce793..3ae7247 100644
--- a/command_private.go
+++ b/command_private.go
@@ -104,6 +104,16 @@
 	return c.scanType(c.scanSubcommandHandler(c.Group))
 }
 
+func (c *Command) eachOption(f func(*Command, *Group, *Option)) {
+	c.eachCommand(func(c *Command) {
+		c.eachGroup(func(g *Group) {
+			for _, option := range g.options {
+				f(c, g, option)
+			}
+		})
+	}, true)
+}
+
 func (c *Command) eachCommand(f func(*Command), recurse bool) {
 	f(c)
 
diff --git a/help.go b/help.go
index 24a5778..5abe257 100644
--- a/help.go
+++ b/help.go
@@ -9,7 +9,6 @@
 	"bytes"
 	"fmt"
 	"io"
-	"reflect"
 	"runtime"
 	"strings"
 	"unicode/utf8"
@@ -155,39 +154,12 @@
 		dw := descstart - written
 		writer.WriteString(strings.Repeat(" ", dw))
 
-		def := ""
-		defs := option.Default
+		var def string
 
-		if len(option.DefaultMask) != 0 {
-			if option.DefaultMask != "-" {
-				def = option.DefaultMask
-			}
-		} else if len(defs) == 0 && option.canArgument() {
-			var showdef bool
-
-			switch option.field.Type.Kind() {
-			case reflect.Func, reflect.Ptr:
-				showdef = !option.value.IsNil()
-			case reflect.Slice, reflect.String, reflect.Array:
-				showdef = option.value.Len() > 0
-			case reflect.Map:
-				showdef = !option.value.IsNil() && option.value.Len() > 0
-			default:
-				zeroval := reflect.Zero(option.field.Type)
-				showdef = !reflect.DeepEqual(zeroval.Interface(), option.value.Interface())
-			}
-
-			if showdef {
-				def, _ = convertToString(option.value, option.tag)
-			}
-		} else if len(defs) != 0 {
-			l := len(defs) - 1
-
-			for i := 0; i < l; i++ {
-				def += quoteIfNeeded(defs[i]) + ", "
-			}
-
-			def += quoteIfNeeded(defs[l])
+		if len(option.DefaultMask) != 0 && option.DefaultMask != "-" {
+			def = option.DefaultMask
+		} else {
+			def = option.defaultLiteral
 		}
 
 		var envDef string
diff --git a/help_test.go b/help_test.go
index 1843cba..5dbffb6 100644
--- a/help_test.go
+++ b/help_test.go
@@ -315,3 +315,79 @@
 		assertDiff(t, e.Message, expected, "help message")
 	}
 }
+
+func TestHelpDefaults(t *testing.T) {
+	var expected string
+
+	if runtime.GOOS == "windows" {
+		expected = `Usage:
+  TestHelpDefaults [OPTIONS]
+
+Application Options:
+      /with-default:               With default (default: default-value)
+      /without-default:            Without default
+      /with-programmatic-default:  With programmatic default (default:
+                                   default-value)
+
+Help Options:
+  /?                               Show this help message
+  /h, /help                        Show this help message
+`
+	} else {
+		expected = `Usage:
+  TestHelpDefaults [OPTIONS]
+
+Application Options:
+      --with-default=              With default (default: default-value)
+      --without-default=           Without default
+      --with-programmatic-default= With programmatic default (default:
+                                   default-value)
+
+Help Options:
+  -h, --help                       Show this help message
+`
+	}
+
+	tests := []struct {
+		Args   []string
+		Output string
+	}{
+		{
+			Args:   []string{"-h"},
+			Output: expected,
+		},
+		{
+			Args:   []string{"--with-default", "other-value", "--with-programmatic-default", "other-value", "-h"},
+			Output: expected,
+		},
+	}
+
+	for _, test := range tests {
+		var opts struct {
+			WithDefault             string `long:"with-default" default:"default-value" description:"With default"`
+			WithoutDefault          string `long:"without-default" description:"Without default"`
+			WithProgrammaticDefault string `long:"with-programmatic-default" description:"With programmatic default"`
+		}
+
+		opts.WithProgrammaticDefault = "default-value"
+
+		p := NewNamedParser("TestHelpDefaults", HelpFlag)
+		p.AddGroup("Application Options", "The application options", &opts)
+
+		_, err := p.ParseArgs(test.Args)
+
+		if err == nil {
+			t.Fatalf("Expected help error")
+		}
+
+		if e, ok := err.(*Error); !ok {
+			t.Fatalf("Expected flags.Error, but got %T", err)
+		} else {
+			if e.Type != ErrHelp {
+				t.Errorf("Expected flags.ErrHelp type, but got %s", e.Type)
+			}
+
+			assertDiff(t, e.Message, test.Output, "help message")
+		}
+	}
+}
diff --git a/option.go b/option.go
index 73c24f5..068ea32 100644
--- a/option.go
+++ b/option.go
@@ -76,6 +76,8 @@
 
 	tag   multiTag
 	isSet bool
+
+	defaultLiteral string
 }
 
 // LongNameWithNamespace returns the option's long name with the group namespaces
diff --git a/option_private.go b/option_private.go
index 06fc206..ab63ba2 100644
--- a/option_private.go
+++ b/option_private.go
@@ -203,3 +203,38 @@
 
 	return nil
 }
+
+func (option *Option) updateDefaultLiteral() {
+	defs := option.Default
+	def := ""
+
+	if len(defs) == 0 && option.canArgument() {
+		var showdef bool
+
+		switch option.field.Type.Kind() {
+		case reflect.Func, reflect.Ptr:
+			showdef = !option.value.IsNil()
+		case reflect.Slice, reflect.String, reflect.Array:
+			showdef = option.value.Len() > 0
+		case reflect.Map:
+			showdef = !option.value.IsNil() && option.value.Len() > 0
+		default:
+			zeroval := reflect.Zero(option.field.Type)
+			showdef = !reflect.DeepEqual(zeroval.Interface(), option.value.Interface())
+		}
+
+		if showdef {
+			def, _ = convertToString(option.value, option.tag)
+		}
+	} else if len(defs) != 0 {
+		l := len(defs) - 1
+
+		for i := 0; i < l; i++ {
+			def += quoteIfNeeded(defs[i]) + ", "
+		}
+
+		def += quoteIfNeeded(defs[l])
+	}
+
+	option.defaultLiteral = def
+}
diff --git a/parser.go b/parser.go
index d403a40..928f225 100644
--- a/parser.go
+++ b/parser.go
@@ -170,7 +170,10 @@
 		return nil, p.internalError
 	}
 
-	p.clearIsSet()
+	p.eachOption(func(c *Command, g *Group, option *Option) {
+		option.isSet = false
+		option.updateDefaultLiteral()
+	})
 
 	// Add built-in help group to all commands if necessary
 	if (p.Options & HelpFlag) != None {
@@ -254,17 +257,13 @@
 	}
 
 	if s.err == nil {
-		p.eachCommand(func(c *Command) {
-			c.eachGroup(func(g *Group) {
-				for _, option := range g.options {
-					if option.isSet {
-						continue
-					}
+		p.eachOption(func(c *Command, g *Group, option *Option) {
+			if option.isSet {
+				return
+			}
 
-					option.clearDefault()
-				}
-			})
-		}, true)
+			option.clearDefault()
+		})
 
 		s.checkRequired(p)
 	}