@@ -1172,6 +1172,91 @@ func TestCommand_PositionalArgsKeepWhitespace(t *testing.T) {
11721172 require .Equal (t , []string {" padded " , "\t tabbed\t " }, args .Slice ())
11731173}
11741174
1175+ func TestCommand_FlagValuesKeepWhitespace (t * testing.T ) {
1176+ cases := []struct {
1177+ name string
1178+ flag string
1179+ value string
1180+ trimSpace bool
1181+ }{
1182+ {name : "empty" , flag : "--text" },
1183+ {name : "spaces" , flag : "--text" , value : " hello " },
1184+ {name : "tab only" , flag : "--text" , value : "\t " },
1185+ {name : "newline" , flag : "--text" , value : "line\n " },
1186+ {name : "unicode space" , flag : "--text" , value : "space\u00a0 " },
1187+ {name : "embedded equals" , flag : "--text" , value : "a=b " },
1188+ {name : "alias" , flag : "-t" , value : " hello " },
1189+ {name : "leading flag whitespace" , flag : "\t --text" , value : " hello " },
1190+ {name : "trim enabled" , flag : "--text" , value : "\t hello \n " , trimSpace : true },
1191+ }
1192+ for _ , kind := range []string {"string" , "slice" , "map" } {
1193+ for _ , tc := range cases {
1194+ for _ , equals := range []bool {false , true } {
1195+ t .Run (fmt .Sprintf ("%s/%s/equals=%v" , kind , tc .name , equals ), func (t * testing.T ) {
1196+ config := StringConfig {TrimSpace : tc .trimSpace }
1197+ want := tc .value
1198+ if tc .trimSpace {
1199+ want = strings .TrimSpace (want )
1200+ }
1201+ var fl Flag
1202+ var expected any
1203+ input := tc .value
1204+ switch kind {
1205+ case "string" :
1206+ fl = & StringFlag {Name : "text" , Aliases : []string {"t" }, Config : config }
1207+ expected = want
1208+ case "slice" :
1209+ fl = & StringSliceFlag {Name : "text" , Aliases : []string {"t" }, Config : config }
1210+ expected = []string {want }
1211+ case "map" :
1212+ fl = & StringMapFlag {Name : "text" , Aliases : []string {"t" }, Config : config }
1213+ input = "key=" + tc .value
1214+ expected = map [string ]string {"key" : want }
1215+ }
1216+ args := []string {"app" , tc .flag , input , "operand" }
1217+ if equals {
1218+ args = []string {"app" , tc .flag + "=" + input , "operand" }
1219+ }
1220+ cmd := & Command {Flags : []Flag {fl }, Action : func (_ context.Context , cmd * Command ) error {
1221+ assert .Equal (t , expected , cmd .Value ("text" ))
1222+ assert .Equal (t , []string {"operand" }, cmd .Args ().Slice ())
1223+ return nil
1224+ }}
1225+ require .NoError (t , cmd .Run (buildTestContext (t ), args ))
1226+ })
1227+ }
1228+ }
1229+ }
1230+ }
1231+
1232+ func TestCommand_EqualsFlagValueValidation (t * testing.T ) {
1233+ for _ , kind := range []string {"int" , "bool" } {
1234+ for _ , whitespace := range []string {"" , " " , "\t " } {
1235+ t .Run (fmt .Sprintf ("%s/whitespace=%q" , kind , whitespace ), func (t * testing.T ) {
1236+ var fl Flag = & IntFlag {Name : "value" }
1237+ value := "42"
1238+ if kind == "bool" {
1239+ fl = & BoolFlag {Name : "value" }
1240+ value = "true"
1241+ }
1242+ actionRan := false
1243+ cmd := & Command {
1244+ Flags : []Flag {fl }, Writer : io .Discard , ErrWriter : io .Discard ,
1245+ Action : func (_ context.Context , _ * Command ) error { actionRan = true ; return nil },
1246+ }
1247+ err := cmd .Run (buildTestContext (t ), []string {"app" , "--value=" + value + whitespace })
1248+ if whitespace == "" {
1249+ require .NoError (t , err )
1250+ assert .True (t , actionRan )
1251+ } else {
1252+ require .Error (t , err )
1253+ assert .False (t , actionRan )
1254+ }
1255+ })
1256+ }
1257+ }
1258+ }
1259+
11751260func TestCommand_CommandWithNoFlagBeforeTerminator (t * testing.T ) {
11761261 var args Args
11771262
0 commit comments