Skip to content

Commit

Permalink
Merge pull request #915 from rsteube/uniquelistf
Browse files Browse the repository at this point in the history
Action: added UniqueListF
  • Loading branch information
rsteube authored Sep 14, 2023
2 parents 6f5fb57 + 51d79ab commit cd95811
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 2 deletions.
10 changes: 10 additions & 0 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,16 @@ func (a Action) UniqueList(divider string) Action {
})
}

// UniqueListF is like UniqueList but uses a function to transform values before filtering.
func (a Action) UniqueListF(divider string, f func(s string) string) Action {
return ActionMultiParts(divider, func(c Context) Action {
for i := range c.Parts {
c.Parts[i] = f(c.Parts[i])
}
return a.Filter(c.Parts...).NoSpace()
})
}

// Usage sets the usage.
func (a Action) Usage(usage string, args ...interface{}) Action {
return a.UsageF(func() string {
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- [TagF](./carapace/action/tagF.md)
- [Timeout](./carapace/action/timeout.md)
- [UniqueList](./carapace/action/uniqueList.md)
- [UniqueListF](./carapace/action/uniqueListF.md)
- [Usage](./carapace/action/usage.md)
- [UsageF](./carapace/action/usageF.md)
- [InvokedAction](./carapace/invokedAction.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/src/carapace/action/uniqueList.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ carapace.ActionValues(

![](./uniquelist.cast)

[`UniqueList`]: https://pkg.go.dev/github.com/rsteube/carapace#Action.List
[`UniqueList`]: https://pkg.go.dev/github.com/rsteube/carapace#Action.UniqueList
21 changes: 21 additions & 0 deletions docs/src/carapace/action/uniqueListF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# UniqueListF

[`UniqueListF`] is like [UniqueList] but uses a function to transform values before filtering.

```go
carapace.ActionMultiPartsN(":", 2, func(c carapace.Context) carapace.Action {
switch len(c.Parts) {
case 0:
return carapace.ActionValues("one", "two", "three")
default:
return carapace.ActionValues("1", "2", "3")
}
}).UniqueListF(",", func(s string) string {
return strings.SplitN(s, ":", 2)[0]
})
```

![](./uniquelistF.cast)

[UniqueList]:./uniqueList.md
[`UniqueListF`]: https://pkg.go.dev/github.com/rsteube/carapace#Action.UniqueListF
78 changes: 78 additions & 0 deletions docs/src/carapace/action/uniquelistF.cast
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{"version": 2, "width": 108, "height": 24, "timestamp": 1694682747, "env": {"SHELL": "elvish", "TERM": "tmux-256color"}}
[0.091087, "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.102225, "o", "\u001b[?25l\r\r\u001b[5C\u001b[?25h\u001b[?25l\r\u001b[K\r\n\u001b[0;1;36mcarapace/example\u001b[0;m on \u001b[0;1;35m uniquelistf\u001b[0;m \u001b[0;1;31m[$!?]\u001b[0;m via \u001b[0;1;36m🐹 v1.21.0 \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m❯\u001b[0;m \r\u001b[6C\u001b[?25h"]
[0.582033, "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"]
[0.582758, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[0.59958, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[0.790332, "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.940353, "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.088234, "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\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[1.088895, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[1.160982, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10C\u001b[0;31mp\u001b[0;m\r\u001b[11C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"]
[1.306839, "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.394217, "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.503183, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[13C \r\u001b[14C\u001b[?25h"]
[1.503453, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h"]
[2.279875, "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.338539, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[15Co\r\u001b[16C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[16C\u001b[?25h"]
[2.521556, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[16Cdifier \r\u001b[23C\u001b[?25h"]
[3.096331, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[23C-\r\u001b[24C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[24C\u001b[?25h"]
[3.250586, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[24C-\r\u001b[25C\u001b[?25h"]
[3.25105, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[25C\u001b[?25h"]
[3.617128, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[25Cu\r\u001b[26C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[26C\u001b[?25h"]
[3.825929, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[23C\u001b[K\u001b[0;4m--uniquelist \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7;34m--uniquelist\u001b[0;2;7m (UniqueList())\u001b[0;m \u001b[0;34m--uniquelistf\u001b[0;2m (UniqueListF())\u001b[0;m \u001b[0;34m--usage\u001b[0;2m (Usage())\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[4.550181, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[35C\u001b[K\u001b[0;4mf \r\n\r\n\u001b[0;m\u001b[K\u001b[0;34m--uniquelist\u001b[0;2m (UniqueList())\u001b[0;m \u001b[0;7;34m--uniquelistf\u001b[0;2;7m (UniqueListF())\u001b[0;m \u001b[0;34m--usage\u001b[0;2m (Usage())\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[4.995452, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[23C\u001b[K--uniquelistf \r\n\u001b[J\u001b[A\r\u001b[37C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[37C\u001b[?25h"]
[5.28154, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[37C\u001b[0;4mone\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"]
[6.194556, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[37C\u001b[Kone\r\n\u001b[J\u001b[A\r\u001b[40C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[40C\u001b[?25h"]
[6.19476, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[40C\u001b[?25h"]
[6.479322, "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"]
[6.668645, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;4;33m'one,three'\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"]
[7.731535, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[43C\u001b[K\u001b[0;4;33mwo'\r\n\r\n\u001b[0;m\u001b[Kthree \u001b[0;7mtwo\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[8.162898, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;33m'one,two'\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[46C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[46C\u001b[?25h"]
[8.573746, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[46C:\r\u001b[47C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[47C\u001b[?25h"]
[8.736582, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;4;33m'one,two:1'\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7m1\u001b[0;m 2 3\u001b[1A\r\u001b[22C\u001b[?25h"]
[9.834408, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[46C\u001b[K\u001b[0;4;33m2'\r\n\r\n\u001b[0;m\u001b[K1 \u001b[0;7m2\u001b[0;m 3\u001b[1A\r\u001b[22C\u001b[?25h"]
[10.001731, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[46C\u001b[K\u001b[0;4;33m3'\r\n\r\n\u001b[3C\u001b[0;m\u001b[K2 \u001b[0;7m3\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[10.324615, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;33m'one,two:3'\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[48C\u001b[?25h"]
[10.324989, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[48C\u001b[?25h"]
[10.626786, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[48C,\r\u001b[49C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[49C\u001b[?25h"]
[10.786717, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;4;33m'one,two:3,three'\r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mthree\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[12.787606, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;33m'one,two:3'\u001b[0;m,\r\n\u001b[J\u001b[A\r\u001b[49C\u001b[?25h"]
[12.861918, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[48C\u001b[K\r\u001b[48C\u001b[?25h"]
[13.210571, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[47C\u001b[K\r\u001b[47C\u001b[?25h"]
[13.449253, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[46C\u001b[K\r\u001b[46C\u001b[?25h"]
[13.592234, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[45C\u001b[K\r\u001b[45C\u001b[?25h"]
[13.739044, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[44C\u001b[K\r\u001b[44C\u001b[?25h"]
[13.890422, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[43C\u001b[K\r\u001b[43C\u001b[?25h"]
[14.053322, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[42C\u001b[K\r\u001b[42C\u001b[?25h"]
[14.219239, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[41C\u001b[K\r\u001b[41C\u001b[?25h"]
[14.488777, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[41C\u001b[0;33m:\u001b[0;m\r\u001b[42C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[42C\u001b[?25h"]
[15.47657, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[42C\u001b[0;33m2\u001b[0;m\r\u001b[43C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[43C\u001b[?25h"]
[15.810041, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[43C\u001b[0;33m,\u001b[0;m\r\u001b[44C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[44C\u001b[?25h"]
[15.943412, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[44C\u001b[0;33mt\u001b[0;m\r\u001b[45C\u001b[?25h"]
[16.41713, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;4;33m'one:2,three'\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"]
[17.549515, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[45C\u001b[K\u001b[0;4;33mwo'\r\n\r\n\u001b[0;m\u001b[Kthree \u001b[0;7mtwo\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[17.748346, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[45C\u001b[K\u001b[0;4;33mhree'\r\n\r\n\u001b[0;m\u001b[K\u001b[0;7mthree\u001b[0;m two\u001b[1A\r\u001b[22C\u001b[?25h"]
[18.276919, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[37C\u001b[K\u001b[0;33m'one:2,three'\u001b[0;m\r\n\u001b[J\u001b[A\r\u001b[50C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[50C\u001b[?25h"]
[19.703498, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\r\u001b[6C\u001b[?25h"]
[19.704296, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.704376, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.704803, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.70501, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.705134, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.705233, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.705377, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.70546, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.706261, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.706466, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.706616, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.706719, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.706894, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[19.722774, "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"]
[20.010591, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31me\u001b[0;m\r\u001b[7C\u001b[?25h"]
[20.010719, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[20.206386, "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"]
[20.367747, "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"]
[20.470616, "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"]
[20.582785, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\u001b[?25h\u001b[?7h\u001b[?2004l\r"]
13 changes: 12 additions & 1 deletion example/cmd/modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func init() {
modifierCmd.Flags().String("tagf", "", "TagF()")
modifierCmd.Flags().String("timeout", "", "Timeout()")
modifierCmd.Flags().String("uniquelist", "", "UniqueList()")
modifierCmd.Flags().String("uniquelistf", "", "UniqueListF()")
modifierCmd.Flags().String("usage", "", "Usage()")

rootCmd.AddCommand(modifierCmd)
Expand Down Expand Up @@ -253,7 +254,17 @@ func init() {
}
}),
"uniquelist": carapace.ActionValues("one", "two", "three").UniqueList(","),
"usage": carapace.ActionValues().Usage("explicit usage"),
"uniquelistf": carapace.ActionMultiPartsN(":", 2, func(c carapace.Context) carapace.Action {
switch len(c.Parts) {
case 0:
return carapace.ActionValues("one", "two", "three")
default:
return carapace.ActionValues("1", "2", "3")
}
}).UniqueListF(",", func(s string) string {
return strings.SplitN(s, ":", 2)[0]
}),
"usage": carapace.ActionValues().Usage("explicit usage"),
})

carapace.Gen(modifierCmd).PositionalCompletion(
Expand Down
57 changes: 57 additions & 0 deletions example/cmd/modifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,60 @@ func TestSplitP(t *testing.T) {
Usage("SplitP()"))
})
}

func TestUniqueList(t *testing.T) {
sandbox.Package(t, "github.com/rsteube/carapace/example")(func(s *sandbox.Sandbox) {
s.Run("modifier", "--uniquelist", "").
Expect(carapace.ActionValues(
"one",
"two",
"three",
).NoSpace().
Usage("UniqueList()"))

s.Run("modifier", "--uniquelist", "two,").
Expect(carapace.ActionValues(
"one",
"three",
).Prefix("two,").
NoSpace().
Usage("UniqueList()"))
})
}

func TestUniqueListF(t *testing.T) {
sandbox.Package(t, "github.com/rsteube/carapace/example")(func(s *sandbox.Sandbox) {
s.Run("modifier", "--uniquelistf", "").
Expect(carapace.ActionValues(
"one",
"two",
"three",
).NoSpace().
Usage("UniqueListF()"))

s.Run("modifier", "--uniquelistf", "two,").
Expect(carapace.ActionValues(
"one",
"three",
).Prefix("two,").
NoSpace().
Usage("UniqueListF()"))

s.Run("modifier", "--uniquelistf", "two:").
Expect(carapace.ActionValues(
"1",
"2",
"3",
).Prefix("two:").
NoSpace().
Usage("UniqueListF()"))

s.Run("modifier", "--uniquelistf", "two:1,").
Expect(carapace.ActionValues(
"one",
"three",
).Prefix("two:1,").
NoSpace().
Usage("UniqueListF()"))
})
}

0 comments on commit cd95811

Please sign in to comment.