Add specification of required rest arg range

The `”required”` tag now also accepts a “<min>-<max>” range, which may
be set to “0-0” to not allow any rest arguments.
diff --git a/arg.go b/arg.go
index d160644..8ec6204 100644
--- a/arg.go
+++ b/arg.go
@@ -12,9 +12,12 @@
 	// A description of the positional argument (used in the help)
 	Description string
 
-	// Whether a positional argument is required
+	// The minimal number of required positional arguments
 	Required int
 
+	// The maximum number of required positional arguments
+	RequiredMaximum int
+
 	value reflect.Value
 	tag   multiTag
 }
diff --git a/arg_test.go b/arg_test.go
index 117e90e..c7c0a61 100644
--- a/arg_test.go
+++ b/arg_test.go
@@ -131,3 +131,33 @@
 	assertString(t, opts.Positional.Rest[1], "rest2")
 	assertString(t, opts.Positional.Rest[2], "rest3")
 }
+
+func TestPositionalRequiredRestRangeFail(t *testing.T) {
+	var opts = struct {
+		Value bool `short:"v"`
+
+		Positional struct {
+			Rest []string `required:"1-2"`
+		} `positional-args:"yes"`
+	}{}
+
+	p := NewParser(&opts, None)
+	_, err := p.ParseArgs([]string{"rest1", "rest2", "rest3"})
+
+	assertError(t, err, ErrRequired, "the required argument `Rest (at most 2 arguments, but got 3)` was not provided")
+}
+
+func TestPositionalRequiredRestRangeEmptyFail(t *testing.T) {
+	var opts = struct {
+		Value bool `short:"v"`
+
+		Positional struct {
+			Rest []string `required:"0-0"`
+		} `positional-args:"yes"`
+	}{}
+
+	p := NewParser(&opts, None)
+	_, err := p.ParseArgs([]string{"some", "thing"})
+
+	assertError(t, err, ErrRequired, "the required argument `Rest (zero arguments)` was not provided")
+}
diff --git a/command.go b/command.go
index aab34e6..580652c 100644
--- a/command.go
+++ b/command.go
@@ -181,15 +181,28 @@
 					name = field.Name
 				}
 
-				var required int
+				required := -1
+				requiredMaximum := -1
 
 				sreq := m.Get("required")
 
 				if sreq != "" {
 					required = 1
 
-					if preq, err := strconv.ParseInt(sreq, 10, 32); err == nil {
-						required = int(preq)
+					rng := strings.SplitN(sreq, "-", 2)
+
+					if len(rng) > 1 {
+						if preq, err := strconv.ParseInt(rng[0], 10, 32); err == nil {
+							required = int(preq)
+						}
+
+						if preq, err := strconv.ParseInt(rng[1], 10, 32); err == nil {
+							requiredMaximum = int(preq)
+						}
+					} else {
+						if preq, err := strconv.ParseInt(sreq, 10, 32); err == nil {
+							required = int(preq)
+						}
 					}
 				}
 
@@ -197,6 +210,7 @@
 					Name:        name,
 					Description: m.Get("description"),
 					Required:    required,
+					RequiredMaximum: requiredMaximum,
 
 					value: realval.Field(i),
 					tag:   m,
diff --git a/parser.go b/parser.go
index eee6e17..137bc07 100644
--- a/parser.go
+++ b/parser.go
@@ -377,7 +377,7 @@
 			var reqnames []string
 
 			for _, arg := range p.positional {
-				argRequired := (!arg.isRemaining() && p.command.ArgsRequired) || arg.Required != 0
+				argRequired := (!arg.isRemaining() && p.command.ArgsRequired) || arg.Required != -1 || arg.RequiredMaximum != -1
 
 				if !argRequired {
 					continue
@@ -394,6 +394,20 @@
 						}
 
 						reqnames = append(reqnames, "`"+arg.Name+" (at least "+fmt.Sprintf("%d", arg.Required)+" "+arguments+")`")
+					} else if arg.RequiredMaximum != -1 && arg.value.Len() > arg.RequiredMaximum {
+						if arg.RequiredMaximum == 0 {
+							reqnames = append(reqnames, "`"+arg.Name+" (zero arguments)`")
+						} else {
+							var arguments string
+
+							if arg.RequiredMaximum > 1 {
+								arguments = "arguments, but got " + fmt.Sprintf("%d", arg.value.Len())
+							} else {
+								arguments = "argument"
+							}
+
+							reqnames = append(reqnames, "`"+arg.Name+" (at most "+fmt.Sprintf("%d", arg.RequiredMaximum)+" "+arguments+")`")
+						}
 					}
 				} else {
 					reqnames = append(reqnames, "`"+arg.Name+"`")