Repository: rsteube/carapace
Pull request #838 (2023-07-23 06:49:02)

added ActionMultiPartsN


Patch:
diff --git a/defaultActions.go b/defaultActions.go
index 9657546..cf1e342 100644
--- a/defaultActions.go
+++ b/defaultActions.go
@@ -211,26 +211,30 @@ func ActionMessage(msg string, args ...interface{}) Action {
 	})
 }
 
-// ActionMultiParts completes multiple parts of words separately where each part is separated by some char (Context.Value is set to the currently completed part during invocation).
-func ActionMultiParts(divider string, callback func(c Context) Action) Action {
+// ActionMultiParts completes parts of c.Value separated by sep.
+func ActionMultiParts(sep string, callback func(c Context) Action) Action {
+	return ActionMultiPartsN(sep, -1, callback)
+}
+
+// ActionMultiPartsN is like ActionMultiParts but limits the number of parts to `n`.
+func ActionMultiPartsN(sep string, n int, callback func(c Context) Action) Action {
 	return ActionCallback(func(c Context) Action {
-		index := strings.LastIndex(c.Value, string(divider))
+		splitted := strings.SplitN(c.Value, sep, n)
 		prefix := ""
-		if len(divider) == 0 {
+		c.Parts = []string{}
+
+		switch {
+		case len(sep) == 0:
 			prefix = c.Value
 			c.Value = ""
-		} else if index != -1 {
-			prefix = c.Value[0 : index+len(divider)]
-			c.Value = c.Value[index+len(divider):] // update Context.Value to only contain the currently completed part
-		}
-		parts := strings.Split(prefix, string(divider))
-		if len(parts) > 0 && len(divider) > 0 {
-			parts = parts[0 : len(parts)-1]
+		case len(splitted) > 1:
+			c.Value = splitted[len(splitted)-1]
+			c.Parts = splitted[:len(splitted)-1]
+			prefix = strings.Join(c.Parts, sep) + sep
 		}
-		c.Parts = parts
 
 		nospace := '*'
-		if runes := []rune(divider); len(runes) > 0 {
+		if runes := []rune(sep); len(runes) > 0 {
 			nospace = runes[len(runes)-1]
 		}
 		return callback(c).Invoke(c).Prefix(prefix).ToA().NoSpace(nospace)
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
index c5faaec..04d999a 100644
--- a/docs/src/SUMMARY.md
+++ b/docs/src/SUMMARY.md
@@ -45,6 +45,7 @@
     - [ActionImport](./carapace/defaultActions/actionImport.md)
     - [ActionMessage](./carapace/defaultActions/actionMessage.md)
     - [ActionMultiParts](./carapace/defaultActions/actionMultiParts.md)
+    - [ActionMultiPartsN](./carapace/defaultActions/actionMultiPartsN.md)
     - [ActionPositional](./carapace/defaultActions/actionPositional.md)
     - [ActionStyles](./carapace/defaultActions/actionStyles.md)
     - [ActionStyleConfig](./carapace/defaultActions/actionStyleConfig.md)
diff --git a/docs/src/carapace/defaultActions/actionMultiPartsN.cast b/docs/src/carapace/defaultActions/actionMultiPartsN.cast
new file mode 100644
index 0000000..750c30f
--- /dev/null
+++ b/docs/src/carapace/defaultActions/actionMultiPartsN.cast
@@ -0,0 +1,59 @@
+{"version": 2, "width": 108, "height": 24, "timestamp": 1690097520, "env": {"SHELL": "elvish", "TERM": "tmux-256color"}}
+[0.083566, "o", "\u001b[?7h\u001b[7m⏎\u001b[m                                                                                                           \r \r\u001b[?7l\u001b[?2004h"]
+[0.084001, "o", "\u001b[?25l\r???>                                                                                                   ???> \r\u001b[5C\u001b[?25h\u001b[?25l\r\u001b[5C\u001b[K\r\u001b[5C\u001b[?25h"]
+[0.092377, "o", "\u001b[?25l\r\r\u001b[5C\u001b[?25h"]
+[0.092446, "o", "\u001b[?25l\r\u001b[K\r\n\u001b[0;1;36mcarapace/example\u001b[0;m on \u001b[0;1;35m add-actionmultipartsn\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"]
+[0.537081, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31me\u001b[0;m\r\u001b[7C\u001b[?25h"]
+[0.537141, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
+[0.537429, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
+[0.54625, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
+[0.546348, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
+[0.714519, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31mx\u001b[0;m\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"]
+[0.841347, "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\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"]
+[1.004587, "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.004967, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
+[1.075482, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10C\u001b[0;31mp\u001b[0;m\r\u001b[11C\u001b[?25h"]
+[1.075896, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"]
+[1.203783, "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.28107, "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"]
+[1.359784, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[13C \r\u001b[14C\u001b[?25h"]
+[1.359916, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h"]
+[1.39334, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14Ca\r\u001b[15C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[15C\u001b[?25h"]
+[1.519907, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[15Cc\r\u001b[16C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[16C\u001b[?25h"]
+[1.691909, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[16Ction \r\u001b[21C\u001b[?25h"]
+[2.61171, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[21C-\r\u001b[22C\u001b[?25h"]
+[2.61209, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[22C\u001b[?25h"]
+[2.828719, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[22C-\r\u001b[23C\u001b[?25h"]
+[3.008649, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[21C\u001b[K\u001b[0;4m--callback \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;34m--callback\u001b[0;2;7m (ActionCallback())                                 \u001b[0;m  \u001b[0;34m--styles\u001b[0;2m (ActionStyles())                   \r\n\u001b[0;34m--directories\u001b[0;2m (ActionDirectories())                           \u001b[0;m  \u001b[0;34m--values\u001b[0;2m (ActionValues())                   \r\n\u001b[0;34m--execcommand\u001b[0;2m (ActionExecCommand())                           \u001b[0;m  \u001b[0;34m--values-described\u001b[0;2m (ActionValuesDescribed())\r\n\u001b[0;34m--execcommandE\u001b[0;2m (ActionExecCommand())                          \r\n\u001b[0;34m--executables\u001b[0;2m (ActionExecutables())                           \r\n\u001b[0;34m--files\u001b[0;2m (ActionFiles())                                       \r\n\u001b[0;34m--files-filtered\u001b[0;2m (ActionFiles(\".md\", \"go.mod\", \"go.sum\"))     \r\n\u001b[0;m--help\u001b[0;2m (help for action)                                      \r\n\u001b[0;34m--import\u001b[0;2m (ActionImport())                                     \r\n\u001b[0;34m--message\u001b[0;2m (ActionMessage())                                   \r\n\u001b[0;34m--message-multiple\u001b[0;2m (ActionMessage())                          \r\n\u001b[0;34m--multiparts\u001b[0;2m (ActionMultiParts())                             \r\n\u001b[0;34m--multiparts-nested\u001b[0;2m (ActionMultiParts(...ActionMultiParts...))\r\n\u001b[0;34m--multipartsn\u001b[0;2m (ActionMultiPartsN())                           \r\n\u001b[0;33m--persistentFlag\u001b[0;2m (Help message for persistentFlag)            \r\n\u001b[0;34m--persistentFlag2\u001b[0;2m (Help message for persistentFlag2)          \r\n\u001b[0;34m--styleconfig\u001b[0;2m (ActionStyleConfig())                           \r\n\u001b[0;34m--styled-values\u001b[0;2m (ActionStyledValues())                        \r\n\u001b[0;34m--styled-values-described\u001b[0;2m (ActionStyledValuesDescribed())     \u001b[0;m\u001b[19A\r\u001b[22C\u001b[?25h"]
+[3.479145, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[23C\u001b[K\u001b[0;4mexeccommand \r\n\u001b[22C\u001b[0;mm\r\n\u001b[2C\u001b[K\u001b[0;7;34mexeccommand\u001b[0;2;7m (ActionExecCommand())                           \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mexeccommandE\u001b[0;2m (ActionExecCommand())                          \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mfiles-filtered\u001b[0;2m (ActionFiles(\".md\", \"go.mod\", \"go.sum\"))     \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mimport\u001b[0;2m (ActionImport())                                     \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmessage\u001b[0;2m (ActionMessage())                                   \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmessage-multiple\u001b[0;2m (ActionMessage())                          \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultiparts\u001b[0;2m (ActionMultiParts())                             \r\n\u001b[0;m\u001b[K\u001b[0;34m--multiparts-nested\u001b[0;2m (ActionMultiParts(...ActionMultiParts...))\r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultipartsn\u001b[0;2m (ActionMultiPartsN())                           \r\n\u001b[0;m\u001b[K\u001b[0;33m--persistentFlag\u001b[0;2m (Help message for persistentFlag)            \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mpersistentFlag2\u001b[0;2m (Help message for persistentFlag2)          \u001b[0;m\r\n\u001b[J\u001b[A\u001b[11A\r\u001b[23C\u001b[?25h"]
+[3.694742, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[23C\u001b[K\u001b[0;4mmessage-multiple \r\n\u001b[23C\u001b[0;mu\r\n\u001b[2C\u001b[K\u001b[0;7;34mmessage-multiple\u001b[0;2;7m (ActionMessage())                          \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultiparts\u001b[0;2m (ActionMultiParts())                             \r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultiparts-nested\u001b[0;2m (ActionMultiParts(...ActionMultiParts...))\r\n\u001b[2C\u001b[0;m\u001b[K\u001b[0;34mmultipartsn\u001b[0;2m (ActionMultiPartsN())                           \u001b[0;m\r\n\u001b[J\u001b[A\u001b[4A\r\u001b[24C\u001b[?25h"]
+[3.695208, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[4A\r\u001b[24C\u001b[?25h"]
+[4.285064, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[24C\u001b[K\u001b[0;4multiparts \r\n\r\n\u001b[0;m\u001b[K\u001b[0;34m--message-multiple\u001b[0;2m (ActionMessage())                          \r\n\u001b[0;m\u001b[K\u001b[0;7;34m--multiparts\u001b[0;2;7m (ActionMultiParts())                             \r\n\r\n\u001b[0;m\u001b[4A\r\u001b[24C\u001b[?25h"]
+[4.440841, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[33C\u001b[K\u001b[0;4m-nested \r\n\r\n\r\n\u001b[0;m\u001b[K\u001b[0;34m--multiparts\u001b[0;2m (ActionMultiParts())                             \r\n\u001b[0;m\u001b[K\u001b[0;7;34m--multiparts-nested\u001b[0;2;7m (ActionMultiParts(...ActionMultiParts...))\r\n\u001b[0;m\u001b[4A\r\u001b[24C\u001b[?25h"]
+[4.566874, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[33C\u001b[K\u001b[0;4mn \r\n\r\n\r\n\r\n\u001b[0;m\u001b[K\u001b[0;34m--multiparts-nested\u001b[0;2m (ActionMultiParts(...ActionMultiParts...))\r\n\u001b[0;m\u001b[K\u001b[0;7;34m--multipartsn\u001b[0;2;7m (ActionMultiPartsN())                           \u001b[0;m\u001b[4A\r\u001b[24C\u001b[?25h"]
+[4.841226, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[21C\u001b[K--multipartsn \r\n\u001b[J\u001b[A\r\u001b[35C\u001b[?25h"]
+[4.84166, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[35C\u001b[?25h"]
+[5.111509, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[35C\u001b[0;33m'\u001b[0;m\r\u001b[36C\u001b[?25h"]
+[5.496688, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;4;33m'one='\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mone\u001b[0;m  two\u001b[1A\r\u001b[22C\u001b[?25h"]
+[6.132794, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[36C\u001b[K\u001b[0;4;33mtwo='\r\n\r\n\u001b[0;m\u001b[Kone  \u001b[0;7mtwo\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
+[6.41278, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;33m'two='\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[41C\u001b[?25h"]
+[6.412868, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[41C\u001b[?25h"]
+[6.755236, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;4;33m'two=four='\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mfour\u001b[0;m  three\u001b[1A\r\u001b[22C\u001b[?25h"]
+[7.531739, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[40C\u001b[K\u001b[0;4;33mthree='\r\n\r\n\u001b[0;m\u001b[Kfour  \u001b[0;7mthree\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
+[7.532333, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\u001b[1A\r\u001b[22C\u001b[?25h"]
+[7.850181, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;33m'two=three='\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[47C\u001b[?25h"]
+[7.850283, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[47C\u001b[?25h"]
+[7.986958, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;4;33m'two=three=five'\u001b[0;4m \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mfive\u001b[0;m  six\u001b[1A\r\u001b[22C\u001b[?25h"]
+[9.126163, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;33m'two=three=five'\u001b[0;m \r\n\u001b[J\u001b[A\r\u001b[52C\u001b[?25h"]
+[9.12627, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[52C\u001b[?25h"]
+[11.677928, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\r\u001b[6C\u001b[?25h"]
+[11.678025, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
+[11.678391, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
+[11.698688, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
+[11.698879, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
+[11.99033, "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"]
+[12.202411, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31mx\u001b[0;m\r\u001b[8C\u001b[?25h"]
+[12.202517, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"]
+[12.303582, "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"]
+[12.412681, "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"]
+[12.508844, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\u001b[?25h\u001b[?7h\u001b[?2004l\r"]
diff --git a/docs/src/carapace/defaultActions/actionMultiPartsN.md b/docs/src/carapace/defaultActions/actionMultiPartsN.md
new file mode 100644
index 0000000..a9c8845
--- /dev/null
+++ b/docs/src/carapace/defaultActions/actionMultiPartsN.md
@@ -0,0 +1,32 @@
+# ActionMultiPartsN
+
+[`ActionMultiPartsN`] is like [ActionMultiParts] but limits the number of parts to `n`.
+
+
+```go
+carapace.ActionMultiPartsN("=", 2, func(c carapace.Context) carapace.Action {
+	switch len(c.Parts) {
+	case 0:
+		return carapace.ActionValues("one", "two").Suffix("=")
+	case 1:
+		return carapace.ActionMultiParts("=", func(c carapace.Context) carapace.Action {
+			switch len(c.Parts) {
+			case 0:
+				return carapace.ActionValues("three", "four").Suffix("=")
+			case 1:
+				return carapace.ActionValues("five", "six")
+			default:
+				return carapace.ActionValues()
+			}
+		})
+	default:
+		return carapace.ActionMessage("should never happen")
+	}
+})
+```
+
+![](./actionMultiPartsN.cast)
+
+[ActionMultiParts]:./actionMultiParts.md
+[`ActionMultiPartsN`]: https://pkg.go.dev/github.com/rsteube/carapace#Action.MultipartsN
+
diff --git a/example/cmd/action.go b/example/cmd/action.go
index f6972a7..45852d6 100644
--- a/example/cmd/action.go
+++ b/example/cmd/action.go
@@ -32,6 +32,7 @@ func init() {
 	actionCmd.Flags().String("message-multiple", "", "ActionMessage()")
 	actionCmd.Flags().String("multiparts", "", "ActionMultiParts()")
 	actionCmd.Flags().String("multiparts-nested", "", "ActionMultiParts(...ActionMultiParts...)")
+	actionCmd.Flags().String("multipartsn", "", "ActionMultiPartsN()")
 	actionCmd.Flags().String("styles", "", "ActionStyles()")
 	actionCmd.Flags().String("styleconfig", "", "ActionStyleConfig()")
 	actionCmd.Flags().String("styled-values", "", "ActionStyledValues()")
@@ -126,6 +127,25 @@ func init() {
 				}
 			})
 		}),
+		"multipartsn": carapace.ActionMultiPartsN("=", 2, func(c carapace.Context) carapace.Action {
+			switch len(c.Parts) {
+			case 0:
+				return carapace.ActionValues("one", "two").Suffix("=")
+			case 1:
+				return carapace.ActionMultiParts("=", func(c carapace.Context) carapace.Action {
+					switch len(c.Parts) {
+					case 0:
+						return carapace.ActionValues("three", "four").Suffix("=")
+					case 1:
+						return carapace.ActionValues("five", "six")
+					default:
+						return carapace.ActionValues()
+					}
+				})
+			default:
+				return carapace.ActionMessage("should never happen")
+			}
+		}),
 		"styles":      carapace.ActionStyles(),
 		"styleconfig": carapace.ActionStyleConfig(),
 		"styled-values": carapace.ActionStyledValues(


Test patch:
diff --git a/example/cmd/action_test.go b/example/cmd/action_test.go
index eeed5ea..4058c7a 100644
--- a/example/cmd/action_test.go
+++ b/example/cmd/action_test.go
@@ -272,3 +272,32 @@ func TestAttached(t *testing.T) {
 				Usage("ActionMultiParts(...ActionMultiParts...)"))
 	})
 }
+
+func TestActionMultipartsN(t *testing.T) {
+	sandbox.Package(t, "github.com/rsteube/carapace/example")(func(s *sandbox.Sandbox) {
+		s.Run("action", "--multipartsn", "").
+			Expect(carapace.ActionValues("one", "two").
+				Suffix("=").
+				NoSpace('=').
+				Usage("ActionMultiPartsN()"))
+
+		s.Run("action", "--multipartsn", "o").
+			Expect(carapace.ActionValues("one").
+				Suffix("=").
+				NoSpace('=').
+				Usage("ActionMultiPartsN()"))
+
+		s.Run("action", "--multipartsn", "one=").
+			Expect(carapace.ActionValues("three", "four").
+				Prefix("one=").
+				Suffix("=").
+				NoSpace('=').
+				Usage("ActionMultiPartsN()"))
+
+		s.Run("action", "--multipartsn", "one=three=").
+			Expect(carapace.ActionValues("five", "six").
+				Prefix("one=three=").
+				NoSpace('=').
+				Usage("ActionMultiPartsN()"))
+	})
+}