mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-10 20:05:50 +02:00
Combine customCommand's subprocess, stream, and showOutput fields into a single output enum
This commit is contained in:
parent
5f4be3bfb7
commit
a9f9dee30d
9 changed files with 187 additions and 43 deletions
|
@ -14,7 +14,7 @@ customCommands:
|
||||||
- key: 'C'
|
- key: 'C'
|
||||||
context: 'global'
|
context: 'global'
|
||||||
command: "git commit"
|
command: "git commit"
|
||||||
subprocess: true
|
output: terminal
|
||||||
- key: 'n'
|
- key: 'n'
|
||||||
context: 'localBranches'
|
context: 'localBranches'
|
||||||
prompts:
|
prompts:
|
||||||
|
@ -53,13 +53,11 @@ For a given custom command, here are the allowed fields:
|
||||||
| key | The key to trigger the command. Use a single letter or one of the values from [here](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md). Custom commands without a key specified can be triggered by selecting them from the keybindings (`?`) menu | no |
|
| key | The key to trigger the command. Use a single letter or one of the values from [here](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md). Custom commands without a key specified can be triggered by selecting them from the keybindings (`?`) menu | no |
|
||||||
| command | The command to run (using Go template syntax for placeholder values) | yes |
|
| command | The command to run (using Go template syntax for placeholder values) | yes |
|
||||||
| context | The context in which to listen for the key (see [below](#contexts)) | yes |
|
| context | The context in which to listen for the key (see [below](#contexts)) | yes |
|
||||||
| subprocess | Whether you want the command to run in a subprocess (e.g. if the command requires user input) | no |
|
|
||||||
| prompts | A list of prompts that will request user input before running the final command | no |
|
| prompts | A list of prompts that will request user input before running the final command | no |
|
||||||
| loadingText | Text to display while waiting for command to finish | no |
|
| loadingText | Text to display while waiting for command to finish | no |
|
||||||
| description | Label for the custom command when displayed in the keybindings menu | no |
|
| description | Label for the custom command when displayed in the keybindings menu | no |
|
||||||
| stream | Whether you want to stream the command's output to the Command Log panel | no |
|
| output | Where the output of the command should go. 'none' discards it, 'terminal' suspends lazygit and runs the command in the terminal (useful for commands that require user input), 'log' streams it to the command log, 'logWithPty' is like 'log' but runs the command in a pseudo terminal (can be useful for commands that produce colored output when the output is a terminal), and 'popup' shows it in a popup. | no |
|
||||||
| showOutput | Whether you want to show the command's output in a popup within Lazygit | no |
|
| 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 |
|
||||||
| 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 |
|
|
||||||
| after | Actions to take after the command has completed | no |
|
| after | Actions to take after the command has completed | no |
|
||||||
|
|
||||||
Here are the options for the `after` key:
|
Here are the options for the `after` key:
|
||||||
|
@ -365,7 +363,7 @@ If you use the commandMenu property, none of the other properties except key and
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## More Examples
|
## More Examples
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,11 @@ func computeMigratedConfig(path string, content []byte) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
|
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = changeCustomCommandStreamAndOutputToOutputEnum(&rootNode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
// Add more migrations here...
|
// Add more migrations here...
|
||||||
|
|
||||||
if !reflect.DeepEqual(rootNode, originalCopy) {
|
if !reflect.DeepEqual(rootNode, originalCopy) {
|
||||||
|
@ -341,6 +346,46 @@ func changeCommitPrefixesMap(rootNode *yaml.Node) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func changeCustomCommandStreamAndOutputToOutputEnum(rootNode *yaml.Node) error {
|
||||||
|
return yaml_utils.Walk(rootNode, func(node *yaml.Node, path string) {
|
||||||
|
// We are being lazy here and rely on the fact that the only mapping
|
||||||
|
// nodes in the tree under customCommands are actual custom commands. If
|
||||||
|
// this ever changes (e.g. because we add a struct field to
|
||||||
|
// customCommand), then we need to change this to iterate properly.
|
||||||
|
if strings.HasPrefix(path, "customCommands[") && node.Kind == yaml.MappingNode {
|
||||||
|
output := ""
|
||||||
|
if streamKey, streamValue := yaml_utils.RemoveKey(node, "subprocess"); streamKey != nil {
|
||||||
|
if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" {
|
||||||
|
output = "terminal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if streamKey, streamValue := yaml_utils.RemoveKey(node, "stream"); streamKey != nil {
|
||||||
|
if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" && output == "" {
|
||||||
|
output = "log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if streamKey, streamValue := yaml_utils.RemoveKey(node, "showOutput"); streamKey != nil {
|
||||||
|
if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" && output == "" {
|
||||||
|
output = "popup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if output != "" {
|
||||||
|
outputKeyNode := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: "output",
|
||||||
|
Tag: "!!str",
|
||||||
|
}
|
||||||
|
outputValueNode := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: output,
|
||||||
|
Tag: "!!str",
|
||||||
|
}
|
||||||
|
node.Content = append(node.Content, outputKeyNode, outputValueNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *AppConfig) GetDebug() bool {
|
func (c *AppConfig) GetDebug() bool {
|
||||||
return c.debug
|
return c.debug
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,92 @@ git:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomCommandsOutputMigration(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Empty String",
|
||||||
|
input: "",
|
||||||
|
expected: "",
|
||||||
|
}, {
|
||||||
|
name: "Convert subprocess to output=terminal",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
subprocess: true
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
output: terminal
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
name: "Convert stream to output=log",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
stream: true
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
output: log
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
name: "Convert showOutput to output=popup",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
showOutput: true
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
output: popup
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
name: "Subprocess wins over the other two",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
subprocess: true
|
||||||
|
stream: true
|
||||||
|
showOutput: true
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
output: terminal
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
name: "Stream wins over showOutput",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
stream: true
|
||||||
|
showOutput: true
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
output: log
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
name: "Explicitly setting to false doesn't create an output=none key",
|
||||||
|
input: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
subprocess: false
|
||||||
|
stream: false
|
||||||
|
showOutput: false
|
||||||
|
`,
|
||||||
|
expected: `customCommands:
|
||||||
|
- command: echo 'hello'
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
t.Run(s.name, func(t *testing.T) {
|
||||||
|
actual, err := computeMigratedConfig("path doesn't matter", []byte(s.input))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, s.expected, string(actual))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var largeConfiguration = []byte(`
|
var largeConfiguration = []byte(`
|
||||||
# Config relating to the Lazygit UI
|
# Config relating to the Lazygit UI
|
||||||
gui:
|
gui:
|
||||||
|
|
|
@ -637,22 +637,15 @@ type CustomCommand struct {
|
||||||
Context string `yaml:"context" jsonschema:"example=status,example=files,example=worktrees,example=localBranches,example=remotes,example=remoteBranches,example=tags,example=commits,example=reflogCommits,example=subCommits,example=commitFiles,example=stash,example=global"`
|
Context string `yaml:"context" jsonschema:"example=status,example=files,example=worktrees,example=localBranches,example=remotes,example=remoteBranches,example=tags,example=commits,example=reflogCommits,example=subCommits,example=commitFiles,example=stash,example=global"`
|
||||||
// The command to run (using Go template syntax for placeholder values)
|
// The command to run (using Go template syntax for placeholder values)
|
||||||
Command string `yaml:"command" jsonschema:"example=git fetch {{.Form.Remote}} {{.Form.Branch}} && git checkout FETCH_HEAD"`
|
Command string `yaml:"command" jsonschema:"example=git fetch {{.Form.Remote}} {{.Form.Branch}} && git checkout FETCH_HEAD"`
|
||||||
// If true, run the command in a subprocess (e.g. if the command requires user input)
|
|
||||||
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
|
|
||||||
Subprocess *bool `yaml:"subprocess"`
|
|
||||||
// A list of prompts that will request user input before running the final command
|
// A list of prompts that will request user input before running the final command
|
||||||
Prompts []CustomCommandPrompt `yaml:"prompts"`
|
Prompts []CustomCommandPrompt `yaml:"prompts"`
|
||||||
// Text to display while waiting for command to finish
|
// Text to display while waiting for command to finish
|
||||||
LoadingText string `yaml:"loadingText" jsonschema:"example=Loading..."`
|
LoadingText string `yaml:"loadingText" jsonschema:"example=Loading..."`
|
||||||
// Label for the custom command when displayed in the keybindings menu
|
// Label for the custom command when displayed in the keybindings menu
|
||||||
Description string `yaml:"description"`
|
Description string `yaml:"description"`
|
||||||
// If true, stream the command's output to the Command Log panel
|
// Where the output of the command should go. 'none' discards it, 'terminal' suspends lazygit and runs the command in the terminal (useful for commands that require user input), 'log' streams it to the command log, 'logWithPty' is like 'log' but runs the command in a pseudo terminal (can be useful for commands that produce colored output when the output is a terminal), and 'popup' shows it in a popup.
|
||||||
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
|
Output string `yaml:"output" jsonschema:"enum=none,enum=terminal,enum=log,enum=logWithPty,enum=popup"`
|
||||||
Stream *bool `yaml:"stream"`
|
// 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.
|
||||||
// If true, show the command's output in a popup within Lazygit
|
|
||||||
// [dev] Pointer to bool so that we can distinguish unset (nil) from false.
|
|
||||||
ShowOutput *bool `yaml:"showOutput"`
|
|
||||||
// The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title.
|
|
||||||
OutputTitle string `yaml:"outputTitle"`
|
OutputTitle string `yaml:"outputTitle"`
|
||||||
// Actions to take after the command has completed
|
// Actions to take after the command has completed
|
||||||
// [dev] Pointer so that we can tell whether it appears in the config file
|
// [dev] Pointer so that we can tell whether it appears in the config file
|
||||||
|
|
|
@ -104,11 +104,9 @@ func validateCustomCommands(customCommands []CustomCommand) error {
|
||||||
if len(customCommand.CommandMenu) > 0 {
|
if len(customCommand.CommandMenu) > 0 {
|
||||||
if len(customCommand.Context) > 0 ||
|
if len(customCommand.Context) > 0 ||
|
||||||
len(customCommand.Command) > 0 ||
|
len(customCommand.Command) > 0 ||
|
||||||
customCommand.Subprocess != nil ||
|
|
||||||
len(customCommand.Prompts) > 0 ||
|
len(customCommand.Prompts) > 0 ||
|
||||||
len(customCommand.LoadingText) > 0 ||
|
len(customCommand.LoadingText) > 0 ||
|
||||||
customCommand.Stream != nil ||
|
len(customCommand.Output) > 0 ||
|
||||||
customCommand.ShowOutput != nil ||
|
|
||||||
len(customCommand.OutputTitle) > 0 ||
|
len(customCommand.OutputTitle) > 0 ||
|
||||||
customCommand.After != nil {
|
customCommand.After != nil {
|
||||||
commandRef := ""
|
commandRef := ""
|
||||||
|
@ -121,6 +119,11 @@ func validateCustomCommands(customCommands []CustomCommand) error {
|
||||||
if err := validateCustomCommands(customCommand.CommandMenu); err != nil {
|
if err := validateCustomCommands(customCommand.CommandMenu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err := validateEnum("customCommand.output", customCommand.Output,
|
||||||
|
[]string{"", "none", "terminal", "log", "logWithPty", "popup"}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -95,6 +95,25 @@ func TestUserConfigValidate_enums(t *testing.T) {
|
||||||
{value: "invalid_value", valid: false},
|
{value: "invalid_value", valid: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Custom command output",
|
||||||
|
setup: func(config *UserConfig, value string) {
|
||||||
|
config.CustomCommands = []CustomCommand{
|
||||||
|
{
|
||||||
|
Output: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
testCases: []testCase{
|
||||||
|
{value: "", valid: true},
|
||||||
|
{value: "none", valid: true},
|
||||||
|
{value: "terminal", valid: true},
|
||||||
|
{value: "log", valid: true},
|
||||||
|
{value: "logWithPty", valid: true},
|
||||||
|
{value: "popup", valid: true},
|
||||||
|
{value: "invalid_value", valid: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Custom command sub menu",
|
name: "Custom command sub menu",
|
||||||
setup: func(config *UserConfig, _ string) {
|
setup: func(config *UserConfig, _ string) {
|
||||||
|
@ -132,11 +151,10 @@ func TestUserConfigValidate_enums(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "Custom command sub menu",
|
name: "Custom command sub menu",
|
||||||
setup: func(config *UserConfig, _ string) {
|
setup: func(config *UserConfig, _ string) {
|
||||||
falseVal := false
|
|
||||||
config.CustomCommands = []CustomCommand{
|
config.CustomCommands = []CustomCommand{
|
||||||
{
|
{
|
||||||
Key: "X",
|
Key: "X",
|
||||||
Subprocess: &falseVal, // other properties are not allowed for submenus (using subprocess as an example)
|
LoadingText: "loading", // other properties are not allowed for submenus (using loadingText as an example)
|
||||||
CommandMenu: []CustomCommand{
|
CommandMenu: []CustomCommand{
|
||||||
{Key: "1", Command: "echo 'hello'", Context: "global"},
|
{Key: "1", Command: "echo 'hello'", Context: "global"},
|
||||||
},
|
},
|
||||||
|
|
|
@ -262,7 +262,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
|
||||||
|
|
||||||
cmdObj := self.c.OS().Cmd.NewShell(cmdStr, self.c.UserConfig().OS.ShellFunctionsFile)
|
cmdObj := self.c.OS().Cmd.NewShell(cmdStr, self.c.UserConfig().OS.ShellFunctionsFile)
|
||||||
|
|
||||||
if customCommand.Subprocess != nil && *customCommand.Subprocess {
|
if customCommand.Output == "terminal" {
|
||||||
return self.c.RunSubprocessAndRefresh(cmdObj)
|
return self.c.RunSubprocessAndRefresh(cmdObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,9 +274,12 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
|
||||||
return self.c.WithWaitingStatus(loadingText, func(gocui.Task) error {
|
return self.c.WithWaitingStatus(loadingText, func(gocui.Task) error {
|
||||||
self.c.LogAction(self.c.Tr.Actions.CustomCommand)
|
self.c.LogAction(self.c.Tr.Actions.CustomCommand)
|
||||||
|
|
||||||
if customCommand.Stream != nil && *customCommand.Stream {
|
if customCommand.Output == "log" || customCommand.Output == "logWithPty" {
|
||||||
cmdObj.StreamOutput()
|
cmdObj.StreamOutput()
|
||||||
}
|
}
|
||||||
|
if customCommand.Output == "logWithPty" {
|
||||||
|
cmdObj.UsePty()
|
||||||
|
}
|
||||||
output, err := cmdObj.RunWithOutput()
|
output, err := cmdObj.RunWithOutput()
|
||||||
|
|
||||||
if refreshErr := self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}); err != nil {
|
if refreshErr := self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}); err != nil {
|
||||||
|
@ -291,7 +294,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if customCommand.ShowOutput != nil && *customCommand.ShowOutput {
|
if customCommand.Output == "popup" {
|
||||||
if strings.TrimSpace(output) == "" {
|
if strings.TrimSpace(output) == "" {
|
||||||
output = self.c.Tr.EmptyOutput
|
output = self.c.Tr.EmptyOutput
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,19 +15,18 @@ var ShowOutputInPanel = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
shell.EmptyCommit("my change")
|
shell.EmptyCommit("my change")
|
||||||
},
|
},
|
||||||
SetupConfig: func(cfg *config.AppConfig) {
|
SetupConfig: func(cfg *config.AppConfig) {
|
||||||
trueVal := true
|
|
||||||
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
cfg.GetUserConfig().CustomCommands = []config.CustomCommand{
|
||||||
{
|
{
|
||||||
Key: "X",
|
Key: "X",
|
||||||
Context: "commits",
|
Context: "commits",
|
||||||
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
|
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
|
||||||
ShowOutput: &trueVal,
|
Output: "popup",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: "Y",
|
Key: "Y",
|
||||||
Context: "commits",
|
Context: "commits",
|
||||||
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
|
Command: "printf '%s' '{{ .SelectedLocalCommit.Name }}'",
|
||||||
ShowOutput: &trueVal,
|
Output: "popup",
|
||||||
OutputTitle: "Subject of commit {{ .SelectedLocalCommit.Hash }}",
|
OutputTitle: "Subject of commit {{ .SelectedLocalCommit.Hash }}",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,6 @@
|
||||||
"git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD"
|
"git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"subprocess": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "If true, run the command in a subprocess (e.g. if the command requires user input)"
|
|
||||||
},
|
|
||||||
"prompts": {
|
"prompts": {
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/$defs/CustomCommandPrompt"
|
"$ref": "#/$defs/CustomCommandPrompt"
|
||||||
|
@ -118,17 +114,20 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Label for the custom command when displayed in the keybindings menu"
|
"description": "Label for the custom command when displayed in the keybindings menu"
|
||||||
},
|
},
|
||||||
"stream": {
|
"output": {
|
||||||
"type": "boolean",
|
"type": "string",
|
||||||
"description": "If true, stream the command's output to the Command Log panel"
|
"enum": [
|
||||||
},
|
"none",
|
||||||
"showOutput": {
|
"terminal",
|
||||||
"type": "boolean",
|
"log",
|
||||||
"description": "If true, show the command's output in a popup within Lazygit"
|
"logWithPty",
|
||||||
|
"popup"
|
||||||
|
],
|
||||||
|
"description": "Where the output of the command should go. 'none' discards it, 'terminal' suspends lazygit and runs the command in the terminal (useful for commands that require user input), 'log' streams it to the command log, 'logWithPty' is like 'log' but runs the command in a pseudo terminal (can be useful for commands that produce colored output when the output is a terminal), and 'popup' shows it in a popup."
|
||||||
},
|
},
|
||||||
"outputTitle": {
|
"outputTitle": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title."
|
"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."
|
||||||
},
|
},
|
||||||
"after": {
|
"after": {
|
||||||
"$ref": "#/$defs/CustomCommandAfterHook",
|
"$ref": "#/$defs/CustomCommandAfterHook",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue