Skip to content

Commit deb1cbe

Browse files
committed
Combine customCommand's stream and showOutput fields into a single output enum
It doesn't make sense to set both to true, so combine them into one property.
1 parent 8b0b153 commit deb1cbe

File tree

8 files changed

+92
-32
lines changed

8 files changed

+92
-32
lines changed

docs/Custom_Command_Keybindings.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ For a given custom command, here are the allowed fields:
5757
| prompts | A list of prompts that will request user input before running the final command | no |
5858
| loadingText | Text to display while waiting for command to finish | no |
5959
| description | Label for the custom command when displayed in the keybindings menu | no |
60-
| stream | Whether you want to stream the command's output to the Command Log panel | no |
61-
| pty | Whether you want to run the command in a pseudo terminal (pty). This can be useful for commands that produce colored output when the output is a terminal. Only used when `stream` is also true. Use with care: some commands may expect the terminal to have capabilities that lazygit's pty doesn't. | no |
62-
| showOutput | Whether you want to show the command's output in a popup within Lazygit | no |
63-
| outputTitle | The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title. | no |
60+
| output | Where the output of the command should go. 'none' discards it, 'log' shows it in the command log, and 'popup' shows it in a popup. | no |
61+
| pty | Whether you want to run the command in a pseudo terminal (pty). This can be useful for commands that produce colored output when the output is a terminal. Only used when ouput is set to 'log', and subprocess is false. Use with care: some commands may expect the terminal to have capabilities that lazygit's pty doesn't. | no |
62+
| outputTitle | The title to display in the popup panel if output is set to 'popup'. If left unset, the command will be used as the title. | no |
6463
| after | Actions to take after the command has completed | no |
6564

6665
Here are the options for the `after` key:
@@ -366,7 +365,7 @@ If you use the commandMenu property, none of the other properties except key and
366365

367366
## Debugging
368367

369-
If you want to verify that your command actually does what you expect, you can wrap it in an 'echo' call and set `showOutput: true` so that it doesn't actually execute the command but you can see how the placeholders were resolved.
368+
If you want to verify that your command actually does what you expect, you can wrap it in an 'echo' call and set `output: popup` so that it doesn't actually execute the command but you can see how the placeholders were resolved.
370369

371370
## More Examples
372371

pkg/config/app_config.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ func computeMigratedConfig(path string, content []byte) ([]byte, error) {
281281
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
282282
}
283283

284+
err = changeCustomCommandStreamAndOutputToOutputEnum(&rootNode)
285+
if err != nil {
286+
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
287+
}
288+
284289
// Add more migrations here...
285290

286291
if !reflect.DeepEqual(rootNode, originalCopy) {
@@ -341,6 +346,41 @@ func changeCommitPrefixesMap(rootNode *yaml.Node) error {
341346
})
342347
}
343348

349+
func changeCustomCommandStreamAndOutputToOutputEnum(rootNode *yaml.Node) error {
350+
return yaml_utils.Walk(rootNode, func(node *yaml.Node, path string) {
351+
// We are being lazy here and rely on the fact that the only mapping
352+
// nodes in the tree under customCommands are actual custom commands. If
353+
// this ever changes (e.g. because we add a struct field to
354+
// customCommand), then we need to change this to iterate properly.
355+
if strings.HasPrefix(path, "customCommands[") && node.Kind == yaml.MappingNode {
356+
output := ""
357+
if streamKey, streamValue := yaml_utils.RemoveKey(node, "stream"); streamKey != nil {
358+
if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" {
359+
output = "log"
360+
}
361+
}
362+
if streamKey, streamValue := yaml_utils.RemoveKey(node, "showOutput"); streamKey != nil {
363+
if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" && output == "" {
364+
output = "popup"
365+
}
366+
}
367+
if output != "" {
368+
outputKeyNode := &yaml.Node{
369+
Kind: yaml.ScalarNode,
370+
Value: "output",
371+
Tag: "!!str",
372+
}
373+
outputValueNode := &yaml.Node{
374+
Kind: yaml.ScalarNode,
375+
Value: output,
376+
Tag: "!!str",
377+
}
378+
node.Content = append(node.Content, outputKeyNode, outputValueNode)
379+
}
380+
}
381+
})
382+
}
383+
344384
func (c *AppConfig) GetDebug() bool {
345385
return c.debug
346386
}

pkg/config/user_config.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,17 +646,14 @@ type CustomCommand struct {
646646
LoadingText string `yaml:"loadingText" jsonschema:"example=Loading..."`
647647
// Label for the custom command when displayed in the keybindings menu
648648
Description string `yaml:"description"`
649-
// If true, stream the command's output to the Command Log panel
650-
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
651-
Stream *bool `yaml:"stream"`
652-
// If true, show the command's output in a popup within Lazygit
653-
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
654-
ShowOutput *bool `yaml:"showOutput"`
649+
// Where the output of the command should go. 'none' discards it, 'log' shows it in the command log, and 'popup' shows it in a popup.
650+
// [dev] Pointer so that we can tell whether it appears in the config file
651+
Output *string `yaml:"output" jsonschema:"enum=none,enum=log,enum=popup"`
655652
// If true, run the command in a pseudo-terminal (pty). This can be useful for commands that produce colored output when the output is a terminal.
656-
// Only used when stream is also true.
653+
// Only used when ouput is set to 'log', and subprocess is false.
657654
// Use with care: some commands may expect the terminal to have capabilities that lazygit's pty doesn't.
658655
Pty *bool `yaml:"pty"`
659-
// The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title.
656+
// The title to display in the popup panel if output is set to 'popup'. If left unset, the command will be used as the title.
660657
OutputTitle string `yaml:"outputTitle"`
661658
// Actions to take after the command has completed
662659
// [dev] Pointer so that we can tell whether it appears in the config file

pkg/config/user_config_validation.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ func validateCustomCommands(customCommands []CustomCommand) error {
107107
customCommand.Subprocess != nil ||
108108
len(customCommand.Prompts) > 0 ||
109109
len(customCommand.LoadingText) > 0 ||
110-
customCommand.Stream != nil ||
111-
customCommand.ShowOutput != nil ||
110+
customCommand.Output != nil ||
112111
customCommand.Pty != nil ||
113112
len(customCommand.OutputTitle) > 0 ||
114113
customCommand.After != nil) {
@@ -119,6 +118,13 @@ func validateCustomCommands(customCommands []CustomCommand) error {
119118
return fmt.Errorf("Error with custom command%s: it is not allowed to use both commandMenu and any of the other fields except key and description.", commandRef)
120119
}
121120

121+
if customCommand.Output != nil {
122+
if err := validateEnum("customCommand.output", *customCommand.Output,
123+
[]string{"none", "log", "popup"}); err != nil {
124+
return err
125+
}
126+
}
127+
122128
if err := validateCustomCommands(customCommand.CommandMenu); err != nil {
123129
return err
124130
}

pkg/config/user_config_validation_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,23 @@ func TestUserConfigValidate_enums(t *testing.T) {
9595
{value: "invalid_value", valid: false},
9696
},
9797
},
98+
{
99+
name: "Custom command output",
100+
setup: func(config *UserConfig, value string) {
101+
config.CustomCommands = []CustomCommand{
102+
{
103+
Output: &value,
104+
},
105+
}
106+
},
107+
testCases: []testCase{
108+
{value: "none", valid: true},
109+
{value: "log", valid: true},
110+
{value: "popup", valid: true},
111+
{value: "", valid: false},
112+
{value: "invalid_value", valid: false},
113+
},
114+
},
98115
{
99116
name: "Custom command sub menu",
100117
setup: func(config *UserConfig, _ string) {

pkg/gui/services/custom_commands/handler_creator.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
274274
return self.c.WithWaitingStatus(loadingText, func(gocui.Task) error {
275275
self.c.LogAction(self.c.Tr.Actions.CustomCommand)
276276

277-
if customCommand.Stream != nil && *customCommand.Stream {
277+
if customCommand.Output != nil && *customCommand.Output == "log" {
278278
cmdObj.StreamOutput()
279279
}
280280
if customCommand.Pty != nil && *customCommand.Pty {
@@ -294,7 +294,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
294294
return err
295295
}
296296

297-
if customCommand.ShowOutput != nil && *customCommand.ShowOutput {
297+
if customCommand.Output != nil && *customCommand.Output == "popup" {
298298
if strings.TrimSpace(output) == "" {
299299
output = self.c.Tr.EmptyOutput
300300
}

pkg/integration/tests/custom_commands/show_output_in_panel.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ var ShowOutputInPanel = NewIntegrationTest(NewIntegrationTestArgs{
1515
shell.EmptyCommit("my change")
1616
},
1717
SetupConfig: func(cfg *config.AppConfig) {
18-
trueVal := true
18+
popupVal := "popup"
1919
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
2020
{
21-
Key: "X",
22-
Context: "commits",
23-
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
24-
ShowOutput: &trueVal,
21+
Key: "X",
22+
Context: "commits",
23+
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
24+
Output: &popupVal,
2525
},
2626
{
2727
Key: "Y",
2828
Context: "commits",
2929
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
30-
ShowOutput: &trueVal,
30+
Output: &popupVal,
3131
OutputTitle: "Subject of commit {{ .SelectedLocalCommit.Hash }}",
3232
},
3333
}

schema/config.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,22 @@
118118
"type": "string",
119119
"description": "Label for the custom command when displayed in the keybindings menu"
120120
},
121-
"stream": {
122-
"type": "boolean",
123-
"description": "If true, stream the command's output to the Command Log panel"
124-
},
125-
"showOutput": {
126-
"type": "boolean",
127-
"description": "If true, show the command's output in a popup within Lazygit"
121+
"output": {
122+
"type": "string",
123+
"enum": [
124+
"none",
125+
"log",
126+
"popup"
127+
],
128+
"description": "Where the output of the command should go. 'none' discards it, 'log' shows it in the command log, and 'popup' shows it in a popup."
128129
},
129130
"pty": {
130131
"type": "boolean",
131-
"description": "If true, run the command in a pseudo-terminal (pty). This can be useful for commands that produce colored output when the output is a terminal.\nOnly used when stream is also true.\nUse with care: some commands may expect the terminal to have capabilities that lazygit's pty doesn't."
132+
"description": "If true, run the command in a pseudo-terminal (pty). This can be useful for commands that produce colored output when the output is a terminal.\nOnly used when ouput is set to 'log', and subprocess is false.\nUse with care: some commands may expect the terminal to have capabilities that lazygit's pty doesn't."
132133
},
133134
"outputTitle": {
134135
"type": "string",
135-
"description": "The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title."
136+
"description": "The title to display in the popup panel if output is set to 'popup'. If left unset, the command will be used as the title."
136137
},
137138
"after": {
138139
"$ref": "#/$defs/CustomCommandAfterHook",

0 commit comments

Comments
 (0)