From 8cc149b6f3fe7ab8ae768052b037b901265a5df6 Mon Sep 17 00:00:00 2001 From: rsteube Date: Fri, 28 Jul 2023 13:24:24 +0200 Subject: [PATCH] lexer: split action --- action.go | 13 ++- docs/src/SUMMARY.md | 1 + docs/src/carapace/action/split.md | 2 +- docs/src/carapace/action/splitP.cast | 109 +++++++++++++++++++ docs/src/carapace/action/splitP.md | 28 +++++ example/cmd/modifier.go | 18 +++ internal/lexer/lexer.go | 16 ++- internal/lexer/lexer_test.go | 2 +- third_party/github.com/google/shlex/shlex.go | 4 +- 9 files changed, 181 insertions(+), 12 deletions(-) create mode 100644 docs/src/carapace/action/splitP.cast create mode 100644 docs/src/carapace/action/splitP.md diff --git a/action.go b/action.go index 6572de62f..a9952d6a5 100644 --- a/action.go +++ b/action.go @@ -166,10 +166,19 @@ func (a Action) Shift(n int) Action { }) } -// Split splits `Context.Value` using a shell lexer and replaces `Context.Args` with the tokens. +// Split splits `Context.Value` lexicographically and replaces `Context.Args` with the tokens. func (a Action) Split() Action { + return a.split(false) +} + +// SplitP is like Split but supports pipelines. +func (a Action) SplitP() Action { + return a.split(true) +} + +func (a Action) split(pipelines bool) Action { return ActionCallback(func(c Context) Action { - tokenset, err := lexer.Split(c.Value) + tokenset, err := lexer.Split(c.Value, pipelines) if err != nil { return ActionMessage(err.Error()) } diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 8f0eb5022..02796daca 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -28,6 +28,7 @@ - [Retain](./carapace/action/retain.md) - [Shift](./carapace/action/shift.md) - [Split](./carapace/action/split.md) + - [SplitP](./carapace/action/splitP.md) - [Style](./carapace/action/style.md) - [StyleF](./carapace/action/styleF.md) - [StyleR](./carapace/action/styleR.md) diff --git a/docs/src/carapace/action/split.md b/docs/src/carapace/action/split.md index c2070c900..dcf8b4772 100644 --- a/docs/src/carapace/action/split.md +++ b/docs/src/carapace/action/split.md @@ -1,6 +1,6 @@ # Split -[`Split`] splits `Context.Value` using a shell lexer and replaces `Context.Args` with the tokens. +[`Split`] splits `Context.Value` lexicographically and replaces `Context.Args` with the tokens. ```go carapace.ActionCallback(func(c carapace.Context) carapace.Action { diff --git a/docs/src/carapace/action/splitP.cast b/docs/src/carapace/action/splitP.cast new file mode 100644 index 000000000..193190aa8 --- /dev/null +++ b/docs/src/carapace/action/splitP.cast @@ -0,0 +1,109 @@ +{"version": 2, "width": 108, "height": 24, "timestamp": 1690543699, "env": {"SHELL": "elvish", "TERM": "tmux-256color"}} +[0.086228, "o", "\u001b[?7h\u001b[7m⏎\u001b[m \r \r\u001b[?7l\u001b[?2004h\u001b[?25l\r???> ???> \r\u001b[5C\u001b[?25h\u001b[?25l\r\u001b[5C\u001b[K\r\u001b[5C\u001b[?25h"] +[0.098363, "o", "\u001b[?25l\r\u001b[K\r\n\u001b[0;1;36mcarapace/example\u001b[0;m on \u001b[0;1;35m lexer-split-action\u001b[0;m \u001b[0;1;31m[$!?]\u001b[0;m via \u001b[0;1;36m🐹 v1.20.6 \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"] +[1.324167, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31me\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"] +[1.341506, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"] +[1.341702, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"] +[1.499179, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31mx\u001b[0;m\r\u001b[8C\u001b[?25h"] +[1.499284, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"] +[1.592179, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mexa\u001b[0;m\r\u001b[9C\u001b[?25h"] +[1.592514, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"] +[1.745759, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;31mexam\u001b[0;m\r\u001b[10C\u001b[?25h"] +[1.745826, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"] +[1.80434, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10C\u001b[0;31mp\u001b[0;m\r\u001b[11C\u001b[?25h"] +[1.804421, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"] +[1.897474, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[11C\u001b[0;31ml\u001b[0;m\r\u001b[12C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[12C\u001b[?25h"] +[1.979187, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mexample\u001b[0;m\r\u001b[13C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[13C\u001b[?25h"] +[2.051643, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[13C \r\u001b[14C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h"] +[2.134329, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14Cm\r\u001b[15C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[15C\u001b[?25h"] +[2.20805, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[15Co\r\u001b[16C\u001b[?25h"] +[2.208136, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[16C\u001b[?25h"] +[2.323358, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[16Cdifier \r\u001b[23C\u001b[?25h"] +[2.890466, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[23C-\r\u001b[24C\u001b[?25h"] +[2.890585, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[24C\u001b[?25h"] +[3.010623, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[24C-\r\u001b[25C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[25C\u001b[?25h"] +[3.116496, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[25Cs\r\u001b[26C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[26C\u001b[?25h"] +[3.208726, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[26Cp\r\u001b[27C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[27C\u001b[?25h"] +[3.424894, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[27Cl\r\u001b[28C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[28C\u001b[?25h"] +[3.550282, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[28Ci\r\u001b[29C\u001b[?25h"] +[3.55035, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[29C\u001b[?25h"] +[3.803321, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[29Ct\r\u001b[30C\u001b[?25h"] +[4.271563, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[23C\u001b[K\u001b[0;4m--split \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;34m--split\u001b[0;2;7m (Split())\u001b[0;m \u001b[0;34m--splitp\u001b[0;2m (SplitP())\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[4.637759, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[30C\u001b[K\u001b[0;4mp \r\n\r\n\u001b[0;m\u001b[K\u001b[0;34m--split\u001b[0;2m (Split())\u001b[0;m \u001b[0;7;34m--splitp\u001b[0;2;7m (SplitP())\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[4.799185, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[23C\u001b[K--splitp \r\n\u001b[J\u001b[A\r\u001b[32C\u001b[?25h"] +[4.799269, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[32C\u001b[?25h"] +[5.225142, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[0;33m'pos\u001b[0;m\r\u001b[36C\u001b[?25h"] +[5.746502, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mpos1\u001b[0;m positional1\u001b[1A\r\u001b[22C\u001b[?25h"] +[6.486288, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[39C\u001b[?25h"] +[6.905963, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[39C-\r\u001b[40C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[40C\u001b[?25h"] +[7.060245, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[40C-\r\u001b[41C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[41C\u001b[?25h"] +[7.183381, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --bool '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7m--bool\u001b[0;2;7m (bool flag)\u001b[0;m \u001b[0;34m--string\u001b[0;2m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[7.719308, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[40C\u001b[K\u001b[0;4;33mstring '\r\n\r\n\u001b[0;m\u001b[K--bool\u001b[0;2m (bool flag)\u001b[0;m \u001b[0;7;34m--string\u001b[0;2;7m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[7.719729, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[7.720609, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[7.720838, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[8.172722, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[48C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[48C\u001b[?25h"] +[8.351769, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mone\u001b[0;m three two\u001b[1A\r\u001b[22C\u001b[?25h"] +[9.028868, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[52C\u001b[?25h"] +[9.029144, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[52C\u001b[?25h"] +[9.444301, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[51C\u001b[?25h"] +[9.772042, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[51C\u001b[K\u001b[0;33m|'\u001b[0;m\r\u001b[52C\u001b[?25h"] +[9.77237, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[52C\u001b[?25h"] +[10.135651, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one |pos1 '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mpos1\u001b[0;m positional1\u001b[1A\r\u001b[22C\u001b[?25h"] +[11.106597, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[55C\u001b[K\u001b[0;4;33mitional1 '\r\n\r\n\u001b[0;m\u001b[Kpos1 \u001b[0;7mpositional1\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[11.614585, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one |positional1 '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[65C\u001b[?25h"] +[11.614938, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[65C\u001b[?25h"] +[11.970476, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[65C-\r\u001b[66C\u001b[?25h"] +[11.970562, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[66C\u001b[?25h"] +[12.134609, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[66C-\r\u001b[67C\u001b[?25h"] +[12.134707, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[67C\u001b[?25h"] +[12.213808, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one |positional1 --bool '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7m--bool\u001b[0;2;7m (bool flag)\u001b[0;m \u001b[0;34m--string\u001b[0;2m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[13.467972, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one |positional1 --bool '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[72C\u001b[?25h"] +[13.468091, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[72C\u001b[?25h"] +[14.085505, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[71C\u001b[?25h"] +[15.528175, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[71C\u001b[K\u001b[0;33m|'\u001b[0;m\r\u001b[72C\u001b[?25h"] +[15.528255, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[72C\u001b[?25h"] +[15.703226, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[72C\u001b[K\u001b[0;33m|'\u001b[0;m\r\u001b[73C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[73C\u001b[?25h"] +[16.281494, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[73C\u001b[K\u001b[0;33m '\u001b[0;m\r\u001b[74C\u001b[?25h"] +[16.281579, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[74C\u001b[?25h"] +[17.14062, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one |positional1 --bool || pos1 '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mpos1\u001b[0;m positional1\u001b[1A\r\u001b[22C\u001b[?25h"] +[17.663432, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[77C\u001b[K\u001b[0;4;33mitional1 '\r\n\r\n\u001b[0;m\u001b[Kpos1 \u001b[0;7mpositional1\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[17.663832, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[17.664683, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[17.665125, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[18.069956, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one |positional1 --bool || positional1 '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[87C\u001b[?25h"] +[18.070079, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[87C\u001b[?25h"] +[18.627946, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[86C\u001b[?25h"] +[18.868989, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[86C\u001b[K\u001b[0;33m-'\u001b[0;m\r\u001b[87C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[87C\u001b[?25h"] +[19.028553, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[87C\u001b[K\u001b[0;33m-'\u001b[0;m\r\u001b[88C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[88C\u001b[?25h"] +[19.147296, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one |positional1 --bool || positional1 --bool '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7m--bool\u001b[0;2;7m (bool flag)\u001b[0;m \u001b[0;34m--string\u001b[0;2m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[20.375247, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[88C\u001b[K\u001b[0;4;33mstring '\r\n\r\n\u001b[0;m\u001b[K--bool\u001b[0;2m (bool flag)\u001b[0;m \u001b[0;7;34m--string\u001b[0;2;7m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[20.375753, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[21.293048, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[88C\u001b[K\u001b[0;4;33mbool '\r\n\r\n\u001b[0;m\u001b[K\u001b[0;7m--bool\u001b[0;2;7m (bool flag)\u001b[0;m \u001b[0;34m--string\u001b[0;2m (string flag)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[21.719817, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one |positional1 --bool || positional1 --bool '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[94C\u001b[?25h"] +[21.719915, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[94C\u001b[?25h"] +[22.061979, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[93C\u001b[?25h"] +[22.310362, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[92C\u001b[K\u001b[0;33m'\u001b[0;m\r\u001b[92C\u001b[?25h"] +[22.54345, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[92C\u001b[K\u001b[0;33m='\u001b[0;m\r\u001b[93C\u001b[?25h"] +[22.543903, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[93C\u001b[?25h"] +[22.643917, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[93C\u001b[K\u001b[0;33m='\u001b[0;m\r\u001b[94C\u001b[?25h"] +[22.643994, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[94C\u001b[?25h"] +[23.030882, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[93C\u001b[K\u001b[0;33m'\u001b[0;m\r\u001b[93C\u001b[?25h"] +[23.134964, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;4;33m'pos1 --string one |positional1 --bool || positional1 --bool=false '\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;31mfalse\u001b[0;m \u001b[0;32mtrue\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[23.807335, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[93C\u001b[K\u001b[0;4;33mtrue '\r\n\r\n\u001b[0;m\u001b[K\u001b[0;31mfalse\u001b[0;m \u001b[0;7;32mtrue\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"] +[23.807766, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"] +[24.189796, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[32C\u001b[K\u001b[0;33m'pos1 --string one |positional1 --bool || positional1 --bool=true '\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[99C\u001b[?25h"] +[24.190183, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[99C\u001b[?25h"] +[25.759864, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\r\u001b[6C\u001b[?25h"] +[25.759953, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"] +[25.76083, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"] +[25.777104, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"] +[25.777244, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"] +[26.03498, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31me\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"] +[26.285404, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31mx\u001b[0;m\r\u001b[8C\u001b[?25h"] +[26.285994, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"] +[26.287719, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"] +[26.424577, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[8C\u001b[0;31mi\u001b[0;m\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"] +[26.486069, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mexit\u001b[0;m\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"] +[26.608906, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\u001b[?25h"] +[26.609153, "o", "\u001b[?7h\u001b[?2004l\r"] diff --git a/docs/src/carapace/action/splitP.md b/docs/src/carapace/action/splitP.md new file mode 100644 index 000000000..fa9573b0b --- /dev/null +++ b/docs/src/carapace/action/splitP.md @@ -0,0 +1,28 @@ +# SplitP + +[`SplitP`] is like [Split] but supports pipelines. + +```go +carapace.ActionCallback(func(c carapace.Context) carapace.Action { + cmd := &cobra.Command{} + carapace.Gen(cmd).Standalone() + cmd.Flags().BoolP("bool", "b", false, "bool flag") + cmd.Flags().StringP("string", "s", "", "string flag") + + carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{ + "string": carapace.ActionValues("one", "two", "three"), + }) + + carapace.Gen(cmd).PositionalCompletion( + carapace.ActionValues("pos1", "positional1"), + carapace.ActionFiles(), + ) + + return carapace.ActionExecute(cmd) +}).SplitP() +``` + +![](./splitP.cast) + +[Split]:./split.md +[`SplitP`]: https://pkg.go.dev/github.com/rsteube/carapace#Action.SplitP diff --git a/example/cmd/modifier.go b/example/cmd/modifier.go index f7f69f3b5..ef5c44498 100644 --- a/example/cmd/modifier.go +++ b/example/cmd/modifier.go @@ -34,6 +34,7 @@ func init() { modifierCmd.Flags().String("retain", "", "Retain()") modifierCmd.Flags().String("shift", "", "Shift()") modifierCmd.Flags().String("split", "", "Split()") + modifierCmd.Flags().String("splitp", "", "SplitP()") modifierCmd.Flags().String("style", "", "Style()") modifierCmd.Flags().String("stylef", "", "StyleF()") modifierCmd.Flags().String("styler", "", "StyleR()") @@ -141,6 +142,23 @@ func init() { return carapace.ActionExecute(cmd) }).Split(), + "splitp": carapace.ActionCallback(func(c carapace.Context) carapace.Action { + cmd := &cobra.Command{} + carapace.Gen(cmd).Standalone() + cmd.Flags().BoolP("bool", "b", false, "bool flag") + cmd.Flags().StringP("string", "s", "", "string flag") + + carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{ + "string": carapace.ActionValues("one", "two", "three"), + }) + + carapace.Gen(cmd).PositionalCompletion( + carapace.ActionValues("pos1", "positional1"), + carapace.ActionFiles(), + ) + + return carapace.ActionExecute(cmd) + }).SplitP(), "style": carapace.ActionValues( "one", "two", diff --git a/internal/lexer/lexer.go b/internal/lexer/lexer.go index 8f03b23ab..8415f20d5 100644 --- a/internal/lexer/lexer.go +++ b/internal/lexer/lexer.go @@ -20,10 +20,10 @@ type Tokenset struct { State State } -func Split(s string) (*Tokenset, error) { - tokenset, err := split(s) +func Split(s string, pipelines bool) (*Tokenset, error) { + tokenset, err := split(s, pipelines) if err != nil && err.Error() == "EOF found when expecting closing quote" { - tokenset, err = split(s + `_"`) + tokenset, err = split(s+`_"`, pipelines) if err == nil { last := tokenset.Tokens[len(tokenset.Tokens)-1] tokenset.Tokens[len(tokenset.Tokens)-1] = last[:len(last)-1] @@ -32,7 +32,7 @@ func Split(s string) (*Tokenset, error) { } } if err != nil && err.Error() == "EOF found when expecting closing quote" { - tokenset, err = split(s + `_'`) + tokenset, err = split(s+`_'`, pipelines) if err == nil { last := tokenset.Tokens[len(tokenset.Tokens)-1] tokenset.Tokens[len(tokenset.Tokens)-1] = last[:len(last)-1] @@ -43,8 +43,12 @@ func Split(s string) (*Tokenset, error) { return tokenset, err } -func split(s string) (*Tokenset, error) { - splitted, err := shlex.SplitP(s) +func split(s string, pipelines bool) (*Tokenset, error) { + f := shlex.Split + if pipelines { + f = shlex.SplitP + } + splitted, err := f(s) if strings.HasSuffix(s, " ") { splitted = append(splitted, "") } diff --git a/internal/lexer/lexer_test.go b/internal/lexer/lexer_test.go index c945b4fc9..b87f9cbfe 100644 --- a/internal/lexer/lexer_test.go +++ b/internal/lexer/lexer_test.go @@ -10,7 +10,7 @@ import ( func TestSplit(t *testing.T) { _test := func(s string, expected Tokenset) { t.Run(s, func(t *testing.T) { - tokenset, err := Split(s) + tokenset, err := Split(s, true) if err != nil { t.Error(err.Error()) } diff --git a/third_party/github.com/google/shlex/shlex.go b/third_party/github.com/google/shlex/shlex.go index 8ac2609f1..520c0f941 100644 --- a/third_party/github.com/google/shlex/shlex.go +++ b/third_party/github.com/google/shlex/shlex.go @@ -431,7 +431,7 @@ func SplitP(s string) ([]string, error) { } // Split partitions a string into a slice of strings. -func split(s string, resetOnPipe bool) ([]string, error) { +func split(s string, pipelines bool) ([]string, error) { l := NewLexer(strings.NewReader(s)) subStrings := make([]string, 0) for { @@ -443,7 +443,7 @@ func split(s string, resetOnPipe bool) ([]string, error) { if _, ok := err.(*PipelineSeparatorError); !ok { return subStrings, err } - if resetOnPipe { + if pipelines { subStrings = make([]string, 0) continue }