mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-30 03:23:08 +03:00
Support using command output directly in menuFromCommand custom command prompt
The menuFromCommand option is a little complicated, so I'm adding an easy way to just use the command output directly, where each line becomes a suggestion, as-is. Now that we support suggestions in the input prompt, there's less of a need for menuFromCommand, but it probably still serves some purpose. In future I want to support this filter/valueFormat/labelFormat thing for suggestions too. I would like to think a little more about the interface though: is using a regex like we currently do really the simplest approach?
This commit is contained in:
@ -210,7 +210,7 @@ func (self *HandlerCreator) menuPromptFromCommand(prompt *config.CustomCommandPr
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
menuItems := slices.Map(candidates, func(candidate *commandMenuEntry) *types.MenuItem {
|
||||
menuItems := slices.Map(candidates, func(candidate *commandMenuItem) *types.MenuItem {
|
||||
return &types.MenuItem{
|
||||
LabelColumns: []string{candidate.label},
|
||||
OnPress: func() error {
|
||||
|
@ -22,12 +22,41 @@ func NewMenuGenerator(c *common.Common) *MenuGenerator {
|
||||
return &MenuGenerator{c: c}
|
||||
}
|
||||
|
||||
type commandMenuEntry struct {
|
||||
type commandMenuItem struct {
|
||||
label string
|
||||
value string
|
||||
}
|
||||
|
||||
func (self *MenuGenerator) call(commandOutput, filter, valueFormat, labelFormat string) ([]*commandMenuEntry, error) {
|
||||
func (self *MenuGenerator) call(commandOutput, filter, valueFormat, labelFormat string) ([]*commandMenuItem, error) {
|
||||
menuItemFromLine, err := self.getMenuItemFromLinefn(filter, valueFormat, labelFormat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
menuItems := []*commandMenuItem{}
|
||||
for _, line := range strings.Split(commandOutput, "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
menuItem, err := menuItemFromLine(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
menuItems = append(menuItems, menuItem)
|
||||
}
|
||||
|
||||
return menuItems, nil
|
||||
}
|
||||
|
||||
func (self *MenuGenerator) getMenuItemFromLinefn(filter string, valueFormat string, labelFormat string) (func(line string) (*commandMenuItem, error), error) {
|
||||
if filter == "" && valueFormat == "" && labelFormat == "" {
|
||||
// showing command output lines as-is in suggestions panel
|
||||
return func(line string) (*commandMenuItem, error) {
|
||||
return &commandMenuItem{label: line, value: line}, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
regex, err := regexp.Compile(filter)
|
||||
if err != nil {
|
||||
return nil, errors.New("unable to parse filter regex, error: " + err.Error())
|
||||
@ -51,37 +80,25 @@ func (self *MenuGenerator) call(commandOutput, filter, valueFormat, labelFormat
|
||||
labelTemplate = valueTemplate
|
||||
}
|
||||
|
||||
candidates := []*commandMenuEntry{}
|
||||
for _, line := range strings.Split(commandOutput, "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
candidate, err := self.generateMenuCandidate(
|
||||
return func(line string) (*commandMenuItem, error) {
|
||||
return self.generateMenuItem(
|
||||
line,
|
||||
regex,
|
||||
valueTemplate,
|
||||
labelTemplate,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candidates = append(candidates, candidate)
|
||||
}
|
||||
|
||||
return candidates, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *MenuGenerator) generateMenuCandidate(
|
||||
func (self *MenuGenerator) generateMenuItem(
|
||||
line string,
|
||||
regex *regexp.Regexp,
|
||||
valueTemplate *TrimmerTemplate,
|
||||
labelTemplate *TrimmerTemplate,
|
||||
) (*commandMenuEntry, error) {
|
||||
) (*commandMenuItem, error) {
|
||||
tmplData := self.parseLine(line, regex)
|
||||
|
||||
entry := &commandMenuEntry{}
|
||||
entry := &commandMenuItem{}
|
||||
|
||||
var err error
|
||||
entry.value, err = valueTemplate.execute(tmplData)
|
||||
|
@ -14,7 +14,7 @@ func TestMenuGenerator(t *testing.T) {
|
||||
filter string
|
||||
valueFormat string
|
||||
labelFormat string
|
||||
test func([]*commandMenuEntry, error)
|
||||
test func([]*commandMenuItem, error)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
@ -24,7 +24,7 @@ func TestMenuGenerator(t *testing.T) {
|
||||
"(?P<remote>[a-z_]+)/(?P<branch>.*)",
|
||||
"{{ .branch }}",
|
||||
"Remote: {{ .remote }}",
|
||||
func(actualEntry []*commandMenuEntry, err error) {
|
||||
func(actualEntry []*commandMenuItem, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1", actualEntry[0].value)
|
||||
assert.EqualValues(t, "Remote: upstream", actualEntry[0].label)
|
||||
@ -36,7 +36,7 @@ func TestMenuGenerator(t *testing.T) {
|
||||
"(?P<remote>[a-z]*)/(?P<branch>.*)",
|
||||
"{{ .branch }}|{{ .remote }}",
|
||||
"",
|
||||
func(actualEntry []*commandMenuEntry, err error) {
|
||||
func(actualEntry []*commandMenuItem, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].value)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].label)
|
||||
@ -48,12 +48,36 @@ func TestMenuGenerator(t *testing.T) {
|
||||
"(?P<remote>[a-z]*)/(?P<branch>.*)",
|
||||
"{{ .group_2 }}|{{ .group_1 }}",
|
||||
"Remote: {{ .group_1 }}",
|
||||
func(actualEntry []*commandMenuEntry, err error) {
|
||||
func(actualEntry []*commandMenuItem, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].value)
|
||||
assert.EqualValues(t, "Remote: upstream", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
{
|
||||
"No named groups",
|
||||
"upstream/pr-1",
|
||||
"([a-z]*)/(.*)",
|
||||
"{{ .group_2 }}|{{ .group_1 }}",
|
||||
"Remote: {{ .group_1 }}",
|
||||
func(actualEntry []*commandMenuItem, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].value)
|
||||
assert.EqualValues(t, "Remote: upstream", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
{
|
||||
"No filter",
|
||||
"upstream/pr-1",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
func(actualEntry []*commandMenuItem, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "upstream/pr-1", actualEntry[0].value)
|
||||
assert.EqualValues(t, "upstream/pr-1", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
|
Reference in New Issue
Block a user