Make falsy tag strings behave intuitively

Fixes #226.
diff --git a/group.go b/group.go
index 51b4704..6133a71 100644
--- a/group.go
+++ b/group.go
@@ -174,6 +174,10 @@
 	}
 }
 
+func isStringFalsy(s string) bool {
+	return s == "" || s == "false" || s == "no" || s == "0"
+}
+
 func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField, handler scanHandler) error {
 	stype := realval.Type()
 
@@ -255,10 +259,10 @@
 		valueName := mtag.Get("value-name")
 		defaultMask := mtag.Get("default-mask")
 
-		optional := (mtag.Get("optional") != "")
-		required := (mtag.Get("required") != "")
+		optional := !isStringFalsy(mtag.Get("optional"))
+		required := !isStringFalsy(mtag.Get("required"))
 		choices := mtag.GetMany("choice")
-		hidden := (mtag.Get("hidden") != "")
+		hidden := !isStringFalsy(mtag.Get("hidden"))
 
 		option := &Option{
 			Description:      description,
diff --git a/help_test.go b/help_test.go
index 01942a2..534a51c 100644
--- a/help_test.go
+++ b/help_test.go
@@ -36,8 +36,9 @@
 	} `group:"Hidden group" hidden:"yes"`
 
 	Group struct {
-		Opt               string `long:"opt" description:"This is a subgroup option"`
-		HiddenInsideGroup string `long:"hidden-inside-group" description:"Hidden inside group" hidden:"yes"`
+		Opt                  string `long:"opt" description:"This is a subgroup option"`
+		HiddenInsideGroup    string `long:"hidden-inside-group" description:"Hidden inside group" hidden:"yes"`
+		NotHiddenInsideGroup string `long:"not-hidden-inside-group" description:"Not hidden inside group" hidden:"false"`
 
 		Group struct {
 			Opt string `long:"opt" description:"This is a subsubgroup option"`
@@ -113,6 +114,7 @@
 
 Subgroup:
       /sip.opt:                             This is a subgroup option
+      /sip.not-hidden-inside-group:         Not hidden inside group
 
 Subsubgroup:
       /sip.sap.opt:                         This is a subsubgroup option
@@ -159,6 +161,7 @@
 
 Subgroup:
       --sip.opt=                            This is a subgroup option
+      --sip.not-hidden-inside-group=        Not hidden inside group
 
 Subsubgroup:
       --sip.sap.opt=                        This is a subsubgroup option
@@ -261,6 +264,9 @@
 .TP
 \fB\fB\-\-sip.opt\fR\fP
 This is a subgroup option
+.TP
+\fB\fB\-\-sip.not-hidden-inside-group\fR\fP
+Not hidden inside group
 .SS Subsubgroup
 .TP
 \fB\fB\-\-sip.sap.opt\fR\fP
diff --git a/ini_test.go b/ini_test.go
index e1f22ce..ad4852e 100644
--- a/ini_test.go
+++ b/ini_test.go
@@ -93,6 +93,9 @@
 ; This is a subgroup option
 Opt =
 
+; Not hidden inside group
+NotHiddenInsideGroup =
+
 [Subsubgroup]
 ; This is a subsubgroup option
 Opt =
@@ -153,6 +156,9 @@
 ; This is a subgroup option
 ; Opt =
 
+; Not hidden inside group
+; NotHiddenInsideGroup =
+
 [Subsubgroup]
 ; This is a subsubgroup option
 ; Opt =
@@ -211,6 +217,9 @@
 ; This is a subgroup option
 ; Opt =
 
+; Not hidden inside group
+; NotHiddenInsideGroup =
+
 [Subsubgroup]
 ; This is a subsubgroup option
 ; Opt =
diff --git a/short_test.go b/short_test.go
index 95712c1..5f4106b 100644
--- a/short_test.go
+++ b/short_test.go
@@ -35,6 +35,22 @@
 	assertParseFail(t, ErrRequired, fmt.Sprintf("the required flag `%cv' was not specified", defaultShortOptDelimiter), &opts)
 }
 
+func TestShortRequiredFalsy1(t *testing.T) {
+	var opts = struct {
+		Value bool `short:"v" required:"false"`
+	}{}
+
+	assertParseSuccess(t, &opts)
+}
+
+func TestShortRequiredFalsy2(t *testing.T) {
+	var opts = struct {
+		Value bool `short:"v" required:"no"`
+	}{}
+
+	assertParseSuccess(t, &opts)
+}
+
 func TestShortMultiConcat(t *testing.T) {
 	var opts = struct {
 		V bool `short:"v"`
@@ -192,3 +208,27 @@
 	assertStringArray(t, ret, []string{"f"})
 	assertString(t, opts.Value, "value")
 }
+
+func TestShortOptionalFalsy1(t *testing.T) {
+	var opts = struct {
+		F     []bool `short:"f"`
+		Value string `short:"v" optional:"false" optional-value:"value"`
+	}{}
+
+	ret := assertParseSuccess(t, &opts, "-fv", "f")
+
+	assertStringArray(t, ret, []string{})
+	assertString(t, opts.Value, "f")
+}
+
+func TestShortOptionalFalsy2(t *testing.T) {
+	var opts = struct {
+		F     []bool `short:"f"`
+		Value string `short:"v" optional:"no" optional-value:"value"`
+	}{}
+
+	ret := assertParseSuccess(t, &opts, "-fv", "f")
+
+	assertStringArray(t, ret, []string{})
+	assertString(t, opts.Value, "f")
+}