diff --git a/action.go b/action.go index eba672261..865e9a79f 100644 --- a/action.go +++ b/action.go @@ -452,6 +452,16 @@ func (a Action) UniqueListF(divider string, f func(s string) string) Action { }) } +// Unless skips invokation if given condition succeeds. +func (a Action) Unless(condition func(c Context) bool) Action { + return ActionCallback(func(c Context) Action { + if condition(c) { + return ActionValues() + } + return a + }) +} + // Usage sets the usage. func (a Action) Usage(usage string, args ...interface{}) Action { return a.UsageF(func() string { diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 6f943bfd9..f37b39099 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -43,6 +43,7 @@ - [Timeout](./carapace/action/timeout.md) - [UniqueList](./carapace/action/uniqueList.md) - [UniqueListF](./carapace/action/uniqueListF.md) + - [Unless](./carapace/action/unless.md) - [Usage](./carapace/action/usage.md) - [UsageF](./carapace/action/usageF.md) - [InvokedAction](./carapace/invokedAction.md) diff --git a/docs/src/carapace/action/unless.cast b/docs/src/carapace/action/unless.cast new file mode 100644 index 000000000..6330283ea --- /dev/null +++ b/docs/src/carapace/action/unless.cast @@ -0,0 +1,60 @@ +{"version": 2, "width": 108, "height": 24, "timestamp": 1704580675, "env": {"SHELL": "elvish", "TERM": "tmux-256color"}} +[0.077611, "o", "\u001b[?7h\u001b[7m⏎\u001b[m \r \r\u001b[?7l\u001b[?2004h"] +[0.078303, "o", "\u001b[?25l\r???> ???> \r\u001b[5C\u001b[?25h\u001b[?25l\r\u001b[5C\u001b[K\r\u001b[5C\u001b[?25h"] +[0.092405, "o", "\u001b[?25l\r\r\u001b[5C\u001b[?25h"] +[0.092532, "o", "\u001b[?25l\r\u001b[K\u001b[0;1;36m~\u001b[0;m \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \r\u001b[6C\u001b[?25h"] +[0.501527, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[0;32me\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[7C\u001b[?25h"] +[0.502665, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[7C\u001b[?25h"] +[0.514318, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[7C\u001b[?25h"] +[0.514567, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[7C\u001b[?25h"] +[0.729453, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;31mex\u001b[0;m\r\u001b[8C\u001b[?25h"] +[0.934243, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;32mexa\u001b[0;m\r\u001b[9C\u001b[?25h"] +[0.934401, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[9C\u001b[?25h"] +[0.935079, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[9C\u001b[?25h"] +[1.078257, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;31mexam\u001b[0;m\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[10C\u001b[?25h"] +[1.130292, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[10C\u001b[0;31mp\u001b[0;m\r\u001b[11C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[11C\u001b[?25h"] +[1.277002, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[11C\u001b[0;31ml\u001b[0;m\r\u001b[12C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[12C\u001b[?25h"] +[1.319499, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;32mexample\u001b[0;m\r\u001b[13C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[13C\u001b[?25h"] +[1.392949, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[13C \r\u001b[14C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[14C\u001b[?25h"] +[1.931041, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[14C\u001b[0;4maction \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;34maction\u001b[0;2;7m (action example) \r\n\u001b[0;34malias\u001b[0;2m (action example) \r\n\u001b[0;mchain\u001b[0;2m (shorthand chain) \r\n\u001b[0;mcompat \r\ncompletion\u001b[0;2m (Generate the autocompletion script for the specified shell)\r\n\u001b[0;34mflag\u001b[0;2m (flag example) \r\n\u001b[0;mgroup\u001b[0;2m (group example) \r\n\u001b[0;mhelp\u001b[0;2m (Help about any command) \r\n\u001b[0;minterspersed\u001b[0;2m (interspersed example) \r\n\u001b[0;33mmodifier\u001b[0;2m (modifier example) \r\n\u001b[0;mmultiparts\u001b[0;2m (multiparts example) \r\n\u001b[0;35mplugin\u001b[0;2m (dynamic plugin command) \r\n\u001b[0;mspecial \r\nsubcommand\u001b[0;2m (subcommand example) \u001b[0;m\u001b[14A\r\u001b[22C\u001b[?25h"] +[2.258815, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[22Cm\r\n\r\n\r\n\u001b[1C\u001b[Kompat \r\n\u001b[4C\u001b[Kletion\u001b[0;2m (Generate the autocompletion script for the specified shell)\r\n\u001b[0;m\u001b[K\u001b[0;34mflag\u001b[0;2m (flag example) \r\n\u001b[0;m\u001b[Kgroup\u001b[0;2m (group example) \r\n\u001b[0;m\u001b[Khelp\u001b[0;2m (Help about any command) \r\n\u001b[0;m\u001b[Kinterspersed\u001b[0;2m (interspersed example) \r\n\u001b[0;m\u001b[K\u001b[0;33mmodifier\u001b[0;2m (modifier example) \r\n\u001b[0;m\u001b[Kmultiparts\u001b[0;2m (multiparts example) \r\n\u001b[0;m\u001b[K\u001b[0;35mplugin\u001b[0;2m (dynamic plugin command) \r\n\u001b[0;m\u001b[Ksubcommand\u001b[0;2m (subcommand example) \u001b[0;m\r\n\u001b[J\u001b[A\u001b[12A\r\u001b[23C\u001b[?25h"] +[2.259838, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[12A\r\u001b[23C\u001b[?25h"] +[2.330185, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[14C\u001b[K\u001b[0;4mmodifier \r\n\u001b[23C\u001b[0;mo\r\n\u001b[K\u001b[0;7;33mmodifier\u001b[0;2;7m (modifier example)\u001b[0;m\r\n\u001b[J\u001b[A\u001b[1A\r\u001b[24C\u001b[?25h"] +[2.333674, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[24C\u001b[?25h"] +[2.333998, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[24C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[24C\u001b[?25h"] +[2.450807, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[24Cd\r\n\u001b[1A\r\u001b[25C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[25C\u001b[?25h"] +[2.911046, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[14C\u001b[Kmodifier \r\n\u001b[J\u001b[A\r\u001b[23C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[23C\u001b[?25h"] +[3.501728, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[23C-\r\u001b[24C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[24C\u001b[?25h"] +[3.63236, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[24C-\r\u001b[25C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[25C\u001b[?25h"] +[3.755864, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[23C\u001b[K\u001b[0;4m--batch \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;34m--batch\u001b[0;2;7m (Batch()) \u001b[0;m \u001b[0;34m--retain\u001b[0;2m (Retain()) \r\n\u001b[0;34m--cache\u001b[0;2m (Cache()) \u001b[0;m \u001b[0;34m--shift\u001b[0;2m (Shift()) \r\n\u001b[0;34m--cache-key\u001b[0;2m (Cache()) \u001b[0;m \u001b[0;34m--split\u001b[0;2m (Split()) \r\n\u001b[0;34m--chdir\u001b[0;2m (Chdir()) \u001b[0;m \u001b[0;34m--splitp\u001b[0;2m (SplitP()) \r\n\u001b[0;34m--chdirf\u001b[0;2m (ChdirF()) \u001b[0;m \u001b[0;34m--style\u001b[0;2m (Style()) \r\n\u001b[0;34m--filter\u001b[0;2m (Filter()) \u001b[0;m \u001b[0;34m--stylef\u001b[0;2m (StyleF()) \r\n\u001b[0;34m--filterargs\u001b[0;2m (FilterArgs()) \u001b[0;m \u001b[0;34m--styler\u001b[0;2m (StyleR()) \r\n\u001b[0;34m--filterparts\u001b[0;2m (FilterParts()) \u001b[0;m \u001b[0;34m--suffix\u001b[0;2m (Suffix()) \r\n\u001b[0;m--help\u001b[0;2m (help for modifier) \u001b[0;m \u001b[0;34m--suppress\u001b[0;2m (Suppress()) \r\n\u001b[0;34m--invoke\u001b[0;2m (Invoke()) \u001b[0;m \u001b[0;34m--tag\u001b[0;2m (Tag()) \r\n\u001b[0;34m--list\u001b[0;2m (List()) \u001b[0;m \u001b[0;34m--tagf\u001b[0;2m (TagF()) \r\n\u001b[0;34m--multiparts\u001b[0;2m (MultiParts()) \u001b[0;m \u001b[0;34m--timeout\u001b[0;2m (Timeout()) \r\n\u001b[0;34m--multipartsp\u001b[0;2m (MultiPartsP()) \u001b[0;m \u001b[0;34m--uniquelist\u001b[0;2m (UniqueList()) \r\n\u001b[0;34m--nospace\u001b[0;2m (NoSpace()) \u001b[0;m \u001b[0;34m--uniquelistf\u001b[0;2m (UniqueListF())\r\n\u001b[0;33m--persistentFlag\u001b[0;2m (Help message for persistentFlag) \u001b[0;m \u001b[0;34m--unless\u001b[0;2m (Unless()) \r\n\u001b[0;34m--persistentFlag2\u001b[0;2m (Help message for persistentFlag2)\u001b[0;m \u001b[0;34m--usage\u001b[0;2m (Usage()) \r\n\u001b[0;34m--prefix\u001b[0;2m (Prefix()) \u001b[0;m\u001b[17A\r\u001b[22C\u001b[?25h"] +[3.757363, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[17A\r\u001b[22C\u001b[?25h"] +[4.121816, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[25C\u001b[K\u001b[0;4mmultiparts \r\n\u001b[22C\u001b[0;mu\r\n\u001b[2C\u001b[K\u001b[0;7;34mmultiparts\u001b[0;2;7m (MultiParts()) \u001b[0;m \u001b[0;34m--suppress\u001b[0;2m (Suppress()) \u001b[0;m \u001b[0;34m--uniquelistf\u001b[0;2m (UniqueListF())\r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultipartsp\u001b[0;2m (MultiPartsP())\u001b[0;m \u001b[0;34m--timeout\u001b[0;2m (Timeout()) \u001b[0;m \u001b[0;34m--unless\u001b[0;2m (Unless()) \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34msuffix\u001b[0;2m (Suffix()) \u001b[0;m \u001b[0;34m--uniquelist\u001b[0;2m (UniqueList())\u001b[0;m \u001b[0;34m--usage\u001b[0;2m (Usage()) \u001b[0;m\r\n\u001b[J\u001b[A\u001b[3A\r\u001b[23C\u001b[?25h"] +[4.297384, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[25C\u001b[K\u001b[0;4muniquelist \r\n\u001b[23C\u001b[0;mn\r\n\u001b[2C\u001b[K\u001b[0;7;34muniquelist\u001b[0;2;7m (UniqueList())\u001b[0;m \u001b[0;34m--uniquelistf\u001b[0;2m (UniqueListF())\u001b[0;m \u001b[0;34m--unless\u001b[0;2m (Unless())\u001b[0;m\r\n\u001b[J\u001b[A\u001b[1A\r\u001b[24C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[24C\u001b[?25h"] +[4.368639, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[27C\u001b[K\u001b[0;4mless \r\n\u001b[24C\u001b[0;ml\r\n\u001b[4C\u001b[K\u001b[0;7;34mless\u001b[0;2;7m (Unless())\u001b[0;m\u001b[1A\r\u001b[25C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\u001b[1A\r\u001b[25C\u001b[?25h"] +[5.060184, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[23C\u001b[K--unless \r\n\u001b[J\u001b[A\r\u001b[32C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[32C\u001b[?25h"] +[5.459028, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[0;4m./local \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7m./local\u001b[0;m /abs one three two ~/home\u001b[1A\r\u001b[22C\u001b[?25h"] +[7.834727, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[32C\u001b[K\r\n\u001b[J\u001b[A\r\u001b[32C\u001b[?25h"] +[8.483363, "o", "\u001b[?25l\u001b[1A\rUnbound key: Alt-t\u001b[K\r\n\u001b[K\u001b[0;1;36m~\u001b[0;m \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \u001b[0;32mexample\u001b[0;m modifier --unless \r\u001b[32C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[32C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[32C\u001b[?25h"] +[9.179995, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32Ct\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[9.677383, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[K\u001b[0;4mthree \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mthree\u001b[0;m two\u001b[1A\r\u001b[22C\u001b[?25h"] +[10.781412, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[32C\u001b[Kt\r\n\u001b[J\u001b[A\r\u001b[33C\u001b[?25h"] +[11.425598, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[K\r\u001b[32C\u001b[?25h"] +[11.713544, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C/\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[11.91868, "o", "\u001b[?25l\u001b[1A\r\u001b[0;2musage: \u001b[0;mUnless()\u001b[K\r\n\u001b[0;31merror:\u001b[0;m no candidates\u001b[K\r\n\u001b[K\u001b[0;1;36m~\u001b[0;m \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \u001b[0;32mexample\u001b[0;m modifier --unless /\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[12.885206, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[K\r\u001b[32C\u001b[?25h"] +[13.300142, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C~\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[13.682684, "o", "\u001b[?25l\u001b[1A\r\u001b[0;2musage: \u001b[0;mUnless()\u001b[K\r\n\u001b[0;31merror:\u001b[0;m no candidates\u001b[K\r\n\u001b[K\u001b[0;1;36m~\u001b[0;m \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \u001b[0;32mexample\u001b[0;m modifier --unless ~\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[14.234812, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[K\r\u001b[32C\u001b[?25h"] +[14.536332, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C.\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[14.745416, "o", "\u001b[?25l\u001b[1A\r\u001b[0;2musage: \u001b[0;mUnless()\u001b[K\r\n\u001b[0;31merror:\u001b[0;m no candidates\u001b[K\r\n\u001b[K\u001b[0;1;36m~\u001b[0;m \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \u001b[0;32mexample\u001b[0;m modifier --unless .\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[15.535869, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32C\u001b[K\r\u001b[32C\u001b[?25h"] +[15.782019, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[32Co\r\u001b[33C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[33C\u001b[?25h"] +[15.911862, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[33Cne \r\u001b[36C\u001b[?25h"] +[16.916407, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[6C\u001b[?25h"] +[16.917521, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[6C\u001b[?25h"] +[16.929318, "o", "\u001b[?25l\u001b[1A\r\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[6C\u001b[?25h"] +[17.205288, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[0;32me\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[7C\u001b[?25h"] +[17.380397, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;31mex\u001b[0;m\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[8C\u001b[?25h"] +[17.567313, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[8C\u001b[0;31mi\u001b[0;m\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[9C\u001b[?25h"] +[17.658512, "o", "\u001b[?25l\u001b[1A\r\r\n\u001b[6C\u001b[K\u001b[0;32mexit\u001b[0;m\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[1A\r\r\n\r\u001b[10C\u001b[?25h"] +[17.773903, "o", "\u001b[?25l\u001b[1A\r\r\n\r\n\r\u001b[?25h\u001b[?7h\u001b[?2004l\r"] diff --git a/docs/src/carapace/action/unless.md b/docs/src/carapace/action/unless.md new file mode 100644 index 000000000..ebfe4482e --- /dev/null +++ b/docs/src/carapace/action/unless.md @@ -0,0 +1,19 @@ +# Unless + +[`Unless`] skips invokation if given [condition] succeeds. + +```go +carapace.ActionValues( + "./local", + "~/home", + "/abs", + "one", + "two", + "three", +).Unless(condition.CompletingPath) +``` + +![](./unless.cast) + +[`Unless`]:https://pkg.go.dev/github.com/rsteube/carapace#Action.Unless +[condition]:https://pkg.go.dev/github.com/rsteube/carapace/pkg/condition diff --git a/example/cmd/modifier.go b/example/cmd/modifier.go index 7ceda38fa..6228ae5f1 100644 --- a/example/cmd/modifier.go +++ b/example/cmd/modifier.go @@ -8,6 +8,7 @@ import ( "github.com/rsteube/carapace" "github.com/rsteube/carapace/pkg/cache" + "github.com/rsteube/carapace/pkg/condition" "github.com/rsteube/carapace/pkg/style" "github.com/rsteube/carapace/pkg/traverse" "github.com/spf13/cobra" @@ -50,6 +51,7 @@ func init() { modifierCmd.Flags().String("timeout", "", "Timeout()") modifierCmd.Flags().String("uniquelist", "", "UniqueList()") modifierCmd.Flags().String("uniquelistf", "", "UniqueListF()") + modifierCmd.Flags().String("unless", "", "Unless()") modifierCmd.Flags().String("usage", "", "Usage()") rootCmd.AddCommand(modifierCmd) @@ -264,6 +266,14 @@ func init() { }).UniqueListF(",", func(s string) string { return strings.SplitN(s, ":", 2)[0] }), + "unless": carapace.ActionValues( + "./local", + "~/home", + "/abs", + "one", + "two", + "three", + ).Unless(condition.CompletingPath), "usage": carapace.ActionValues().Usage("explicit usage"), }) diff --git a/example/cmd/modifier_test.go b/example/cmd/modifier_test.go index ca258c7f8..59899d88a 100644 --- a/example/cmd/modifier_test.go +++ b/example/cmd/modifier_test.go @@ -463,6 +463,34 @@ func TestSplitP(t *testing.T) { Usage("SplitP()")) }) } +func TestUnless(t *testing.T) { + sandbox.Package(t, "github.com/rsteube/carapace/example")(func(s *sandbox.Sandbox) { + s.Run("modifier", "--unless", ""). + Expect(carapace.ActionValues( + "./local", + "~/home", + "/abs", + "one", + "two", + "three", + ).Usage("Unless()")) + + s.Run("modifier", "--unless", "t"). + Expect(carapace.ActionValues( + "two", + "three", + ).Usage("Unless()")) + + s.Run("modifier", "--unless", "."). + Expect(carapace.ActionValues().Usage("Unless()")) + + s.Run("modifier", "--unless", "~"). + Expect(carapace.ActionValues().Usage("Unless()")) + + s.Run("modifier", "--unless", "/"). + Expect(carapace.ActionValues().Usage("Unless()")) + }) +} func TestUniqueList(t *testing.T) { sandbox.Package(t, "github.com/rsteube/carapace/example")(func(s *sandbox.Sandbox) { diff --git a/pkg/condition/condition.go b/pkg/condition/condition.go new file mode 100644 index 000000000..e533edece --- /dev/null +++ b/pkg/condition/condition.go @@ -0,0 +1,75 @@ +package condition + +import ( + "os" + "os/exec" + "runtime" + "strings" + + "github.com/rsteube/carapace" + "github.com/rsteube/carapace/pkg/util" +) + +// Arch returns true if any of the given strings matches `runtime.GOARCH`. +func Arch(s ...string) func(c carapace.Context) bool { + return func(c carapace.Context) bool { + for _, arch := range s { + if arch == runtime.GOARCH { + return true + } + } + return false + } +} + +// Arch returns true if any of the given strings matches `runtime.GOOS`. +func Os(s ...string) func(c carapace.Context) bool { + return func(c carapace.Context) bool { + for _, os := range s { + if os == runtime.GOOS { + return true + } + } + return false + } +} + +// Excutable returns true if any of the given strings matches an executable in PATH. +func Executable(s ...string) func(c carapace.Context) bool { + return func(c carapace.Context) bool { + for _, executable := range s { + // TODO needs to use Context.Env + if _, err := exec.LookPath(executable); err == nil { + return true + } + } + return false + } +} + +// Retuns true if given string is a valid file or directory. +func File(s string) func(c carapace.Context) bool { + return func(c carapace.Context) bool { + if _, err := os.Stat(s); err == nil { + return true + } + return false + } +} + +// CompletingPath returns true when Context.Value is assumed a path. +// Either +// - it has a path prefix +// - it contains a filepath delimiter and the first segment is a valid directory +// - it is a valid file or directory +func CompletingPath(c carapace.Context) bool { + if util.HasPathPrefix(c.Value) { + return true + } + if s := c.Value; strings.ContainsAny(s, "/\\") { + s = strings.SplitN(s, "/", 2)[0] + s = strings.SplitN(s, "\\", 2)[0] + return File(s)(c) + } + return File(c.Value)(c) +}