Skip to content

Commit

Permalink
Merge pull request #838 from rsteube/add-actionmultipartsn
Browse files Browse the repository at this point in the history
added ActionMultiPartsN
  • Loading branch information
rsteube authored Jul 23, 2023
2 parents e1959b7 + ad70d97 commit c05acf1
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 13 deletions.
30 changes: 17 additions & 13 deletions defaultActions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
59 changes: 59 additions & 0 deletions docs/src/carapace/defaultActions/actionMultiPartsN.cast
Original file line number Diff line number Diff line change
@@ -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"]
32 changes: 32 additions & 0 deletions docs/src/carapace/defaultActions/actionMultiPartsN.md
Original file line number Diff line number Diff line change
@@ -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

20 changes: 20 additions & 0 deletions example/cmd/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()")
Expand Down Expand Up @@ -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(
Expand Down
29 changes: 29 additions & 0 deletions example/cmd/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()"))
})
}

0 comments on commit c05acf1

Please sign in to comment.