mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-03-19 21:28:28 +02:00
Minor changes to menuFromCommand prompts
This commit is contained in:
parent
a8ec044f0e
commit
906ec30cac
@ -47,8 +47,8 @@ customCommands:
|
||||
title: 'Remote branch:'
|
||||
command: 'git branch -r --list {{index .PromptResponses 0}}/*'
|
||||
filter: '.*{{index .PromptResponses 0}}/(?P<branch>.*)'
|
||||
itemFormat: '{{ .branch }}'
|
||||
descriptionFormat: ''
|
||||
valueFormat: '{{ .branch }}'
|
||||
labelFormat: ''
|
||||
```
|
||||
|
||||
Looking at the command assigned to the 'n' key, here's what the result looks like:
|
||||
@ -103,11 +103,11 @@ The permitted prompt fields are:
|
||||
| | menu options | |
|
||||
| filter | (only applicable to 'menuFromCommand' prompts) the regexp to run specifying | yes |
|
||||
| | groups which are going to be kept from the command's output | |
|
||||
| itemFormat | (only applicable to 'menuFromCommand' prompts) how to format matched groups from | yes |
|
||||
| valueFormat | (only applicable to 'menuFromCommand' prompts) how to format matched groups from | yes |
|
||||
| | the filter to construct a menu item. You can use named groups, | yes |
|
||||
| | or `{{ .group_GROUPID }}`. | |
|
||||
| | PS: named groups keep first match only | yes |
|
||||
| descriptionFormat | (only applicable to 'menuFromCommand' prompts) how to format matched groups from | yes |
|
||||
| labelFormat | (only applicable to 'menuFromCommand' prompts) how to format matched groups from | yes |
|
||||
| | the filter to construct a menu item's description. You can use named groups, | yes |
|
||||
| | or `{{ .group_GROUPID }}`. | |
|
||||
| | PS: named groups keep first match only | yes |
|
||||
|
@ -283,10 +283,10 @@ type CustomCommandPrompt struct {
|
||||
Options []CustomCommandMenuOption
|
||||
|
||||
// this only applies to menuFromCommand
|
||||
Command string `yaml:"command"`
|
||||
Filter string `yaml:"filter"`
|
||||
TFormat string `yaml:"itemFormat"`
|
||||
DFormat string `yaml:"descriptionFormat"`
|
||||
Command string `yaml:"command"`
|
||||
Filter string `yaml:"filter"`
|
||||
ValueFormat string `yaml:"valueFormat"`
|
||||
LabelFormat string `yaml:"labelFormat"`
|
||||
}
|
||||
|
||||
type CustomCommandMenuOption struct {
|
||||
|
@ -33,6 +33,11 @@ type CustomCommandObjects struct {
|
||||
PromptResponses []string
|
||||
}
|
||||
|
||||
type CommandMenuEntry struct {
|
||||
label string
|
||||
value string
|
||||
}
|
||||
|
||||
func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (string, error) {
|
||||
objects := CustomCommandObjects{
|
||||
SelectedFile: gui.getSelectedFile(),
|
||||
@ -118,22 +123,21 @@ func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses []
|
||||
return gui.createMenu(title, menuItems, createMenuOptions{showCancel: true})
|
||||
}
|
||||
|
||||
func (gui *Gui) GenerateMenuCandidates(commandOutput string, filter string, tFormat string, dFormat string) ([]string, []string, error) {
|
||||
candidates := []string{}
|
||||
descriptions := []string{}
|
||||
func (gui *Gui) GenerateMenuCandidates(commandOutput, filter, valueFormat, labelFormat string) ([]CommandMenuEntry, error) {
|
||||
candidates := []CommandMenuEntry{}
|
||||
reg, err := regexp.Compile(filter)
|
||||
if err != nil {
|
||||
return candidates, descriptions, gui.surfaceError(errors.New("unable to parse filter regex, error: " + err.Error()))
|
||||
return candidates, gui.surfaceError(errors.New("unable to parse filter regex, error: " + err.Error()))
|
||||
}
|
||||
buffTitle := bytes.NewBuffer(nil)
|
||||
tempTitle, err := template.New("format").Parse(tFormat)
|
||||
buffItem := bytes.NewBuffer(nil)
|
||||
tempItem, err := template.New("format").Parse(valueFormat)
|
||||
if err != nil {
|
||||
return candidates, descriptions, gui.surfaceError(errors.New("unable to parse item format, error: " + err.Error()))
|
||||
return candidates, gui.surfaceError(errors.New("unable to parse item format, error: " + err.Error()))
|
||||
}
|
||||
buffDescr := bytes.NewBuffer(nil)
|
||||
tempDescr, err := template.New("format").Parse(dFormat)
|
||||
tempDescr, err := template.New("format").Parse(labelFormat)
|
||||
if err != nil {
|
||||
return candidates, descriptions, gui.surfaceError(errors.New("unable to parse item description format, error: " + err.Error()))
|
||||
return candidates, gui.surfaceError(errors.New("unable to parse item description format, error: " + err.Error()))
|
||||
}
|
||||
for _, str := range strings.Split(string(commandOutput), "\n") {
|
||||
if str == "" {
|
||||
@ -152,21 +156,28 @@ func (gui *Gui) GenerateMenuCandidates(commandOutput string, filter string, tFor
|
||||
}
|
||||
}
|
||||
}
|
||||
err = tempTitle.Execute(buffTitle, tmplData)
|
||||
err = tempItem.Execute(buffItem, tmplData)
|
||||
if err != nil {
|
||||
return candidates, descriptions, gui.surfaceError(err)
|
||||
return candidates, gui.surfaceError(err)
|
||||
}
|
||||
err = tempDescr.Execute(buffDescr, tmplData)
|
||||
if err != nil {
|
||||
return candidates, descriptions, gui.surfaceError(err)
|
||||
return candidates, gui.surfaceError(err)
|
||||
}
|
||||
|
||||
candidates = append(candidates, strings.TrimSpace(buffTitle.String()))
|
||||
descriptions = append(descriptions, strings.TrimSpace(buffDescr.String()))
|
||||
buffTitle.Reset()
|
||||
// Populate menu entry
|
||||
// label formatted as labelFormat
|
||||
// value as valueFormat
|
||||
entry := CommandMenuEntry{
|
||||
strings.TrimSpace(buffDescr.String()),
|
||||
//"Description",
|
||||
strings.TrimSpace(buffItem.String()),
|
||||
}
|
||||
candidates = append(candidates, entry)
|
||||
buffItem.Reset()
|
||||
buffDescr.Reset()
|
||||
}
|
||||
return candidates, descriptions, err
|
||||
return candidates, err
|
||||
}
|
||||
|
||||
func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error {
|
||||
@ -189,7 +200,7 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR
|
||||
}
|
||||
|
||||
// Need to make a menu out of what the cmd has displayed
|
||||
candidates, descriptions, err := gui.GenerateMenuCandidates(message, filter, prompt.TFormat, prompt.DFormat)
|
||||
candidates, err := gui.GenerateMenuCandidates(message, filter, prompt.ValueFormat, prompt.LabelFormat)
|
||||
if err != nil {
|
||||
return gui.surfaceError(err)
|
||||
}
|
||||
@ -198,9 +209,9 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR
|
||||
for i := range candidates {
|
||||
menuItems[i] = &menuItem{
|
||||
// Put in candidate and its description
|
||||
displayStrings: []string{candidates[i], style.FgYellow.Sprint(descriptions[i])},
|
||||
displayStrings: []string{candidates[i].value, style.FgYellow.Sprint(candidates[i].label)},
|
||||
onPress: func() error {
|
||||
promptResponses[responseIdx] = candidates[i]
|
||||
promptResponses[responseIdx] = candidates[i].value
|
||||
return wrappedF()
|
||||
},
|
||||
}
|
||||
|
@ -83,12 +83,12 @@ func runCmdHeadless(cmd *exec.Cmd) error {
|
||||
|
||||
func TestGuiGenerateMenuCandidates(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
cmdOut string
|
||||
filter string
|
||||
tFormat string
|
||||
dFormat string
|
||||
test func([]string, []string, error)
|
||||
testName string
|
||||
cmdOut string
|
||||
filter string
|
||||
valueFormat string
|
||||
labelFormat string
|
||||
test func([]CommandMenuEntry, error)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
@ -98,10 +98,10 @@ func TestGuiGenerateMenuCandidates(t *testing.T) {
|
||||
"(?P<remote>[a-z_]+)/(?P<branch>.*)",
|
||||
"{{ .branch }}",
|
||||
"Remote: {{ .remote }}",
|
||||
func(actualCandidate []string, actualDescr []string, err error) {
|
||||
func(actualEntry []CommandMenuEntry, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1", actualCandidate[0])
|
||||
assert.EqualValues(t, "Remote: upstream", actualDescr[0])
|
||||
assert.EqualValues(t, "pr-1", actualEntry[0].value)
|
||||
assert.EqualValues(t, "Remote: upstream", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -110,10 +110,10 @@ func TestGuiGenerateMenuCandidates(t *testing.T) {
|
||||
"(?P<remote>[a-z]*)/(?P<branch>.*)",
|
||||
"{{ .branch }}|{{ .remote }}",
|
||||
"",
|
||||
func(actualCandidate []string, actualDescr []string, err error) {
|
||||
func(actualEntry []CommandMenuEntry, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualCandidate[0])
|
||||
assert.EqualValues(t, "", actualDescr[0])
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].value)
|
||||
assert.EqualValues(t, "", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -122,17 +122,17 @@ func TestGuiGenerateMenuCandidates(t *testing.T) {
|
||||
"(?P<remote>[a-z]*)/(?P<branch>.*)",
|
||||
"{{ .group_2 }}|{{ .group_1 }}",
|
||||
"Remote: {{ .group_1 }}",
|
||||
func(actualCandidate []string, actualDescr []string, err error) {
|
||||
func(actualEntry []CommandMenuEntry, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, "pr-1|upstream", actualCandidate[0])
|
||||
assert.EqualValues(t, "Remote: upstream", actualDescr[0])
|
||||
assert.EqualValues(t, "pr-1|upstream", actualEntry[0].value)
|
||||
assert.EqualValues(t, "Remote: upstream", actualEntry[0].label)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
s.test(NewDummyGui().GenerateMenuCandidates(s.cmdOut, s.filter, s.tFormat, s.dFormat))
|
||||
s.test(NewDummyGui().GenerateMenuCandidates(s.cmdOut, s.filter, s.valueFormat, s.labelFormat))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user