From a1cf7f44b6cf65c0c10c282c71524cc37442b798 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Mon, 12 Aug 2019 09:42:12 +0200 Subject: [PATCH 1/5] Add `TakesFile` to fish shell completion The new `TakesFile` flag will be now consumed by the fish shell completion generator. Signed-off-by: Sascha Grunert --- docs_test.go | 12 ++- fish.go | 8 +- flag-gen/assets_vfsdata.go | 4 +- flag-gen/templates/cli_flags_generated.gotpl | 6 ++ flag.go | 4 + flag_generated.go | 78 ++++++++++++++++++++ testdata/expected-fish-full.fish | 34 ++++----- 7 files changed, 121 insertions(+), 25 deletions(-) diff --git a/docs_test.go b/docs_test.go index 177eb19..25afd23 100644 --- a/docs_test.go +++ b/docs_test.go @@ -10,9 +10,10 @@ func testApp() *App { app.Name = "greet" app.Flags = []Flag{ StringFlag{ - Name: "socket, s", - Usage: "some usage text", - Value: "value", + Name: "socket, s", + Usage: "some usage text", + Value: "value", + TakesFile: true, }, StringFlag{Name: "flag, fl, f"}, BoolFlag{ @@ -23,7 +24,10 @@ func testApp() *App { app.Commands = []Command{{ Aliases: []string{"c"}, Flags: []Flag{ - StringFlag{Name: "flag, fl, f"}, + StringFlag{ + Name: "flag, fl, f", + TakesFile: true, + }, BoolFlag{ Name: "another-flag, b", Usage: "another usage text", diff --git a/fish.go b/fish.go index 0f51065..d286881 100644 --- a/fish.go +++ b/fish.go @@ -75,7 +75,7 @@ func (a *App) prepareFishCommands( var completion strings.Builder completion.WriteString(fmt.Sprintf( - "complete -c %s -f -n '%s' -a '%s'", + "complete -r -c %s -n '%s' -a '%s'", a.Name, a.fishSubcommandHelper(previousCommands), strings.Join(command.Names(), " "), @@ -126,11 +126,15 @@ func (a *App) prepareFishFlags( var completion strings.Builder completion.WriteString(fmt.Sprintf( - "complete -c %s -f -n '%s'", + "complete -c %s -n '%s'", a.Name, a.fishSubcommandHelper(previousCommands), )) + if !flag.GetTakesFile() { + completion.WriteString(" -f") + } + for idx, opt := range strings.Split(flag.GetName(), ",") { if idx == 0 { completion.WriteString(fmt.Sprintf( diff --git a/flag-gen/assets_vfsdata.go b/flag-gen/assets_vfsdata.go index ab600d9..7e7d01b 100644 --- a/flag-gen/assets_vfsdata.go +++ b/flag-gen/assets_vfsdata.go @@ -46,9 +46,9 @@ var assets = func() http.FileSystem { "/templates/cli_flags_generated.gotpl": &vfsgen۰CompressedFileInfo{ name: "cli_flags_generated.gotpl", modTime: time.Time{}, - uncompressedSize: 2638, + uncompressedSize: 2895, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x55\x4d\x6f\xe3\x36\x10\x3d\x4b\xbf\x62\x6a\xec\x41\x0a\x5c\xfb\xde\xc5\x9e\xe2\xcd\x76\x81\x62\x37\xe8\xa6\xb9\xd3\xd2\x50\x26\x42\x93\x0a\x39\x4a\x1a\x18\xfe\xef\xc5\x90\xd4\x87\x3f\x10\xfb\x92\x9e\x2c\x72\x66\xde\x7b\x7c\x33\xa4\x97\x4b\xb8\xb5\x35\x42\x83\x06\x9d\x20\xac\x61\xfd\x06\xb2\xf9\x0c\xab\x9f\xf0\xe3\xe7\x03\x7c\x5d\x7d\x7f\x58\xe4\x79\x2b\xaa\x27\xd1\x20\xec\x76\xb0\xb8\x8f\xdf\x3f\xc4\x16\x61\xbf\xcf\x73\xb5\x6d\xad\x23\x28\xf2\x6c\x26\xb5\x68\x66\xfc\xbb\x25\xfe\xf1\xe4\x2a\x6b\x5e\xf8\x93\xd4\x16\x67\x79\x99\xef\x76\xe0\x84\x69\x10\x3e\xa9\x39\x7c\xe2\x7c\xf8\xe3\x0b\x2c\xee\xb4\x68\x3c\xa3\x2d\x97\xcc\x11\x02\x8b\xc4\xc0\x31\x50\x1e\x04\x84\xf4\x57\x45\x1b\xa0\xb7\x16\xc7\xc4\x07\x5e\xed\xf7\xc3\x7a\x65\x2b\x12\x4a\x33\xde\x61\xe2\x14\xd1\x93\xeb\x2a\x82\x5d\x9e\xf1\x6e\x96\x79\x72\xca\x34\x79\xf6\x8f\x17\xcd\x64\xf9\xd5\xbc\x3c\x0a\x37\xae\xef\x94\xc6\x7b\x41\x9b\x61\xe3\x6f\x7c\xee\x94\xc3\x3a\x5b\x5b\xab\xf3\xec\x4f\x55\xd7\x68\xb2\xb4\xda\xed\x7e\x07\x25\x01\x9f\x7b\xa5\xe2\x09\x3d\x43\x00\xb9\x2e\xd8\x97\x0d\x5b\x93\x12\x34\x75\x88\x1d\x97\x3f\x0a\xdd\x4d\x4a\xc3\x32\x3b\xb6\xe1\x7d\x88\x15\x7a\x52\x46\x90\xb2\x66\x04\x9a\x6c\x66\x37\xef\xe2\xed\x73\x6e\xd1\xaf\x70\x76\x70\x48\x9d\x33\xdc\x19\x87\xa2\x16\x6b\x8d\xe0\xb0\x75\xe8\xd1\x50\x64\xb0\x12\x68\xa3\x3c\xbc\xb0\x52\xae\x2c\xa4\x75\xd0\xb1\xc5\x50\xa3\x14\x9d\x26\x5f\xe6\xb2\x33\x15\x14\xf2\x6c\x9f\xca\x44\x56\x94\x10\x1d\xe7\x8e\x45\x62\xe0\x78\x8c\xa2\x2b\x64\x99\xc4\x7d\x43\x0a\xf5\xbd\x3a\xda\x20\x18\xde\x08\x62\x30\x4c\xd1\x05\xca\x04\x71\x8e\x53\x86\xcc\x44\xf5\xdd\xf7\xdd\x1f\xd8\x5e\x37\x48\x1b\x74\x60\x1d\x18\x4b\x03\x21\x0f\xb0\x4b\xb9\x17\xc8\x47\xd0\xa2\x04\x9e\x89\x03\xf6\x3e\x96\x14\x84\xe9\x89\x63\x31\x9c\x97\xbb\x3a\x39\x2b\x10\xe7\x80\x88\x4d\x98\x83\x65\x7d\xaf\xca\x23\x48\xa1\x3d\x5e\x50\x33\x12\x9c\xaa\x19\x2a\xa2\x80\x61\x3c\xbe\x21\x85\x5b\x74\xd0\x82\xd8\xf4\xe4\x27\x4f\xc1\xf5\xbd\x08\x60\xe7\x9b\x11\x42\x23\xed\x91\x13\x89\x21\xcd\x1f\x08\xdf\x43\x1c\x8d\xa9\x30\x35\x08\x03\xb8\x6d\xe9\x8d\x91\x52\x96\x3a\x31\xd1\xd8\x1e\x8a\x40\x68\xbd\xb8\xac\xbd\xb7\x6e\xd4\x7e\xe8\x5a\xba\x4a\x83\x77\xc7\x40\xa0\xad\x7d\xf2\xd0\xb5\x41\x4a\x24\xb7\x12\x04\x68\x5b\x09\x7d\x96\x77\xde\x1b\x70\x80\x77\x6b\x0d\xe1\xbf\xb4\x8a\xb7\x8e\x91\x95\x0c\x23\x2a\x6d\x67\xfa\x99\xac\xe0\x26\xe5\x95\x27\xd0\x45\xb8\x44\xf1\x1c\x21\xca\xf5\x08\x3d\x70\x78\x2d\x66\xb3\xe9\x3b\x3c\x8d\x84\x6d\xd4\xfe\xe0\xa1\x1e\x22\xfd\xfb\x32\xe9\x2d\x9f\xbb\x6b\xcf\x8a\x98\x43\xb5\xe0\xcd\x5f\x48\xc3\xa5\xd7\x76\x2d\xf4\xd5\xe6\x35\x21\xfd\x23\xdd\x3b\x2f\xe8\xff\xf2\x50\x49\x90\x9e\xff\x59\xa3\x8b\x51\xcc\x5d\xb4\xac\xb7\xb0\xfc\xcc\x39\xbf\x7d\x01\xa3\xc2\xa5\xbe\xca\x78\xe9\xcb\x3c\xdb\x9f\xbe\x00\x27\xfe\x70\x5f\x82\x2b\xef\xc0\x25\x23\xe6\xe0\x91\xe0\x26\x84\x93\xc6\x8f\xf4\x46\xb2\x2f\x1e\x69\xf1\x57\x50\x16\x94\x94\xd1\xb2\xa9\x1b\xa3\x80\x7b\xe1\x3c\xba\xc8\xdd\xf2\x77\x3d\x07\x74\x8e\x61\x06\xa6\x94\x33\x55\x71\x94\x2a\xe3\x7d\x0f\x6b\xeb\x0a\xa3\x74\xc9\xb9\xe9\x6f\x9a\xe9\x39\x71\x22\xe0\x0a\x8f\x33\x6e\xc5\x89\xd2\x5b\xe1\x29\xaa\x3d\x46\x98\xc4\xa7\x4a\x53\x5a\x14\x3c\x11\x75\x65\x9f\xc7\x8a\xff\x02\x00\x00\xff\xff\x73\xc9\x52\x5f\x4e\x0a\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x56\x4d\x6f\xdb\x38\x10\x3d\x4b\xbf\x62\xd6\xe8\xc1\x0a\xbc\xce\x7d\x8b\x9e\xe2\xa6\x5b\x60\xd1\x06\xdb\x6c\xef\x8c\x34\x94\x89\xd0\xa4\x4a\x8e\x92\x0d\x04\xff\xf7\xc5\x90\x94\x44\x7f\x20\xf1\xa5\x8b\x9e\x22\x72\x86\xef\x3d\xbe\x19\x8e\x73\x7d\x0d\x37\xb6\x41\x68\xd1\xa0\x13\x84\x0d\x3c\xbc\x80\x6c\xdf\xc3\xe6\x2b\x7c\xf9\x7a\x0f\x1f\x37\x9f\xef\xd7\x65\xd9\x89\xfa\x51\xb4\x08\xc3\x00\xeb\xbb\xf8\xfd\x45\xec\x10\xf6\xfb\xb2\x54\xbb\xce\x3a\x82\x65\x59\x2c\xa4\x16\xed\x82\xff\xee\x88\xff\x78\x72\xb5\x35\x4f\xfc\x49\x6a\x87\x8b\xb2\x2a\x87\x01\x9c\x30\x2d\xc2\x3b\xb5\x82\x77\x9c\x0f\x7f\x7c\x80\xf5\xad\x16\xad\x67\xb4\xeb\x6b\xe6\x08\x81\x75\x62\xe0\x18\x28\x0f\x02\x42\xfa\xb3\xa2\x2d\xd0\x4b\x87\x73\xe2\x3d\xaf\xf6\xfb\x69\xbd\xb1\x35\x09\xa5\x19\xef\x30\x31\x47\xf4\xe4\xfa\x9a\x60\x28\x0b\xde\x2d\x0a\x4f\x4e\x99\xb6\x2c\xfe\xf1\xa2\xcd\x96\x1f\xcd\xd3\x77\xe1\xe6\xf5\xad\xd2\x78\x27\x68\x3b\x6d\xfc\x8d\x3f\x7a\xe5\xb0\x29\x1e\xac\xd5\x65\xf1\xa7\x6a\x1a\x34\x45\x5a\x0d\xc3\xef\xa0\x24\xe0\x8f\x51\xa9\x78\x44\xcf\x10\x40\xae\x0f\xf6\x15\xd3\x56\x76\x04\x4d\x13\x62\xc7\xc7\xbf\x0b\xdd\x67\x47\xc3\xb2\x38\xb6\xe1\x75\x88\x0d\x7a\x52\x46\x90\xb2\x66\x06\xca\x36\x8b\xab\x57\xf1\xf6\x25\x97\xe8\x5b\xb8\x3b\x38\xa4\xde\x19\xae\x8c\x43\xd1\x88\x07\x8d\xe0\xb0\x73\xe8\xd1\x50\x64\xb0\x12\x68\xab\x3c\x3c\xb1\x52\x3e\xb9\x94\xd6\x41\xcf\x16\x43\x83\x52\xf4\x9a\x7c\x55\xca\xde\xd4\xb0\x94\x67\xeb\x54\x25\xb2\x65\x05\xd1\x71\xae\x58\x24\x06\x8e\xc7\x28\xba\xa5\xac\x92\xb8\x4f\x48\xe1\xfc\xa8\x8e\xb6\x08\x86\x37\x82\x18\x0c\x5d\xf4\x06\x65\x82\x38\xc7\x29\x43\x66\xa2\xfa\xec\xc7\xea\x4f\x6c\xcf\x5b\xa4\x2d\x3a\xb0\x0e\x8c\xa5\x89\x90\x1b\xd8\xa5\xdc\x37\xc8\x67\xd0\x65\x05\xdc\x13\x07\xec\x63\x2c\x29\x08\xdd\x13\xdb\x62\xba\x2f\x57\x35\xbb\x2b\x10\xe7\x80\x88\x45\x58\x81\x65\x7d\xcf\xca\x23\x48\xa1\x3d\xbe\xa1\x66\x26\x38\x55\x33\x9d\x88\x02\xa6\xf6\xf8\x84\x14\x5e\xd1\x41\x09\x62\xd1\x93\x9f\xdc\x05\x97\xd7\x22\x80\x9d\x2f\x46\x08\xcd\xb4\x47\x4e\x24\x86\xd4\x7f\x20\xfc\x08\x71\xd4\xa6\xc2\x34\x20\x0c\xe0\xae\xa3\x17\x46\x4a\x59\xea\xc4\x44\x63\x47\x28\x02\xa1\xf5\xfa\x6d\xed\xa3\x75\xb3\xf6\x43\xd7\xd2\x53\xca\xbd\xfb\xf5\x2e\x31\xcd\xa8\xac\x07\x86\xe1\xf5\xc9\x36\x95\x68\x8a\x0c\x03\xa0\xf6\x79\x8c\xfb\x8f\x77\xf3\xd9\x72\x2c\x02\xb4\xb5\x8f\x1e\xfa\x2e\x5c\x23\x0a\xb7\x12\x04\x68\x5b\x0b\x7d\x56\xf3\x6a\x34\xef\x00\xef\xc6\x1a\xc2\x7f\x69\x13\xc7\x0e\x23\x2b\x19\xde\xa8\xb4\xbd\x19\x1f\x65\x0d\x57\x29\xaf\x3a\x81\x5e\x86\x29\x12\x6d\x0d\x51\x3e\x8f\x30\x02\x87\x71\xb9\x58\xe4\x3f\x44\x79\x24\x6c\xa7\xfb\x9f\xfe\x72\x8d\x03\x36\x6b\x6e\xbe\x77\xdf\x9d\x15\xb1\x82\x7a\xcd\x9b\xdf\x90\xa6\xa9\xa7\xed\x83\xd0\x17\x9b\xd7\x86\xf4\x9f\xe9\xde\x79\x41\xff\x97\x87\x4a\x82\xf4\xfc\xaf\x45\x74\x31\x8a\xb9\x8d\x96\x8d\x16\x56\xef\x39\xe7\xb7\x0f\x60\x54\xe8\xe8\x8b\x8c\x97\xbe\x2a\x8b\xfd\xe9\x08\x3c\xf1\x87\xeb\x12\x5c\x79\x05\x2e\x19\xb1\x02\x8f\x04\x57\x21\x9c\x34\xfe\x4c\x6f\x24\xfb\xe2\x91\xd6\x7f\x05\x65\x41\x49\x15\x2d\xcb\xdd\x98\x05\xdc\x09\xe7\xd1\x45\xee\x8e\xbf\x9b\x15\xa0\x73\x0c\x33\x31\xa5\x9c\x5c\xc5\x51\xaa\x8c\x03\x2f\xac\xad\x5b\x1a\xa5\xab\xf9\xed\x17\x4c\xcf\x89\x99\x80\x0b\x3c\x2e\xb8\x14\x27\x4a\x6f\x84\xa7\xa8\xf6\x18\x21\x8b\xe7\x4a\x53\x5a\x14\x9c\x89\xba\xb0\xce\xf3\x89\xff\x02\x00\x00\xff\xff\x05\x8b\x54\x74\x4f\x0b\x00\x00"), }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/flag-gen/templates/cli_flags_generated.gotpl b/flag-gen/templates/cli_flags_generated.gotpl index 61d06f0..1a95416 100644 --- a/flag-gen/templates/cli_flags_generated.gotpl +++ b/flag-gen/templates/cli_flags_generated.gotpl @@ -60,6 +60,12 @@ func (f {{ $flag.Name }}Flag) GetValue() string { {{ $flag.ValueString }} } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f {{ $flag.Name }}Flag) GetTakesFile() bool { + {{ if eq $flag.TakesFile true }}return f.TakesFile{{ else }}return false{{ end }} +} + // {{ $flag.Name }} looks up the value of a local {{ $flag.Name }}Flag, returns // {{ $flag.ContextDefault }} if not found func (c *Context) {{ $flag.Name }}(name string) {{ if ne .ContextType "" }}{{ $flag.ContextType }}{{ else }}{{ $flag.Type }}{{- end }} { diff --git a/flag.go b/flag.go index be55a33..4aa2fa8 100644 --- a/flag.go +++ b/flag.go @@ -96,6 +96,10 @@ type DocGenerationFlag interface { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. GetValue() string + + // GetTakesFile indicates that the command takes a file as input, which + // will be used for documentation and completion generation purposes. + GetTakesFile() bool } // errorableFlag is an interface that allows us to return errors during apply diff --git a/flag_generated.go b/flag_generated.go index 9dcdfd6..f847835 100644 --- a/flag_generated.go +++ b/flag_generated.go @@ -52,6 +52,12 @@ func (f BoolFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f BoolFlag) GetTakesFile() bool { + return false +} + // Bool looks up the value of a local BoolFlag, returns // false if not found func (c *Context) Bool(name string) bool { @@ -122,6 +128,12 @@ func (f BoolTFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f BoolTFlag) GetTakesFile() bool { + return false +} + // BoolT looks up the value of a local BoolTFlag, returns // false if not found func (c *Context) BoolT(name string) bool { @@ -193,6 +205,12 @@ func (f DurationFlag) GetValue() string { return f.Value.String() } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f DurationFlag) GetTakesFile() bool { + return false +} + // Duration looks up the value of a local DurationFlag, returns // 0 if not found func (c *Context) Duration(name string) time.Duration { @@ -264,6 +282,12 @@ func (f Float64Flag) GetValue() string { return fmt.Sprintf("%f", f.Value) } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f Float64Flag) GetTakesFile() bool { + return false +} + // Float64 looks up the value of a local Float64Flag, returns // 0 if not found func (c *Context) Float64(name string) float64 { @@ -338,6 +362,12 @@ func (f GenericFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f GenericFlag) GetTakesFile() bool { + return f.TakesFile +} + // Generic looks up the value of a local GenericFlag, returns // nil if not found func (c *Context) Generic(name string) interface{} { @@ -409,6 +439,12 @@ func (f Int64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f Int64Flag) GetTakesFile() bool { + return false +} + // Int64 looks up the value of a local Int64Flag, returns // 0 if not found func (c *Context) Int64(name string) int64 { @@ -480,6 +516,12 @@ func (f IntFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f IntFlag) GetTakesFile() bool { + return false +} + // Int looks up the value of a local IntFlag, returns // 0 if not found func (c *Context) Int(name string) int { @@ -553,6 +595,12 @@ func (f IntSliceFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f IntSliceFlag) GetTakesFile() bool { + return false +} + // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found func (c *Context) IntSlice(name string) []int { @@ -626,6 +674,12 @@ func (f Int64SliceFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f Int64SliceFlag) GetTakesFile() bool { + return false +} + // Int64Slice looks up the value of a local Int64SliceFlag, returns // nil if not found func (c *Context) Int64Slice(name string) []int64 { @@ -698,6 +752,12 @@ func (f StringFlag) GetValue() string { return f.Value } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f StringFlag) GetTakesFile() bool { + return f.TakesFile +} + // String looks up the value of a local StringFlag, returns // "" if not found func (c *Context) String(name string) string { @@ -772,6 +832,12 @@ func (f StringSliceFlag) GetValue() string { return "" } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f StringSliceFlag) GetTakesFile() bool { + return f.TakesFile +} + // StringSlice looks up the value of a local StringSliceFlag, returns // nil if not found func (c *Context) StringSlice(name string) []string { @@ -843,6 +909,12 @@ func (f Uint64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f Uint64Flag) GetTakesFile() bool { + return false +} + // Uint64 looks up the value of a local Uint64Flag, returns // 0 if not found func (c *Context) Uint64(name string) uint64 { @@ -914,6 +986,12 @@ func (f UintFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f UintFlag) GetTakesFile() bool { + return false +} + // Uint looks up the value of a local UintFlag, returns // 0 if not found func (c *Context) Uint(name string) uint { diff --git a/testdata/expected-fish-full.fish b/testdata/expected-fish-full.fish index 3538c19..bda0322 100644 --- a/testdata/expected-fish-full.fish +++ b/testdata/expected-fish-full.fish @@ -9,20 +9,20 @@ function __fish_greet_no_subcommand --description 'Test if there has been any su return 0 end -complete -c greet -f -n '__fish_greet_no_subcommand' -l socket -s s -r -d 'some usage text' -complete -c greet -f -n '__fish_greet_no_subcommand' -l flag -s fl -s f -r -complete -c greet -f -n '__fish_greet_no_subcommand' -l another-flag -s b -d 'another usage text' -complete -c greet -f -n '__fish_greet_no_subcommand' -l help -s h -d 'show help' -complete -c greet -f -n '__fish_greet_no_subcommand' -l version -s v -d 'print the version' -complete -c greet -f -n '__fish_seen_subcommand_from config c' -l help -s h -d 'show help' -complete -c greet -f -n '__fish_greet_no_subcommand' -a 'config c' -d 'another usage test' -complete -c greet -f -n '__fish_seen_subcommand_from config c' -l flag -s fl -s f -r -complete -c greet -f -n '__fish_seen_subcommand_from config c' -l another-flag -s b -d 'another usage text' -complete -c greet -f -n '__fish_seen_subcommand_from sub-config s ss' -l help -s h -d 'show help' -complete -c greet -f -n '__fish_seen_subcommand_from config c' -a 'sub-config s ss' -d 'another usage test' -complete -c greet -f -n '__fish_seen_subcommand_from sub-config s ss' -l sub-flag -s sub-fl -s s -r -complete -c greet -f -n '__fish_seen_subcommand_from sub-config s ss' -l sub-command-flag -s s -d 'some usage text' -complete -c greet -f -n '__fish_seen_subcommand_from info i in' -l help -s h -d 'show help' -complete -c greet -f -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information' -complete -c greet -f -n '__fish_seen_subcommand_from some-command' -l help -s h -d 'show help' -complete -c greet -f -n '__fish_greet_no_subcommand' -a 'some-command' +complete -c greet -n '__fish_greet_no_subcommand' -l socket -s s -r -d 'some usage text' +complete -c greet -n '__fish_greet_no_subcommand' -f -l flag -s fl -s f -r +complete -c greet -n '__fish_greet_no_subcommand' -f -l another-flag -s b -d 'another usage text' +complete -c greet -n '__fish_greet_no_subcommand' -f -l help -s h -d 'show help' +complete -c greet -n '__fish_greet_no_subcommand' -f -l version -s v -d 'print the version' +complete -c greet -n '__fish_seen_subcommand_from config c' -f -l help -s h -d 'show help' +complete -r -c greet -n '__fish_greet_no_subcommand' -a 'config c' -d 'another usage test' +complete -c greet -n '__fish_seen_subcommand_from config c' -l flag -s fl -s f -r +complete -c greet -n '__fish_seen_subcommand_from config c' -f -l another-flag -s b -d 'another usage text' +complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l help -s h -d 'show help' +complete -r -c greet -n '__fish_seen_subcommand_from config c' -a 'sub-config s ss' -d 'another usage test' +complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-flag -s sub-fl -s s -r +complete -c greet -n '__fish_seen_subcommand_from sub-config s ss' -f -l sub-command-flag -s s -d 'some usage text' +complete -c greet -n '__fish_seen_subcommand_from info i in' -f -l help -s h -d 'show help' +complete -r -c greet -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information' +complete -c greet -n '__fish_seen_subcommand_from some-command' -f -l help -s h -d 'show help' +complete -r -c greet -n '__fish_greet_no_subcommand' -a 'some-command' From 38d0ac629677a7fbf08a52e17fec73894bb31263 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Sun, 25 Aug 2019 17:50:18 +0200 Subject: [PATCH 2/5] Removed GetTakesFile and stick to type assertions Signed-off-by: Sascha Grunert --- fish.go | 25 ++++++- flag-gen/assets_vfsdata.go | 4 +- flag-gen/templates/cli_flags_generated.gotpl | 6 -- flag.go | 4 - flag_generated.go | 78 -------------------- 5 files changed, 23 insertions(+), 94 deletions(-) diff --git a/fish.go b/fish.go index d286881..922b924 100644 --- a/fish.go +++ b/fish.go @@ -124,16 +124,14 @@ func (a *App) prepareFishFlags( continue } - var completion strings.Builder + completion := &strings.Builder{} completion.WriteString(fmt.Sprintf( "complete -c %s -n '%s'", a.Name, a.fishSubcommandHelper(previousCommands), )) - if !flag.GetTakesFile() { - completion.WriteString(" -f") - } + fishAddFileFlag(f, completion) for idx, opt := range strings.Split(flag.GetName(), ",") { if idx == 0 { @@ -162,6 +160,25 @@ func (a *App) prepareFishFlags( return completions } +func fishAddFileFlag( + flag Flag, + completion *strings.Builder, +) { + addFileExclusionFlag := true + if f, ok := flag.(GenericFlag); ok && f.TakesFile { + addFileExclusionFlag = false + } + if f, ok := flag.(StringFlag); ok && f.TakesFile { + addFileExclusionFlag = false + } + if f, ok := flag.(StringSliceFlag); ok && f.TakesFile { + addFileExclusionFlag = false + } + if addFileExclusionFlag { + completion.WriteString(" -f") + } +} + func (a *App) fishSubcommandHelper(allCommands []string) string { fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name) if len(allCommands) > 0 { diff --git a/flag-gen/assets_vfsdata.go b/flag-gen/assets_vfsdata.go index 7e7d01b..ab600d9 100644 --- a/flag-gen/assets_vfsdata.go +++ b/flag-gen/assets_vfsdata.go @@ -46,9 +46,9 @@ var assets = func() http.FileSystem { "/templates/cli_flags_generated.gotpl": &vfsgen۰CompressedFileInfo{ name: "cli_flags_generated.gotpl", modTime: time.Time{}, - uncompressedSize: 2895, + uncompressedSize: 2638, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x56\x4d\x6f\xdb\x38\x10\x3d\x4b\xbf\x62\xd6\xe8\xc1\x0a\xbc\xce\x7d\x8b\x9e\xe2\xa6\x5b\x60\xd1\x06\xdb\x6c\xef\x8c\x34\x94\x89\xd0\xa4\x4a\x8e\x92\x0d\x04\xff\xf7\xc5\x90\x94\x44\x7f\x20\xf1\xa5\x8b\x9e\x22\x72\x86\xef\x3d\xbe\x19\x8e\x73\x7d\x0d\x37\xb6\x41\x68\xd1\xa0\x13\x84\x0d\x3c\xbc\x80\x6c\xdf\xc3\xe6\x2b\x7c\xf9\x7a\x0f\x1f\x37\x9f\xef\xd7\x65\xd9\x89\xfa\x51\xb4\x08\xc3\x00\xeb\xbb\xf8\xfd\x45\xec\x10\xf6\xfb\xb2\x54\xbb\xce\x3a\x82\x65\x59\x2c\xa4\x16\xed\x82\xff\xee\x88\xff\x78\x72\xb5\x35\x4f\xfc\x49\x6a\x87\x8b\xb2\x2a\x87\x01\x9c\x30\x2d\xc2\x3b\xb5\x82\x77\x9c\x0f\x7f\x7c\x80\xf5\xad\x16\xad\x67\xb4\xeb\x6b\xe6\x08\x81\x75\x62\xe0\x18\x28\x0f\x02\x42\xfa\xb3\xa2\x2d\xd0\x4b\x87\x73\xe2\x3d\xaf\xf6\xfb\x69\xbd\xb1\x35\x09\xa5\x19\xef\x30\x31\x47\xf4\xe4\xfa\x9a\x60\x28\x0b\xde\x2d\x0a\x4f\x4e\x99\xb6\x2c\xfe\xf1\xa2\xcd\x96\x1f\xcd\xd3\x77\xe1\xe6\xf5\xad\xd2\x78\x27\x68\x3b\x6d\xfc\x8d\x3f\x7a\xe5\xb0\x29\x1e\xac\xd5\x65\xf1\xa7\x6a\x1a\x34\x45\x5a\x0d\xc3\xef\xa0\x24\xe0\x8f\x51\xa9\x78\x44\xcf\x10\x40\xae\x0f\xf6\x15\xd3\x56\x76\x04\x4d\x13\x62\xc7\xc7\xbf\x0b\xdd\x67\x47\xc3\xb2\x38\xb6\xe1\x75\x88\x0d\x7a\x52\x46\x90\xb2\x66\x06\xca\x36\x8b\xab\x57\xf1\xf6\x25\x97\xe8\x5b\xb8\x3b\x38\xa4\xde\x19\xae\x8c\x43\xd1\x88\x07\x8d\xe0\xb0\x73\xe8\xd1\x50\x64\xb0\x12\x68\xab\x3c\x3c\xb1\x52\x3e\xb9\x94\xd6\x41\xcf\x16\x43\x83\x52\xf4\x9a\x7c\x55\xca\xde\xd4\xb0\x94\x67\xeb\x54\x25\xb2\x65\x05\xd1\x71\xae\x58\x24\x06\x8e\xc7\x28\xba\xa5\xac\x92\xb8\x4f\x48\xe1\xfc\xa8\x8e\xb6\x08\x86\x37\x82\x18\x0c\x5d\xf4\x06\x65\x82\x38\xc7\x29\x43\x66\xa2\xfa\xec\xc7\xea\x4f\x6c\xcf\x5b\xa4\x2d\x3a\xb0\x0e\x8c\xa5\x89\x90\x1b\xd8\xa5\xdc\x37\xc8\x67\xd0\x65\x05\xdc\x13\x07\xec\x63\x2c\x29\x08\xdd\x13\xdb\x62\xba\x2f\x57\x35\xbb\x2b\x10\xe7\x80\x88\x45\x58\x81\x65\x7d\xcf\xca\x23\x48\xa1\x3d\xbe\xa1\x66\x26\x38\x55\x33\x9d\x88\x02\xa6\xf6\xf8\x84\x14\x5e\xd1\x41\x09\x62\xd1\x93\x9f\xdc\x05\x97\xd7\x22\x80\x9d\x2f\x46\x08\xcd\xb4\x47\x4e\x24\x86\xd4\x7f\x20\xfc\x08\x71\xd4\xa6\xc2\x34\x20\x0c\xe0\xae\xa3\x17\x46\x4a\x59\xea\xc4\x44\x63\x47\x28\x02\xa1\xf5\xfa\x6d\xed\xa3\x75\xb3\xf6\x43\xd7\xd2\x53\xca\xbd\xfb\xf5\x2e\x31\xcd\xa8\xac\x07\x86\xe1\xf5\xc9\x36\x95\x68\x8a\x0c\x03\xa0\xf6\x79\x8c\xfb\x8f\x77\xf3\xd9\x72\x2c\x02\xb4\xb5\x8f\x1e\xfa\x2e\x5c\x23\x0a\xb7\x12\x04\x68\x5b\x0b\x7d\x56\xf3\x6a\x34\xef\x00\xef\xc6\x1a\xc2\x7f\x69\x13\xc7\x0e\x23\x2b\x19\xde\xa8\xb4\xbd\x19\x1f\x65\x0d\x57\x29\xaf\x3a\x81\x5e\x86\x29\x12\x6d\x0d\x51\x3e\x8f\x30\x02\x87\x71\xb9\x58\xe4\x3f\x44\x79\x24\x6c\xa7\xfb\x9f\xfe\x72\x8d\x03\x36\x6b\x6e\xbe\x77\xdf\x9d\x15\xb1\x82\x7a\xcd\x9b\xdf\x90\xa6\xa9\xa7\xed\x83\xd0\x17\x9b\xd7\x86\xf4\x9f\xe9\xde\x79\x41\xff\x97\x87\x4a\x82\xf4\xfc\xaf\x45\x74\x31\x8a\xb9\x8d\x96\x8d\x16\x56\xef\x39\xe7\xb7\x0f\x60\x54\xe8\xe8\x8b\x8c\x97\xbe\x2a\x8b\xfd\xe9\x08\x3c\xf1\x87\xeb\x12\x5c\x79\x05\x2e\x19\xb1\x02\x8f\x04\x57\x21\x9c\x34\xfe\x4c\x6f\x24\xfb\xe2\x91\xd6\x7f\x05\x65\x41\x49\x15\x2d\xcb\xdd\x98\x05\xdc\x09\xe7\xd1\x45\xee\x8e\xbf\x9b\x15\xa0\x73\x0c\x33\x31\xa5\x9c\x5c\xc5\x51\xaa\x8c\x03\x2f\xac\xad\x5b\x1a\xa5\xab\xf9\xed\x17\x4c\xcf\x89\x99\x80\x0b\x3c\x2e\xb8\x14\x27\x4a\x6f\x84\xa7\xa8\xf6\x18\x21\x8b\xe7\x4a\x53\x5a\x14\x9c\x89\xba\xb0\xce\xf3\x89\xff\x02\x00\x00\xff\xff\x05\x8b\x54\x74\x4f\x0b\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x55\x4d\x6f\xe3\x36\x10\x3d\x4b\xbf\x62\x6a\xec\x41\x0a\x5c\xfb\xde\xc5\x9e\xe2\xcd\x76\x81\x62\x37\xe8\xa6\xb9\xd3\xd2\x50\x26\x42\x93\x0a\x39\x4a\x1a\x18\xfe\xef\xc5\x90\xd4\x87\x3f\x10\xfb\x92\x9e\x2c\x72\x66\xde\x7b\x7c\x33\xa4\x97\x4b\xb8\xb5\x35\x42\x83\x06\x9d\x20\xac\x61\xfd\x06\xb2\xf9\x0c\xab\x9f\xf0\xe3\xe7\x03\x7c\x5d\x7d\x7f\x58\xe4\x79\x2b\xaa\x27\xd1\x20\xec\x76\xb0\xb8\x8f\xdf\x3f\xc4\x16\x61\xbf\xcf\x73\xb5\x6d\xad\x23\x28\xf2\x6c\x26\xb5\x68\x66\xfc\xbb\x25\xfe\xf1\xe4\x2a\x6b\x5e\xf8\x93\xd4\x16\x67\x79\x99\xef\x76\xe0\x84\x69\x10\x3e\xa9\x39\x7c\xe2\x7c\xf8\xe3\x0b\x2c\xee\xb4\x68\x3c\xa3\x2d\x97\xcc\x11\x02\x8b\xc4\xc0\x31\x50\x1e\x04\x84\xf4\x57\x45\x1b\xa0\xb7\x16\xc7\xc4\x07\x5e\xed\xf7\xc3\x7a\x65\x2b\x12\x4a\x33\xde\x61\xe2\x14\xd1\x93\xeb\x2a\x82\x5d\x9e\xf1\x6e\x96\x79\x72\xca\x34\x79\xf6\x8f\x17\xcd\x64\xf9\xd5\xbc\x3c\x0a\x37\xae\xef\x94\xc6\x7b\x41\x9b\x61\xe3\x6f\x7c\xee\x94\xc3\x3a\x5b\x5b\xab\xf3\xec\x4f\x55\xd7\x68\xb2\xb4\xda\xed\x7e\x07\x25\x01\x9f\x7b\xa5\xe2\x09\x3d\x43\x00\xb9\x2e\xd8\x97\x0d\x5b\x93\x12\x34\x75\x88\x1d\x97\x3f\x0a\xdd\x4d\x4a\xc3\x32\x3b\xb6\xe1\x7d\x88\x15\x7a\x52\x46\x90\xb2\x66\x04\x9a\x6c\x66\x37\xef\xe2\xed\x73\x6e\xd1\xaf\x70\x76\x70\x48\x9d\x33\xdc\x19\x87\xa2\x16\x6b\x8d\xe0\xb0\x75\xe8\xd1\x50\x64\xb0\x12\x68\xa3\x3c\xbc\xb0\x52\xae\x2c\xa4\x75\xd0\xb1\xc5\x50\xa3\x14\x9d\x26\x5f\xe6\xb2\x33\x15\x14\xf2\x6c\x9f\xca\x44\x56\x94\x10\x1d\xe7\x8e\x45\x62\xe0\x78\x8c\xa2\x2b\x64\x99\xc4\x7d\x43\x0a\xf5\xbd\x3a\xda\x20\x18\xde\x08\x62\x30\x4c\xd1\x05\xca\x04\x71\x8e\x53\x86\xcc\x44\xf5\xdd\xf7\xdd\x1f\xd8\x5e\x37\x48\x1b\x74\x60\x1d\x18\x4b\x03\x21\x0f\xb0\x4b\xb9\x17\xc8\x47\xd0\xa2\x04\x9e\x89\x03\xf6\x3e\x96\x14\x84\xe9\x89\x63\x31\x9c\x97\xbb\x3a\x39\x2b\x10\xe7\x80\x88\x4d\x98\x83\x65\x7d\xaf\xca\x23\x48\xa1\x3d\x5e\x50\x33\x12\x9c\xaa\x19\x2a\xa2\x80\x61\x3c\xbe\x21\x85\x5b\x74\xd0\x82\xd8\xf4\xe4\x27\x4f\xc1\xf5\xbd\x08\x60\xe7\x9b\x11\x42\x23\xed\x91\x13\x89\x21\xcd\x1f\x08\xdf\x43\x1c\x8d\xa9\x30\x35\x08\x03\xb8\x6d\xe9\x8d\x91\x52\x96\x3a\x31\xd1\xd8\x1e\x8a\x40\x68\xbd\xb8\xac\xbd\xb7\x6e\xd4\x7e\xe8\x5a\xba\x4a\x83\x77\xc7\x40\xa0\xad\x7d\xf2\xd0\xb5\x41\x4a\x24\xb7\x12\x04\x68\x5b\x09\x7d\x96\x77\xde\x1b\x70\x80\x77\x6b\x0d\xe1\xbf\xb4\x8a\xb7\x8e\x91\x95\x0c\x23\x2a\x6d\x67\xfa\x99\xac\xe0\x26\xe5\x95\x27\xd0\x45\xb8\x44\xf1\x1c\x21\xca\xf5\x08\x3d\x70\x78\x2d\x66\xb3\xe9\x3b\x3c\x8d\x84\x6d\xd4\xfe\xe0\xa1\x1e\x22\xfd\xfb\x32\xe9\x2d\x9f\xbb\x6b\xcf\x8a\x98\x43\xb5\xe0\xcd\x5f\x48\xc3\xa5\xd7\x76\x2d\xf4\xd5\xe6\x35\x21\xfd\x23\xdd\x3b\x2f\xe8\xff\xf2\x50\x49\x90\x9e\xff\x59\xa3\x8b\x51\xcc\x5d\xb4\xac\xb7\xb0\xfc\xcc\x39\xbf\x7d\x01\xa3\xc2\xa5\xbe\xca\x78\xe9\xcb\x3c\xdb\x9f\xbe\x00\x27\xfe\x70\x5f\x82\x2b\xef\xc0\x25\x23\xe6\xe0\x91\xe0\x26\x84\x93\xc6\x8f\xf4\x46\xb2\x2f\x1e\x69\xf1\x57\x50\x16\x94\x94\xd1\xb2\xa9\x1b\xa3\x80\x7b\xe1\x3c\xba\xc8\xdd\xf2\x77\x3d\x07\x74\x8e\x61\x06\xa6\x94\x33\x55\x71\x94\x2a\xe3\x7d\x0f\x6b\xeb\x0a\xa3\x74\xc9\xb9\xe9\x6f\x9a\xe9\x39\x71\x22\xe0\x0a\x8f\x33\x6e\xc5\x89\xd2\x5b\xe1\x29\xaa\x3d\x46\x98\xc4\xa7\x4a\x53\x5a\x14\x3c\x11\x75\x65\x9f\xc7\x8a\xff\x02\x00\x00\xff\xff\x73\xc9\x52\x5f\x4e\x0a\x00\x00"), }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/flag-gen/templates/cli_flags_generated.gotpl b/flag-gen/templates/cli_flags_generated.gotpl index 1a95416..61d06f0 100644 --- a/flag-gen/templates/cli_flags_generated.gotpl +++ b/flag-gen/templates/cli_flags_generated.gotpl @@ -60,12 +60,6 @@ func (f {{ $flag.Name }}Flag) GetValue() string { {{ $flag.ValueString }} } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f {{ $flag.Name }}Flag) GetTakesFile() bool { - {{ if eq $flag.TakesFile true }}return f.TakesFile{{ else }}return false{{ end }} -} - // {{ $flag.Name }} looks up the value of a local {{ $flag.Name }}Flag, returns // {{ $flag.ContextDefault }} if not found func (c *Context) {{ $flag.Name }}(name string) {{ if ne .ContextType "" }}{{ $flag.ContextType }}{{ else }}{{ $flag.Type }}{{- end }} { diff --git a/flag.go b/flag.go index 4aa2fa8..be55a33 100644 --- a/flag.go +++ b/flag.go @@ -96,10 +96,6 @@ type DocGenerationFlag interface { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. GetValue() string - - // GetTakesFile indicates that the command takes a file as input, which - // will be used for documentation and completion generation purposes. - GetTakesFile() bool } // errorableFlag is an interface that allows us to return errors during apply diff --git a/flag_generated.go b/flag_generated.go index f847835..9dcdfd6 100644 --- a/flag_generated.go +++ b/flag_generated.go @@ -52,12 +52,6 @@ func (f BoolFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f BoolFlag) GetTakesFile() bool { - return false -} - // Bool looks up the value of a local BoolFlag, returns // false if not found func (c *Context) Bool(name string) bool { @@ -128,12 +122,6 @@ func (f BoolTFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f BoolTFlag) GetTakesFile() bool { - return false -} - // BoolT looks up the value of a local BoolTFlag, returns // false if not found func (c *Context) BoolT(name string) bool { @@ -205,12 +193,6 @@ func (f DurationFlag) GetValue() string { return f.Value.String() } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f DurationFlag) GetTakesFile() bool { - return false -} - // Duration looks up the value of a local DurationFlag, returns // 0 if not found func (c *Context) Duration(name string) time.Duration { @@ -282,12 +264,6 @@ func (f Float64Flag) GetValue() string { return fmt.Sprintf("%f", f.Value) } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Float64Flag) GetTakesFile() bool { - return false -} - // Float64 looks up the value of a local Float64Flag, returns // 0 if not found func (c *Context) Float64(name string) float64 { @@ -362,12 +338,6 @@ func (f GenericFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f GenericFlag) GetTakesFile() bool { - return f.TakesFile -} - // Generic looks up the value of a local GenericFlag, returns // nil if not found func (c *Context) Generic(name string) interface{} { @@ -439,12 +409,6 @@ func (f Int64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Int64Flag) GetTakesFile() bool { - return false -} - // Int64 looks up the value of a local Int64Flag, returns // 0 if not found func (c *Context) Int64(name string) int64 { @@ -516,12 +480,6 @@ func (f IntFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f IntFlag) GetTakesFile() bool { - return false -} - // Int looks up the value of a local IntFlag, returns // 0 if not found func (c *Context) Int(name string) int { @@ -595,12 +553,6 @@ func (f IntSliceFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f IntSliceFlag) GetTakesFile() bool { - return false -} - // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found func (c *Context) IntSlice(name string) []int { @@ -674,12 +626,6 @@ func (f Int64SliceFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Int64SliceFlag) GetTakesFile() bool { - return false -} - // Int64Slice looks up the value of a local Int64SliceFlag, returns // nil if not found func (c *Context) Int64Slice(name string) []int64 { @@ -752,12 +698,6 @@ func (f StringFlag) GetValue() string { return f.Value } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f StringFlag) GetTakesFile() bool { - return f.TakesFile -} - // String looks up the value of a local StringFlag, returns // "" if not found func (c *Context) String(name string) string { @@ -832,12 +772,6 @@ func (f StringSliceFlag) GetValue() string { return "" } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f StringSliceFlag) GetTakesFile() bool { - return f.TakesFile -} - // StringSlice looks up the value of a local StringSliceFlag, returns // nil if not found func (c *Context) StringSlice(name string) []string { @@ -909,12 +843,6 @@ func (f Uint64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Uint64Flag) GetTakesFile() bool { - return false -} - // Uint64 looks up the value of a local Uint64Flag, returns // 0 if not found func (c *Context) Uint64(name string) uint64 { @@ -986,12 +914,6 @@ func (f UintFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f UintFlag) GetTakesFile() bool { - return false -} - // Uint looks up the value of a local UintFlag, returns // 0 if not found func (c *Context) Uint(name string) uint { From 0c01922a12c501867cad200bc4b36a25f9a073e0 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Mon, 26 Aug 2019 08:46:55 +0200 Subject: [PATCH 3/5] Add type switch Signed-off-by: Sascha Grunert --- fish.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/fish.go b/fish.go index 922b924..e6c6d84 100644 --- a/fish.go +++ b/fish.go @@ -164,19 +164,21 @@ func fishAddFileFlag( flag Flag, completion *strings.Builder, ) { - addFileExclusionFlag := true - if f, ok := flag.(GenericFlag); ok && f.TakesFile { - addFileExclusionFlag = false - } - if f, ok := flag.(StringFlag); ok && f.TakesFile { - addFileExclusionFlag = false - } - if f, ok := flag.(StringSliceFlag); ok && f.TakesFile { - addFileExclusionFlag = false - } - if addFileExclusionFlag { - completion.WriteString(" -f") + switch f := flag.(type) { + case GenericFlag: + if f.TakesFile { + return + } + case StringFlag: + if f.TakesFile { + return + } + case StringSliceFlag: + if f.TakesFile { + return + } } + completion.WriteString(" -f") } func (a *App) fishSubcommandHelper(allCommands []string) string { From 687f721eaa40859950820b37b9ad1fcd85b7da9f Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Mon, 26 Aug 2019 10:07:50 +0200 Subject: [PATCH 4/5] Update function alignment Signed-off-by: Sascha Grunert --- fish.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/fish.go b/fish.go index e6c6d84..166435c 100644 --- a/fish.go +++ b/fish.go @@ -64,11 +64,7 @@ func (a *App) writeFishCompletionTemplate(w io.Writer) error { }) } -func (a *App) prepareFishCommands( - commands []Command, - allCommands *[]string, - previousCommands []string, -) []string { +func (a *App) prepareFishCommands(commands []Command, allCommands *[]string, previousCommands []string) []string { completions := []string{} for i := range commands { command := &commands[i] @@ -113,10 +109,7 @@ func (a *App) prepareFishCommands( return completions } -func (a *App) prepareFishFlags( - flags []Flag, - previousCommands []string, -) []string { +func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { completions := []string{} for _, f := range flags { flag, ok := f.(DocGenerationFlag) @@ -160,10 +153,7 @@ func (a *App) prepareFishFlags( return completions } -func fishAddFileFlag( - flag Flag, - completion *strings.Builder, -) { +func fishAddFileFlag(flag Flag, completion *strings.Builder) { switch f := flag.(type) { case GenericFlag: if f.TakesFile { From 4bbff841690954ed86c147147151c0144dcf1765 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Thu, 29 Aug 2019 14:45:32 +0200 Subject: [PATCH 5/5] Escape single quotes in fish shell completion Single quotes can break the generated fish shell completion and should be escaped correctly. Signed-off-by: Sascha Grunert --- docs_test.go | 2 +- fish.go | 10 ++++++++-- testdata/expected-doc-full.man | 2 +- testdata/expected-doc-full.md | 2 +- testdata/expected-doc-no-commands.md | 2 +- testdata/expected-fish-full.fish | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs_test.go b/docs_test.go index 25afd23..6ffc995 100644 --- a/docs_test.go +++ b/docs_test.go @@ -11,7 +11,7 @@ func testApp() *App { app.Flags = []Flag{ StringFlag{ Name: "socket, s", - Usage: "some usage text", + Usage: "some 'usage' text", Value: "value", TakesFile: true, }, diff --git a/fish.go b/fish.go index 166435c..1121a20 100644 --- a/fish.go +++ b/fish.go @@ -78,7 +78,8 @@ func (a *App) prepareFishCommands(commands []Command, allCommands *[]string, pre )) if command.Usage != "" { - completion.WriteString(fmt.Sprintf(" -d '%s'", command.Usage)) + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(command.Usage))) } if !command.HideHelp { @@ -144,7 +145,8 @@ func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string } if flag.GetUsage() != "" { - completion.WriteString(fmt.Sprintf(" -d '%s'", flag.GetUsage())) + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(flag.GetUsage()))) } completions = append(completions, completion.String()) @@ -182,3 +184,7 @@ func (a *App) fishSubcommandHelper(allCommands []string) string { return fishHelper } + +func escapeSingleQuotes(input string) string { + return strings.Replace(input, `'`, `\'`, -1) +} diff --git a/testdata/expected-doc-full.man b/testdata/expected-doc-full.man index a2d0e6d..5190698 100644 --- a/testdata/expected-doc-full.man +++ b/testdata/expected-doc-full.man @@ -49,7 +49,7 @@ greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] \fB\-\-flag, \-\-fl, \-f\fP="": .PP -\fB\-\-socket, \-s\fP="": some usage text (default: value) +\fB\-\-socket, \-s\fP="": some 'usage' text (default: value) .SH COMMANDS diff --git a/testdata/expected-doc-full.md b/testdata/expected-doc-full.md index 8fb9f58..23d7c23 100644 --- a/testdata/expected-doc-full.md +++ b/testdata/expected-doc-full.md @@ -32,7 +32,7 @@ greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] **--flag, --fl, -f**="": -**--socket, -s**="": some usage text (default: value) +**--socket, -s**="": some 'usage' text (default: value) # COMMANDS diff --git a/testdata/expected-doc-no-commands.md b/testdata/expected-doc-no-commands.md index dba7bb0..18d8e35 100644 --- a/testdata/expected-doc-no-commands.md +++ b/testdata/expected-doc-no-commands.md @@ -32,5 +32,5 @@ greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] **--flag, --fl, -f**="": -**--socket, -s**="": some usage text (default: value) +**--socket, -s**="": some 'usage' text (default: value) diff --git a/testdata/expected-fish-full.fish b/testdata/expected-fish-full.fish index bda0322..b18d51e 100644 --- a/testdata/expected-fish-full.fish +++ b/testdata/expected-fish-full.fish @@ -9,7 +9,7 @@ function __fish_greet_no_subcommand --description 'Test if there has been any su return 0 end -complete -c greet -n '__fish_greet_no_subcommand' -l socket -s s -r -d 'some usage text' +complete -c greet -n '__fish_greet_no_subcommand' -l socket -s s -r -d 'some \'usage\' text' complete -c greet -n '__fish_greet_no_subcommand' -f -l flag -s fl -s f -r complete -c greet -n '__fish_greet_no_subcommand' -f -l another-flag -s b -d 'another usage text' complete -c greet -n '__fish_greet_no_subcommand' -f -l help -s h -d 'show help'