Skip to content

Commit

Permalink
InvokedAction: private composition
Browse files Browse the repository at this point in the history
  • Loading branch information
rsteube committed Jan 11, 2024
1 parent f8cc742 commit 287e348
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 70 deletions.
38 changes: 19 additions & 19 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (a Action) Cache(timeout time.Duration, keys ...pkgcache.Key) Action {
}

invokedAction := (Action{callback: cachedCallback}).Invoke(c)
if invokedAction.meta.Messages.IsEmpty() {
if invokedAction.action.meta.Messages.IsEmpty() {
if cacheFile, err := cache.File(file, line, keys...); err == nil { // regenerate as cache keys might have changed due to invocation
_ = cache.Write(cacheFile, invokedAction.export())
}
Expand Down Expand Up @@ -122,7 +122,7 @@ func (a Action) Invoke(c Context) InvokedAction {

if a.rawValues == nil && a.callback != nil {
result := a.callback(c).Invoke(c)
result.meta.Merge(a.meta)
result.action.meta.Merge(a.meta)
return result
}
return InvokedAction{a}
Expand Down Expand Up @@ -154,7 +154,7 @@ func (a Action) MultiPartsP(delimiter string, pattern string, f func(placeholder
staticMatches := make(map[int]bool)

path:
for index, value := range invoked.rawValues {
for index, value := range invoked.action.rawValues {
segments := strings.Split(value.Value, delimiter)
segment:
for index, segment := range segments {
Expand Down Expand Up @@ -185,7 +185,7 @@ func (a Action) MultiPartsP(delimiter string, pattern string, f func(placeholder

// store segment as path matched so far and this is currently being completed
if len(segments) == (len(c.Parts) + 1) {
matchedSegments[segments[len(c.Parts)]] = invoked.rawValues[index]
matchedSegments[segments[len(c.Parts)]] = invoked.action.rawValues[index]
} else {
matchedSegments[segments[len(c.Parts)]+delimiter] = common.RawValue{}
}
Expand All @@ -200,8 +200,8 @@ func (a Action) MultiPartsP(delimiter string, pattern string, f func(placeholder
}
actions = append(actions, ActionCallback(func(c Context) Action {
invoked := f(trimmedKey, matchedData).Invoke(c).Suffix(suffix)
for index := range invoked.rawValues {
invoked.rawValues[index].Display += suffix
for index := range invoked.action.rawValues {
invoked.action.rawValues[index].Display += suffix
}
return invoked.ToA()
}))
Expand All @@ -211,7 +211,7 @@ func (a Action) MultiPartsP(delimiter string, pattern string, f func(placeholder
}

a := Batch(actions...).ToA()
a.meta.Merge(invoked.meta)
a.meta.Merge(invoked.action.meta)
return a
})
})
Expand Down Expand Up @@ -310,19 +310,19 @@ func (a Action) split(pipelines bool) Action {
}

invoked := a.Invoke(c)
for index, value := range invoked.rawValues {
if !invoked.meta.Nospace.Matches(value.Value) || strings.Contains(value.Value, " ") { // TODO special characters
for index, value := range invoked.action.rawValues {
if !invoked.action.meta.Nospace.Matches(value.Value) || strings.Contains(value.Value, " ") { // TODO special characters
switch tokens.CurrentToken().State {
case shlex.QUOTING_ESCAPING_STATE:
invoked.rawValues[index].Value = fmt.Sprintf(`"%v"`, strings.ReplaceAll(value.Value, `"`, `\"`))
invoked.action.rawValues[index].Value = fmt.Sprintf(`"%v"`, strings.ReplaceAll(value.Value, `"`, `\"`))
case shlex.QUOTING_STATE:
invoked.rawValues[index].Value = fmt.Sprintf(`'%v'`, strings.ReplaceAll(value.Value, `'`, `'"'"'`))
invoked.action.rawValues[index].Value = fmt.Sprintf(`'%v'`, strings.ReplaceAll(value.Value, `'`, `'"'"'`))
default:
invoked.rawValues[index].Value = strings.Replace(value.Value, ` `, `\ `, -1)
invoked.action.rawValues[index].Value = strings.Replace(value.Value, ` `, `\ `, -1)
}
}
if !invoked.meta.Nospace.Matches(value.Value) {
invoked.rawValues[index].Value += " "
if !invoked.action.meta.Nospace.Matches(value.Value) {
invoked.action.rawValues[index].Value += " "
}
}
return invoked.Prefix(prefix).ToA().NoSpace()
Expand All @@ -346,8 +346,8 @@ func (a Action) Style(s string) Action {
func (a Action) StyleF(f func(s string, sc style.Context) string) Action {
return ActionCallback(func(c Context) Action {
invoked := a.Invoke(c)
for index, v := range invoked.rawValues {
invoked.rawValues[index].Style = f(v.Value, c)
for index, v := range invoked.action.rawValues {
invoked.action.rawValues[index].Style = f(v.Value, c)
}
return invoked.ToA()
})
Expand Down Expand Up @@ -379,7 +379,7 @@ func (a Action) Suffix(suffix string) Action {
func (a Action) Suppress(expr ...string) Action {
return ActionCallback(func(c Context) Action {
invoked := a.Invoke(c)
if err := invoked.meta.Messages.Suppress(expr...); err != nil {
if err := invoked.action.meta.Messages.Suppress(expr...); err != nil {
return ActionMessage(err.Error())
}
return invoked.ToA()
Expand All @@ -403,8 +403,8 @@ func (a Action) Tag(tag string) Action {
func (a Action) TagF(f func(s string) string) Action {
return ActionCallback(func(c Context) Action {
invoked := a.Invoke(c)
for index, v := range invoked.rawValues {
invoked.rawValues[index].Tag = f(v.Value)
for index, v := range invoked.action.rawValues {
invoked.action.rawValues[index].Tag = f(v.Value)
}
return invoked.ToA()
})
Expand Down
24 changes: 12 additions & 12 deletions action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ func init() {
}

func assertEqual(t *testing.T, expected, actual InvokedAction) {
sort.Sort(common.ByValue(expected.rawValues))
sort.Sort(common.ByValue(actual.rawValues))
sort.Sort(common.ByValue(expected.action.rawValues))
sort.Sort(common.ByValue(actual.action.rawValues))

e, _ := json.MarshalIndent(expected.rawValues, "", " ")
a, _ := json.MarshalIndent(actual.rawValues, "", " ")
e, _ := json.MarshalIndent(expected.action.rawValues, "", " ")
a, _ := json.MarshalIndent(actual.action.rawValues, "", " ")
assert.Equal(t, string(e), string(a))

eMeta, _ := json.MarshalIndent(expected.meta, "", " ")
aMeta, _ := json.MarshalIndent(actual.meta, "", " ")
eMeta, _ := json.MarshalIndent(expected.action.meta, "", " ")
aMeta, _ := json.MarshalIndent(actual.action.meta, "", " ")
assert.Equal(t, string(eMeta), string(aMeta))
}

func assertNotEqual(t *testing.T, expected, actual InvokedAction) {
sort.Sort(common.ByValue(expected.rawValues))
sort.Sort(common.ByValue(actual.rawValues))
sort.Sort(common.ByValue(expected.action.rawValues))
sort.Sort(common.ByValue(actual.action.rawValues))

e, _ := json.MarshalIndent(expected.rawValues, "", " ")
a, _ := json.MarshalIndent(actual.rawValues, "", " ")
e, _ := json.MarshalIndent(expected.action.rawValues, "", " ")
a, _ := json.MarshalIndent(actual.action.rawValues, "", " ")

if string(e) == string(a) {
t.Errorf("should differ:\n%v", a)
Expand Down Expand Up @@ -89,7 +89,7 @@ func TestSkipCache(t *testing.T) {
if !a.meta.Messages.IsEmpty() {
t.Fatal("uninvoked action should not contain messages")
}
if a.Invoke(Context{}).meta.Messages.IsEmpty() {
if a.Invoke(Context{}).action.meta.Messages.IsEmpty() {
t.Fatal("invoked action should contain messages")
}
}
Expand All @@ -108,7 +108,7 @@ func TestNoSpace(t *testing.T) {
if a.meta.Nospace.Matches("x") {
t.Fatal("uninvoked nospace should not match")
}
if !a.Invoke(Context{}).meta.Nospace.Matches("x") {
if !a.Invoke(Context{}).action.meta.Nospace.Matches("x") {
t.Fatal("invoked nospace should match")
}
}
Expand Down
8 changes: 4 additions & 4 deletions compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func registerFlagCompletion(cmd *cobra.Command) {
}

func cobraValuesFor(action InvokedAction) []string {
result := make([]string, len(action.rawValues))
for index, r := range action.rawValues {
result := make([]string, len(action.action.rawValues))
for index, r := range action.action.rawValues {
if r.Description != "" {
result[index] = fmt.Sprintf("%v\t%v", r.Value, r.Description)
} else {
Expand All @@ -54,8 +54,8 @@ func cobraValuesFor(action InvokedAction) []string {

func cobraDirectiveFor(action InvokedAction) cobra.ShellCompDirective {
directive := cobra.ShellCompDirectiveNoFileComp
for _, val := range action.rawValues {
if action.meta.Nospace.Matches(val.Value) {
for _, val := range action.action.rawValues {
if action.action.meta.Nospace.Matches(val.Value) {
directive = directive | cobra.ShellCompDirectiveNoSpace
break
}
Expand Down
62 changes: 31 additions & 31 deletions invokedAction.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,68 +11,68 @@ import (

// InvokedAction is a logical alias for an Action whose (nested) callback was invoked.
type InvokedAction struct {
Action
action Action
}

func (a InvokedAction) export() export.Export {
return export.Export{Meta: a.meta, Values: a.rawValues}
func (ia InvokedAction) export() export.Export {
return export.Export{Meta: ia.action.meta, Values: ia.action.rawValues}
}

// Filter filters given values.
//
// a := carapace.ActionValues("A", "B", "C").Invoke(c)
// b := a.Filter([]string{"B"}) // ["A", "C"]
func (a InvokedAction) Filter(values ...string) InvokedAction {
a.rawValues = a.rawValues.Filter(values...)
return a
func (ia InvokedAction) Filter(values ...string) InvokedAction {
ia.action.rawValues = ia.action.rawValues.Filter(values...)
return ia
}

// Merge merges InvokedActions (existing values are overwritten)
//
// a := carapace.ActionValues("A", "B").Invoke(c)
// b := carapace.ActionValues("B", "C").Invoke(c)
// c := a.Merge(b) // ["A", "B", "C"]
func (a InvokedAction) Merge(others ...InvokedAction) InvokedAction {
for _, other := range append([]InvokedAction{a}, others...) {
a.rawValues = append(a.rawValues, other.rawValues...)
a.meta.Merge(other.meta)
func (ia InvokedAction) Merge(others ...InvokedAction) InvokedAction {
for _, other := range append([]InvokedAction{ia}, others...) {
ia.action.rawValues = append(ia.action.rawValues, other.action.rawValues...)
ia.action.meta.Merge(other.action.meta)
}
a.rawValues = a.rawValues.Unique()
return a
ia.action.rawValues = ia.action.rawValues.Unique()
return ia
}

// Prefix adds a prefix to values (only the ones inserted, not the display values)
//
// carapace.ActionValues("melon", "drop", "fall").Invoke(c).Prefix("water")
func (a InvokedAction) Prefix(prefix string) InvokedAction {
for index, val := range a.rawValues {
a.rawValues[index].Value = prefix + val.Value
func (ia InvokedAction) Prefix(prefix string) InvokedAction {
for index, val := range ia.action.rawValues {
ia.action.rawValues[index].Value = prefix + val.Value
}
return a
return ia
}

// Retain retains given values.
//
// a := carapace.ActionValues("A", "B", "C").Invoke(c)
// b := a.Retain([]string{"A", "C"}) // ["A", "C"]
func (a InvokedAction) Retain(values ...string) InvokedAction {
a.rawValues = a.rawValues.Retain(values...)
return a
func (ia InvokedAction) Retain(values ...string) InvokedAction {
ia.action.rawValues = ia.action.rawValues.Retain(values...)
return ia
}

// Suffix adds a suffx to values (only the ones inserted, not the display values)
//
// carapace.ActionValues("apple", "melon", "orange").Invoke(c).Suffix("juice")
func (a InvokedAction) Suffix(suffix string) InvokedAction {
for index, val := range a.rawValues {
a.rawValues[index].Value = val.Value + suffix
func (ia InvokedAction) Suffix(suffix string) InvokedAction {
for index, val := range ia.action.rawValues {
ia.action.rawValues[index].Value = val.Value + suffix
}
return a
return ia
}

// ToA casts an InvokedAction to Action.
func (a InvokedAction) ToA() Action {
return a.Action
func (ia InvokedAction) ToA() Action {
return ia.action
}

func tokenize(s string, dividers ...string) []string {
Expand All @@ -95,12 +95,12 @@ func tokenize(s string, dividers ...string) []string {
//
// a := carapace.ActionValues("A/B/C", "A/C", "B/C", "C").Invoke(c)
// b := a.ToMultiPartsA("/") // completes segments separately (first one is ["A/", "B/", "C"])
func (a InvokedAction) ToMultiPartsA(dividers ...string) Action {
func (ia InvokedAction) ToMultiPartsA(dividers ...string) Action {
return ActionCallback(func(c Context) Action {
splittedCV := tokenize(c.Value, dividers...)

uniqueVals := make(map[string]common.RawValue)
for _, val := range a.rawValues {
for _, val := range ia.action.rawValues {
if match.HasPrefix(val.Value, c.Value) {
if splitted := tokenize(val.Value, dividers...); len(splitted) >= len(splittedCV) {
v := strings.Join(splitted[:len(splittedCV)], "")
Expand Down Expand Up @@ -145,14 +145,14 @@ func (a InvokedAction) ToMultiPartsA(dividers ...string) Action {
})
}

func (a InvokedAction) value(shell string, value string) string {
return _shell.Value(shell, value, a.meta, a.rawValues)
func (ia InvokedAction) value(shell string, value string) string {
return _shell.Value(shell, value, ia.action.meta, ia.action.rawValues)
}

func init() {
common.FromInvokedAction = func(i interface{}) (common.Meta, common.RawValues) {
if a, ok := i.(InvokedAction); ok {
return a.meta, a.rawValues
if invoked, ok := i.(InvokedAction); ok {
return invoked.action.meta, invoked.action.rawValues
}
return common.Meta{}, nil
}
Expand Down
8 changes: 4 additions & 4 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ func (s _storage) getFlag(cmd *cobra.Command, name string) Action {

return ActionCallback(func(c Context) Action { // TODO verify order of execution is correct
invoked := a.Invoke(c)
if invoked.meta.Usage == "" {
invoked.meta.Usage = flag.Usage
if invoked.action.meta.Usage == "" {
invoked.action.meta.Usage = flag.Usage
}
return invoked.ToA()
})
Expand Down Expand Up @@ -177,8 +177,8 @@ func (s _storage) getPositional(cmd *cobra.Command, index int) Action {

return ActionCallback(func(c Context) Action {
invoked := a.Invoke(c)
if invoked.meta.Usage == "" && len(strings.Fields(cmd.Use)) > 1 {
invoked.meta.Usage = cmd.Use
if invoked.action.meta.Usage == "" && len(strings.Fields(cmd.Use)) > 1 {
invoked.action.meta.Usage = cmd.Use
}
return invoked.ToA()
})
Expand Down

0 comments on commit 287e348

Please sign in to comment.