diff --git a/docs/Config.md b/docs/Config.md index 49f884dac..2e0f104d0 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -411,6 +411,11 @@ os: # window is closed. editAtLineAndWait: "" + # Whether lazygit suspends until an edit process returns + # Pointer to bool so that we can distinguish unset (nil) from false. + # We're naming this `editInTerminal` for backwards compatibility + editInTerminal: false + # For opening a directory in an editor openDirInEditor: "" diff --git a/go.mod b/go.mod index df8cf660a..f0f2a20bc 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/gdamore/tcell/v2 v2.8.1 github.com/go-errors/errors v1.5.1 github.com/gookit/color v1.4.2 - github.com/iancoleman/orderedmap v0.3.0 github.com/imdario/mergo v0.3.11 github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 diff --git a/go.sum b/go.sum index 019905ef7..3750f2e9f 100644 --- a/go.sum +++ b/go.sum @@ -171,8 +171,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= -github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= diff --git a/pkg/jsonschema/generate.go b/pkg/jsonschema/generate.go index be28519e3..05d9f5782 100644 --- a/pkg/jsonschema/generate.go +++ b/pkg/jsonschema/generate.go @@ -7,41 +7,76 @@ import ( "fmt" "os" "reflect" + "strings" "github.com/jesseduffield/lazycore/pkg/utils" "github.com/jesseduffield/lazygit/pkg/config" "github.com/karimkhaleel/jsonschema" + "github.com/samber/lo" ) func GetSchemaDir() string { return utils.GetLazyRootDirectory() + "/schema" } -func GenerateSchema() { +func GenerateSchema() *jsonschema.Schema { schema := customReflect(&config.UserConfig{}) obj, _ := json.MarshalIndent(schema, "", " ") obj = append(obj, '\n') if err := os.WriteFile(GetSchemaDir()+"/config.json", obj, 0o644); err != nil { fmt.Println("Error writing to file:", err) - return + return nil } + return schema +} + +func getSubSchema(rootSchema, parentSchema *jsonschema.Schema, key string) *jsonschema.Schema { + subSchema, found := parentSchema.Properties.Get(key) + if !found { + panic(fmt.Sprintf("Failed to find subSchema at %s on parent", key)) + } + + // This means the schema is defined on the rootSchema's Definitions + if subSchema.Ref != "" { + key, _ = strings.CutPrefix(subSchema.Ref, "#/$defs/") + refSchema, ok := rootSchema.Definitions[key] + if !ok { + panic(fmt.Sprintf("Failed to find #/$defs/%s", key)) + } + refSchema.Description = subSchema.Description + return refSchema + } + + return subSchema } func customReflect(v *config.UserConfig) *jsonschema.Schema { - defaultConfig := config.GetDefaultConfig() - r := &jsonschema.Reflector{FieldNameTag: "yaml", RequiredFromJSONSchemaTags: true, DoNotReference: true} + r := &jsonschema.Reflector{FieldNameTag: "yaml", RequiredFromJSONSchemaTags: true} if err := r.AddGoComments("github.com/jesseduffield/lazygit/pkg/config", "../config"); err != nil { panic(err) } schema := r.Reflect(v) + defaultConfig := config.GetDefaultConfig() + userConfigSchema := schema.Definitions["UserConfig"] - setDefaultVals(defaultConfig, schema) + defaultValue := reflect.ValueOf(defaultConfig).Elem() + + yamlToFieldNames := lo.Invert(userConfigSchema.OriginalPropertiesMapping) + + for pair := userConfigSchema.Properties.Oldest(); pair != nil; pair = pair.Next() { + yamlName := pair.Key + fieldName := yamlToFieldNames[yamlName] + + subSchema := getSubSchema(schema, userConfigSchema, yamlName) + + setDefaultVals(schema, subSchema, defaultValue.FieldByName(fieldName).Interface()) + } return schema } -func setDefaultVals(defaults any, schema *jsonschema.Schema) { +func setDefaultVals(rootSchema, schema *jsonschema.Schema, defaults any) { t := reflect.TypeOf(defaults) v := reflect.ValueOf(defaults) @@ -50,6 +85,24 @@ func setDefaultVals(defaults any, schema *jsonschema.Schema) { v = v.Elem() } + k := t.Kind() + _ = k + + switch t.Kind() { + case reflect.Bool: + schema.Default = v.Bool() + case reflect.Int: + schema.Default = v.Int() + case reflect.String: + schema.Default = v.String() + default: + // Do nothing + } + + if t.Kind() != reflect.Struct { + return + } + for i := 0; i < t.NumField(); i++ { value := v.Field(i).Interface() parentKey := t.Field(i).Name @@ -59,13 +112,10 @@ func setDefaultVals(defaults any, schema *jsonschema.Schema) { continue } - subSchema, ok := schema.Properties.Get(key) - if !ok { - continue - } + subSchema := getSubSchema(rootSchema, schema, key) if isStruct(value) { - setDefaultVals(value, subSchema) + setDefaultVals(rootSchema, subSchema, value) } else if !isZeroValue(value) { subSchema.Default = value } diff --git a/pkg/jsonschema/generate_config_docs.go b/pkg/jsonschema/generate_config_docs.go index 441cc55e7..b5228c042 100644 --- a/pkg/jsonschema/generate_config_docs.go +++ b/pkg/jsonschema/generate_config_docs.go @@ -2,14 +2,13 @@ package jsonschema import ( "bytes" - "encoding/json" "errors" "fmt" "os" "strings" - "github.com/iancoleman/orderedmap" "github.com/jesseduffield/lazycore/pkg/utils" + "github.com/karimkhaleel/jsonschema" "github.com/samber/lo" "gopkg.in/yaml.v3" @@ -106,16 +105,7 @@ func (n *Node) MarshalYAML() (interface{}, error) { setComment(&keyNode, n.Description) } - if n.Default != nil { - valueNode := yaml.Node{ - Kind: yaml.ScalarNode, - } - err := valueNode.Encode(n.Default) - if err != nil { - return nil, err - } - node.Content = append(node.Content, &keyNode, &valueNode) - } else if len(n.Children) > 0 { + if len(n.Children) > 0 { childrenNode := yaml.Node{ Kind: yaml.MappingNode, } @@ -136,62 +126,20 @@ func (n *Node) MarshalYAML() (interface{}, error) { childrenNode.Content = append(childrenNode.Content, childYaml.(*yaml.Node).Content...) } node.Content = append(node.Content, &keyNode, &childrenNode) + } else { + valueNode := yaml.Node{ + Kind: yaml.ScalarNode, + } + err := valueNode.Encode(n.Default) + if err != nil { + return nil, err + } + node.Content = append(node.Content, &keyNode, &valueNode) } return &node, nil } -func getDescription(v *orderedmap.OrderedMap) string { - description, ok := v.Get("description") - if !ok { - description = "" - } - return description.(string) -} - -func getDefault(v *orderedmap.OrderedMap) (error, any) { - defaultValue, ok := v.Get("default") - if ok { - return nil, defaultValue - } - - dataType, ok := v.Get("type") - if ok { - dataTypeString := dataType.(string) - if dataTypeString == "string" { - return nil, "" - } - } - - return errors.New("Failed to get default value"), nil -} - -func parseNode(parent *Node, name string, value *orderedmap.OrderedMap) { - description := getDescription(value) - err, defaultValue := getDefault(value) - if err == nil { - leaf := &Node{Name: name, Description: description, Default: defaultValue} - parent.Children = append(parent.Children, leaf) - } - - properties, ok := value.Get("properties") - if !ok { - return - } - - orderedProperties := properties.(orderedmap.OrderedMap) - - node := &Node{Name: name, Description: description} - parent.Children = append(parent.Children, node) - - keys := orderedProperties.Keys() - for _, name := range keys { - value, _ := orderedProperties.Get(name) - typedValue := value.(orderedmap.OrderedMap) - parseNode(node, name, &typedValue) - } -} - func writeToConfigDocs(config []byte) error { configPath := utils.GetLazyRootDirectory() + "/docs/Config.md" markdown, err := os.ReadFile(configPath) @@ -222,31 +170,12 @@ func writeToConfigDocs(config []byte) error { return nil } -func GenerateConfigDocs() { - content, err := os.ReadFile(GetSchemaDir() + "/config.json") - if err != nil { - panic("Error reading config.json") +func GenerateConfigDocs(schema *jsonschema.Schema) { + rootNode := &Node{ + Children: make([]*Node, 0), } - schema := orderedmap.New() - - err = json.Unmarshal(content, &schema) - if err != nil { - panic("Failed to unmarshal config.json") - } - - root, ok := schema.Get("properties") - if !ok { - panic("properties key not found in schema") - } - orderedRoot := root.(orderedmap.OrderedMap) - - rootNode := Node{} - for _, name := range orderedRoot.Keys() { - value, _ := orderedRoot.Get(name) - typedValue := value.(orderedmap.OrderedMap) - parseNode(&rootNode, name, &typedValue) - } + recurseOverSchema(schema, schema.Definitions["UserConfig"], rootNode) var buffer bytes.Buffer encoder := yaml.NewEncoder(&buffer) @@ -262,8 +191,51 @@ func GenerateConfigDocs() { config := prepareMarshalledConfig(buffer) - err = writeToConfigDocs(config) + err := writeToConfigDocs(config) if err != nil { panic(err) } } + +func recurseOverSchema(rootSchema, schema *jsonschema.Schema, parent *Node) { + if schema == nil || schema.Properties == nil || schema.Properties.Len() == 0 { + return + } + + for pair := schema.Properties.Oldest(); pair != nil; pair = pair.Next() { + subSchema := getSubSchema(rootSchema, schema, pair.Key) + + // Skip empty objects + if subSchema.Type == "object" && subSchema.Properties == nil { + continue + } + + // Skip empty arrays + if isZeroValue(subSchema.Default) && subSchema.Type == "array" { + continue + } + + node := Node{ + Name: pair.Key, + Description: subSchema.Description, + Default: getZeroValue(subSchema.Default, subSchema.Type), + } + parent.Children = append(parent.Children, &node) + recurseOverSchema(rootSchema, subSchema, &node) + } +} + +func getZeroValue(val any, t string) any { + if !isZeroValue(val) { + return val + } + + switch t { + case "string": + return "" + case "boolean": + return false + default: + return nil + } +} diff --git a/pkg/jsonschema/generator.go b/pkg/jsonschema/generator.go index df53dee56..33739fa9e 100644 --- a/pkg/jsonschema/generator.go +++ b/pkg/jsonschema/generator.go @@ -10,6 +10,6 @@ import ( func main() { fmt.Printf("Generating jsonschema in %s...\n", jsonschema.GetSchemaDir()) - jsonschema.GenerateSchema() - jsonschema.GenerateConfigDocs() + schema := jsonschema.GenerateSchema() + jsonschema.GenerateConfigDocs(schema) } diff --git a/schema/config.json b/schema/config.json index ef8a642cf..2af6ae595 100644 --- a/schema/config.json +++ b/schema/config.json @@ -1,8 +1,380 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/jesseduffield/lazygit/pkg/config/user-config", - "properties": { - "gui": { + "$ref": "#/$defs/UserConfig", + "$defs": { + "CommitConfig": { + "properties": { + "signOff": { + "type": "boolean", + "description": "If true, pass '--signoff' flag when committing", + "default": false + }, + "autoWrapCommitMessage": { + "type": "boolean", + "description": "Automatic WYSIWYG wrapping of the commit message as you type", + "default": true + }, + "autoWrapWidth": { + "type": "integer", + "description": "If autoWrapCommitMessage is true, the width to wrap to", + "default": 72 + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config relating to committing" + }, + "CommitLengthConfig": { + "properties": { + "show": { + "type": "boolean", + "description": "If true, show an indicator of commit message length", + "default": true + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config relating to the commit length indicator" + }, + "CommitPrefixConfig": { + "properties": { + "pattern": { + "type": "string", + "description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"", + "examples": [ + "^\\w+\\/(\\w+-\\w+).*" + ] + }, + "replace": { + "type": "string", + "description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"", + "examples": [ + "[$1]" + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "CustomCommand": { + "properties": { + "key": { + "type": "string", + "description": "The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md" + }, + "context": { + "type": "string", + "description": "The context in which to listen for the key. Valid values are: status, files, worktrees, localBranches, remotes, remoteBranches, tags, commits, reflogCommits, subCommits, commitFiles, stash, and global. Multiple contexts separated by comma are allowed; most useful for \"commits, subCommits\" or \"files, commitFiles\".", + "examples": [ + "status", + "files", + "worktrees", + "localBranches", + "remotes", + "remoteBranches", + "tags", + "commits", + "reflogCommits", + "subCommits", + "commitFiles", + "stash", + "global" + ] + }, + "command": { + "type": "string", + "description": "The command to run (using Go template syntax for placeholder values)", + "examples": [ + "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": { + "items": { + "$ref": "#/$defs/CustomCommandPrompt" + }, + "type": "array", + "description": "A list of prompts that will request user input before running the final command" + }, + "loadingText": { + "type": "string", + "description": "Text to display while waiting for command to finish", + "examples": [ + "Loading..." + ] + }, + "description": { + "type": "string", + "description": "Label for the custom command when displayed in the keybindings menu" + }, + "stream": { + "type": "boolean", + "description": "If true, stream the command's output to the Command Log panel" + }, + "showOutput": { + "type": "boolean", + "description": "If true, show the command's output in a popup within Lazygit" + }, + "outputTitle": { + "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." + }, + "after": { + "$ref": "#/$defs/CustomCommandAfterHook", + "description": "Actions to take after the command has completed" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CustomCommandAfterHook": { + "properties": { + "checkForConflicts": { + "type": "boolean" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CustomCommandMenuOption": { + "properties": { + "name": { + "type": "string", + "description": "The first part of the label" + }, + "description": { + "type": "string", + "description": "The second part of the label" + }, + "value": { + "type": "string", + "minLength": 1, + "description": "The value that will be used in the command", + "examples": [ + "feature" + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "CustomCommandPrompt": { + "properties": { + "type": { + "type": "string", + "description": "One of: 'input' | 'menu' | 'confirm' | 'menuFromCommand'" + }, + "key": { + "type": "string", + "description": "Used to reference the entered value from within the custom command. E.g. a prompt with `key: 'Branch'` can be referred to as `{{.Form.Branch}}` in the command" + }, + "title": { + "type": "string", + "description": "The title to display in the popup panel" + }, + "initialValue": { + "type": "string", + "description": "The initial value to appear in the text box.\nOnly for input prompts." + }, + "suggestions": { + "$ref": "#/$defs/CustomCommandSuggestions", + "description": "Shows suggestions as the input is entered\nOnly for input prompts." + }, + "body": { + "type": "string", + "description": "The message of the confirmation prompt.\nOnly for confirm prompts.", + "examples": [ + "Are you sure you want to push to the remote?" + ] + }, + "options": { + "items": { + "$ref": "#/$defs/CustomCommandMenuOption" + }, + "type": "array", + "description": "Menu options.\nOnly for menu prompts." + }, + "command": { + "type": "string", + "description": "The command to run to generate menu options\nOnly for menuFromCommand prompts.", + "examples": [ + "git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD" + ] + }, + "filter": { + "type": "string", + "description": "The regexp to run specifying groups which are going to be kept from the command's output.\nOnly for menuFromCommand prompts.", + "examples": [ + ".*{{.SelectedRemote.Name }}/(?P\u003cbranch\u003e.*)" + ] + }, + "valueFormat": { + "type": "string", + "description": "How to format matched groups from the filter to construct a menu item's value.\nOnly for menuFromCommand prompts.", + "examples": [ + "{{ .branch }}" + ] + }, + "labelFormat": { + "type": "string", + "description": "Like valueFormat but for the labels. If `labelFormat` is not specified, `valueFormat` is shown instead.\nOnly for menuFromCommand prompts.", + "examples": [ + "{{ .branch | green }}" + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "CustomCommandSuggestions": { + "properties": { + "preset": { + "type": "string", + "enum": [ + "authors", + "branches", + "files", + "refs", + "remotes", + "remoteBranches", + "tags" + ], + "description": "Uses built-in logic to obtain the suggestions. One of 'authors' | 'branches' | 'files' | 'refs' | 'remotes' | 'remoteBranches' | 'tags'" + }, + "command": { + "type": "string", + "description": "Command to run such that each line in the output becomes a suggestion. Mutually exclusive with 'preset' field.", + "examples": [ + "git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD" + ] + } + }, + "additionalProperties": false, + "type": "object" + }, + "GitConfig": { + "properties": { + "paging": { + "$ref": "#/$defs/PagingConfig", + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md" + }, + "commit": { + "$ref": "#/$defs/CommitConfig", + "description": "Config relating to committing" + }, + "merging": { + "$ref": "#/$defs/MergingConfig", + "description": "Config relating to merging" + }, + "mainBranches": { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true, + "description": "list of branches that are considered 'main' branches, used when displaying commits", + "default": [ + "master", + "main" + ] + }, + "skipHookPrefix": { + "type": "string", + "description": "Prefix to use when skipping hooks. E.g. if set to 'WIP', then pre-commit hooks will be skipped when the commit message starts with 'WIP'", + "default": "WIP" + }, + "autoFetch": { + "type": "boolean", + "description": "If true, periodically fetch from remote", + "default": true + }, + "autoRefresh": { + "type": "boolean", + "description": "If true, periodically refresh files and submodules", + "default": true + }, + "fetchAll": { + "type": "boolean", + "description": "If true, pass the --all arg to git fetch", + "default": true + }, + "autoStageResolvedConflicts": { + "type": "boolean", + "description": "If true, lazygit will automatically stage files that used to have merge\nconflicts but no longer do; and it will also ask you if you want to\ncontinue a merge or rebase if you've resolved all conflicts. If false, it\nwon't do either of these things.", + "default": true + }, + "branchLogCmd": { + "type": "string", + "description": "Command used when displaying the current branch git log in the main window", + "default": "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --" + }, + "allBranchesLogCmd": { + "type": "string", + "description": "Command used to display git log of all branches in the main window.\nDeprecated: Use `allBranchesLogCmds` instead.", + "default": "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium" + }, + "allBranchesLogCmds": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Commands used to display git log of all branches in the main window, they will be cycled in order of appearance" + }, + "overrideGpg": { + "type": "boolean", + "description": "If true, do not spawn a separate process when using GPG", + "default": false + }, + "disableForcePushing": { + "type": "boolean", + "description": "If true, do not allow force pushes", + "default": false + }, + "commitPrefix": { + "items": { + "$ref": "#/$defs/CommitPrefixConfig" + }, + "type": "array", + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix" + }, + "commitPrefixes": { + "additionalProperties": { + "items": { + "$ref": "#/$defs/CommitPrefixConfig" + }, + "type": "array" + }, + "type": "object", + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix" + }, + "branchPrefix": { + "type": "string", + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-branch-name-prefix" + }, + "parseEmoji": { + "type": "boolean", + "description": "If true, parse emoji strings in commit messages e.g. render :rocket: as 🚀\n(This should really be under 'gui', not 'git')", + "default": false + }, + "log": { + "$ref": "#/$defs/LogConfig", + "description": "Config for showing the log in the commits view" + }, + "truncateCopiedCommitHashesTo": { + "type": "integer", + "description": "When copying commit hashes to the clipboard, truncate them to this\nlength. Set to 40 to disable truncation.", + "default": 12 + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config relating to git" + }, + "GuiConfig": { "properties": { "authorColors": { "additionalProperties": { @@ -141,164 +513,11 @@ "default": "3:04PM" }, "theme": { - "properties": { - "activeBorderColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Border color of focused window", - "default": [ - "green", - "bold" - ] - }, - "inactiveBorderColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Border color of non-focused windows", - "default": [ - "default" - ] - }, - "searchingActiveBorderColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Border color of focused window when searching in that window", - "default": [ - "cyan", - "bold" - ] - }, - "optionsTextColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Color of keybindings help text in the bottom line", - "default": [ - "blue" - ] - }, - "selectedLineBgColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Background color of selected line.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line", - "default": [ - "blue" - ] - }, - "inactiveViewSelectedLineBgColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Background color of selected line when view doesn't have focus.", - "default": [ - "bold" - ] - }, - "cherryPickedCommitFgColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Foreground color of copied commit", - "default": [ - "blue" - ] - }, - "cherryPickedCommitBgColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Background color of copied commit", - "default": [ - "cyan" - ] - }, - "markedBaseCommitFgColor": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Foreground color of marked base commit (for rebase)", - "default": [ - "blue" - ] - }, - "markedBaseCommitBgColor": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Background color of marked base commit (for rebase)", - "default": [ - "yellow" - ] - }, - "unstagedChangesColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Color for file with unstaged changes", - "default": [ - "red" - ] - }, - "defaultFgColor": { - "items": { - "type": "string" - }, - "type": "array", - "minItems": 1, - "uniqueItems": true, - "description": "Default text color", - "default": [ - "default" - ] - } - }, - "additionalProperties": false, - "type": "object", + "$ref": "#/$defs/ThemeConfig", "description": "Config relating to colors and styles.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#color-attributes" }, "commitLength": { - "properties": { - "show": { - "type": "boolean", - "description": "If true, show an indicator of commit message length", - "default": true - } - }, - "additionalProperties": false, - "type": "object", + "$ref": "#/$defs/CommitLengthConfig", "description": "Config relating to the commit length indicator" }, "showListFooter": { @@ -442,29 +661,7 @@ "default": "substring" }, "spinner": { - "properties": { - "frames": { - "items": { - "type": "string" - }, - "type": "array", - "description": "The frames of the spinner animation.", - "default": [ - "|", - "/", - "-", - "\\" - ] - }, - "rate": { - "type": "integer", - "minimum": 1, - "description": "The \"speed\" of the spinner in milliseconds.", - "default": 50 - } - }, - "additionalProperties": false, - "type": "object", + "$ref": "#/$defs/SpinnerConfig", "description": "Config relating to the spinner." }, "statusPanelView": { @@ -496,309 +693,766 @@ "type": "object", "description": "Config relating to the Lazygit UI" }, - "git": { + "KeybindingAmendAttributeConfig": { "properties": { - "paging": { - "properties": { - "colorArg": { - "type": "string", - "enum": [ - "always", - "never" - ], - "description": "Value of the --color arg in the git diff command. Some pagers want this to be set to 'always' and some want it set to 'never'", - "default": "always" - }, - "pager": { - "type": "string", - "description": "e.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat -s --wrap --width={{columnWidth}}", - "default": "", - "examples": [ - "delta --dark --paging=never", - "diff-so-fancy", - "ydiff -p cat -s --wrap --width={{columnWidth}}" - ] - }, - "useConfig": { - "type": "boolean", - "description": "If true, Lazygit will use whatever pager is specified in `$GIT_PAGER`, `$PAGER`, or your *git config*. If the pager ends with something like ` | less` we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).", - "default": false - }, - "externalDiffCommand": { - "type": "string", - "description": "e.g. 'difft --color=always'" - } - }, - "additionalProperties": false, - "type": "object", - "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md" + "resetAuthor": { + "type": "string", + "default": "a" }, - "commit": { - "properties": { - "signOff": { - "type": "boolean", - "description": "If true, pass '--signoff' flag when committing", - "default": false - }, - "autoWrapCommitMessage": { - "type": "boolean", - "description": "Automatic WYSIWYG wrapping of the commit message as you type", - "default": true - }, - "autoWrapWidth": { - "type": "integer", - "description": "If autoWrapCommitMessage is true, the width to wrap to", - "default": 72 - } - }, - "additionalProperties": false, - "type": "object", - "description": "Config relating to committing" + "setAuthor": { + "type": "string", + "default": "A" }, - "merging": { - "properties": { - "manualCommit": { - "type": "boolean", - "description": "If true, run merges in a subprocess so that if a commit message is required, Lazygit will not hang\nOnly applicable to unix users.", - "default": false - }, - "args": { - "type": "string", - "description": "Extra args passed to `git merge`, e.g. --no-ff", - "examples": [ - "--no-ff" - ] - }, - "squashMergeMessage": { - "type": "string", - "description": "The commit message to use for a squash merge commit. Can contain \"{{selectedRef}}\" and \"{{currentBranch}}\" placeholders.", - "default": "Squash merge {{selectedRef}} into {{currentBranch}}" - } - }, - "additionalProperties": false, - "type": "object", - "description": "Config relating to merging" + "addCoAuthor": { + "type": "string", + "default": "c" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingBranchesConfig": { + "properties": { + "createPullRequest": { + "type": "string", + "default": "o" }, - "mainBranches": { + "viewPullRequestOptions": { + "type": "string", + "default": "O" + }, + "copyPullRequestURL": { + "type": "string", + "default": "\u003cc-y\u003e" + }, + "checkoutBranchByName": { + "type": "string", + "default": "c" + }, + "forceCheckoutBranch": { + "type": "string", + "default": "F" + }, + "rebaseBranch": { + "type": "string", + "default": "r" + }, + "renameBranch": { + "type": "string", + "default": "R" + }, + "mergeIntoCurrentBranch": { + "type": "string", + "default": "M" + }, + "viewGitFlowOptions": { + "type": "string", + "default": "i" + }, + "fastForward": { + "type": "string", + "default": "f" + }, + "createTag": { + "type": "string", + "default": "T" + }, + "pushTag": { + "type": "string", + "default": "P" + }, + "setUpstream": { + "type": "string", + "default": "u" + }, + "fetchRemote": { + "type": "string", + "default": "f" + }, + "sortOrder": { + "type": "string", + "default": "s" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingCommitFilesConfig": { + "properties": { + "checkoutCommitFile": { + "type": "string", + "default": "c" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingCommitMessageConfig": { + "properties": { + "commitMenu": { + "type": "string", + "default": "\u003cc-o\u003e" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingCommitsConfig": { + "properties": { + "squashDown": { + "type": "string", + "default": "s" + }, + "renameCommit": { + "type": "string", + "default": "r" + }, + "renameCommitWithEditor": { + "type": "string", + "default": "R" + }, + "viewResetOptions": { + "type": "string", + "default": "g" + }, + "markCommitAsFixup": { + "type": "string", + "default": "f" + }, + "createFixupCommit": { + "type": "string", + "default": "F" + }, + "squashAboveCommits": { + "type": "string", + "default": "S" + }, + "moveDownCommit": { + "type": "string", + "default": "\u003cc-j\u003e" + }, + "moveUpCommit": { + "type": "string", + "default": "\u003cc-k\u003e" + }, + "amendToCommit": { + "type": "string", + "default": "A" + }, + "resetCommitAuthor": { + "type": "string", + "default": "a" + }, + "pickCommit": { + "type": "string", + "default": "p" + }, + "revertCommit": { + "type": "string", + "default": "t" + }, + "cherryPickCopy": { + "type": "string", + "default": "C" + }, + "pasteCommits": { + "type": "string", + "default": "V" + }, + "markCommitAsBaseForRebase": { + "type": "string", + "default": "B" + }, + "tagCommit": { + "type": "string", + "default": "T" + }, + "checkoutCommit": { + "type": "string", + "default": "\u003cspace\u003e" + }, + "resetCherryPick": { + "type": "string", + "default": "\u003cc-R\u003e" + }, + "copyCommitAttributeToClipboard": { + "type": "string", + "default": "y" + }, + "openLogMenu": { + "type": "string", + "default": "\u003cc-l\u003e" + }, + "openInBrowser": { + "type": "string", + "default": "o" + }, + "viewBisectOptions": { + "type": "string", + "default": "b" + }, + "startInteractiveRebase": { + "type": "string", + "default": "i" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingConfig": { + "properties": { + "universal": { + "$ref": "#/$defs/KeybindingUniversalConfig" + }, + "status": { + "$ref": "#/$defs/KeybindingStatusConfig" + }, + "files": { + "$ref": "#/$defs/KeybindingFilesConfig" + }, + "branches": { + "$ref": "#/$defs/KeybindingBranchesConfig" + }, + "worktrees": { + "$ref": "#/$defs/KeybindingWorktreesConfig" + }, + "commits": { + "$ref": "#/$defs/KeybindingCommitsConfig" + }, + "amendAttribute": { + "$ref": "#/$defs/KeybindingAmendAttributeConfig" + }, + "stash": { + "$ref": "#/$defs/KeybindingStashConfig" + }, + "commitFiles": { + "$ref": "#/$defs/KeybindingCommitFilesConfig" + }, + "main": { + "$ref": "#/$defs/KeybindingMainConfig" + }, + "submodules": { + "$ref": "#/$defs/KeybindingSubmodulesConfig" + }, + "commitMessage": { + "$ref": "#/$defs/KeybindingCommitMessageConfig" + } + }, + "additionalProperties": false, + "type": "object", + "description": "Keybindings" + }, + "KeybindingFilesConfig": { + "properties": { + "commitChanges": { + "type": "string", + "default": "c" + }, + "commitChangesWithoutHook": { + "type": "string", + "default": "w" + }, + "amendLastCommit": { + "type": "string", + "default": "A" + }, + "commitChangesWithEditor": { + "type": "string", + "default": "C" + }, + "findBaseCommitForFixup": { + "type": "string", + "default": "\u003cc-f\u003e" + }, + "confirmDiscard": { + "type": "string", + "default": "x" + }, + "ignoreFile": { + "type": "string", + "default": "i" + }, + "refreshFiles": { + "type": "string", + "default": "r" + }, + "stashAllChanges": { + "type": "string", + "default": "s" + }, + "viewStashOptions": { + "type": "string", + "default": "S" + }, + "toggleStagedAll": { + "type": "string", + "default": "a" + }, + "viewResetOptions": { + "type": "string", + "default": "D" + }, + "fetch": { + "type": "string", + "default": "f" + }, + "toggleTreeView": { + "type": "string", + "default": "`" + }, + "openMergeTool": { + "type": "string", + "default": "M" + }, + "openStatusFilter": { + "type": "string", + "default": "\u003cc-b\u003e" + }, + "copyFileInfoToClipboard": { + "type": "string", + "default": "y" + }, + "collapseAll": { + "type": "string", + "default": "-" + }, + "expandAll": { + "type": "string", + "default": "=" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingMainConfig": { + "properties": { + "toggleSelectHunk": { + "type": "string", + "default": "a" + }, + "pickBothHunks": { + "type": "string", + "default": "b" + }, + "editSelectHunk": { + "type": "string", + "default": "E" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingStashConfig": { + "properties": { + "popStash": { + "type": "string", + "default": "g" + }, + "renameStash": { + "type": "string", + "default": "r" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingStatusConfig": { + "properties": { + "checkForUpdate": { + "type": "string", + "default": "u" + }, + "recentRepos": { + "type": "string", + "default": "\u003center\u003e" + }, + "allBranchesLogGraph": { + "type": "string", + "default": "a" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingSubmodulesConfig": { + "properties": { + "init": { + "type": "string", + "default": "i" + }, + "update": { + "type": "string", + "default": "u" + }, + "bulkMenu": { + "type": "string", + "default": "b" + } + }, + "additionalProperties": false, + "type": "object" + }, + "KeybindingUniversalConfig": { + "properties": { + "quit": { + "type": "string", + "default": "q" + }, + "quit-alt1": { + "type": "string", + "default": "\u003cc-c\u003e" + }, + "return": { + "type": "string", + "default": "\u003cesc\u003e" + }, + "quitWithoutChangingDirectory": { + "type": "string", + "default": "Q" + }, + "togglePanel": { + "type": "string", + "default": "\u003ctab\u003e" + }, + "prevItem": { + "type": "string", + "default": "\u003cup\u003e" + }, + "nextItem": { + "type": "string", + "default": "\u003cdown\u003e" + }, + "prevItem-alt": { + "type": "string", + "default": "k" + }, + "nextItem-alt": { + "type": "string", + "default": "j" + }, + "prevPage": { + "type": "string", + "default": "," + }, + "nextPage": { + "type": "string", + "default": "." + }, + "scrollLeft": { + "type": "string", + "default": "H" + }, + "scrollRight": { + "type": "string", + "default": "L" + }, + "gotoTop": { + "type": "string", + "default": "\u003c" + }, + "gotoBottom": { + "type": "string", + "default": "\u003e" + }, + "toggleRangeSelect": { + "type": "string", + "default": "v" + }, + "rangeSelectDown": { + "type": "string", + "default": "\u003cs-down\u003e" + }, + "rangeSelectUp": { + "type": "string", + "default": "\u003cs-up\u003e" + }, + "prevBlock": { + "type": "string", + "default": "\u003cleft\u003e" + }, + "nextBlock": { + "type": "string", + "default": "\u003cright\u003e" + }, + "prevBlock-alt": { + "type": "string", + "default": "h" + }, + "nextBlock-alt": { + "type": "string", + "default": "l" + }, + "nextBlock-alt2": { + "type": "string", + "default": "\u003ctab\u003e" + }, + "prevBlock-alt2": { + "type": "string", + "default": "\u003cbacktab\u003e" + }, + "jumpToBlock": { "items": { "type": "string" }, "type": "array", - "uniqueItems": true, - "description": "list of branches that are considered 'main' branches, used when displaying commits", "default": [ - "master", - "main" + "1", + "2", + "3", + "4", + "5" ] }, - "skipHookPrefix": { + "nextMatch": { "type": "string", - "description": "Prefix to use when skipping hooks. E.g. if set to 'WIP', then pre-commit hooks will be skipped when the commit message starts with 'WIP'", - "default": "WIP" + "default": "n" }, - "autoFetch": { - "type": "boolean", - "description": "If true, periodically fetch from remote", - "default": true - }, - "autoRefresh": { - "type": "boolean", - "description": "If true, periodically refresh files and submodules", - "default": true - }, - "fetchAll": { - "type": "boolean", - "description": "If true, pass the --all arg to git fetch", - "default": true - }, - "autoStageResolvedConflicts": { - "type": "boolean", - "description": "If true, lazygit will automatically stage files that used to have merge\nconflicts but no longer do; and it will also ask you if you want to\ncontinue a merge or rebase if you've resolved all conflicts. If false, it\nwon't do either of these things.", - "default": true - }, - "branchLogCmd": { + "prevMatch": { "type": "string", - "description": "Command used when displaying the current branch git log in the main window", - "default": "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --" + "default": "N" }, - "allBranchesLogCmd": { + "startSearch": { "type": "string", - "description": "Command used to display git log of all branches in the main window.\nDeprecated: Use `allBranchesLogCmds` instead.", - "default": "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium" + "default": "/" }, - "allBranchesLogCmds": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Commands used to display git log of all branches in the main window, they will be cycled in order of appearance" - }, - "overrideGpg": { - "type": "boolean", - "description": "If true, do not spawn a separate process when using GPG", - "default": false - }, - "disableForcePushing": { - "type": "boolean", - "description": "If true, do not allow force pushes", - "default": false - }, - "commitPrefix": { - "items": { - "properties": { - "pattern": { - "type": "string", - "description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"", - "examples": [ - "^\\w+\\/(\\w+-\\w+).*" - ] - }, - "replace": { - "type": "string", - "description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"", - "examples": [ - "[$1]" - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "type": "array", - "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix" - }, - "commitPrefixes": { - "additionalProperties": { - "items": { - "properties": { - "pattern": { - "type": "string", - "description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"", - "examples": [ - "^\\w+\\/(\\w+-\\w+).*" - ] - }, - "replace": { - "type": "string", - "description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"", - "examples": [ - "[$1]" - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "type": "array" - }, - "type": "object", - "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix" - }, - "branchPrefix": { + "optionMenu": { "type": "string", - "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-branch-name-prefix" + "default": "\u003cdisabled\u003e" }, - "parseEmoji": { - "type": "boolean", - "description": "If true, parse emoji strings in commit messages e.g. render :rocket: as 🚀\n(This should really be under 'gui', not 'git')", - "default": false + "optionMenu-alt1": { + "type": "string", + "default": "?" }, - "log": { - "properties": { - "order": { - "type": "string", - "enum": [ - "date-order", - "author-date-order", - "topo-order", - "default" - ], - "description": "One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default'\n'topo-order' makes it easier to read the git log graph, but commits may not\nappear chronologically. See https://git-scm.com/docs/\n\nDeprecated: Configure this with `Log menu -\u003e Commit sort order` (\u003cc-l\u003e in the commits window by default).", - "default": "topo-order" - }, - "showGraph": { - "type": "string", - "enum": [ - "always", - "never", - "when-maximised" - ], - "description": "This determines whether the git graph is rendered in the commits panel\nOne of 'always' | 'never' | 'when-maximised'\n\nDeprecated: Configure this with `Log menu -\u003e Show git graph` (\u003cc-l\u003e in the commits window by default).", - "default": "always" - }, - "showWholeGraph": { - "type": "boolean", - "description": "displays the whole git graph by default in the commits view (equivalent to passing the `--all` argument to `git log`)", - "default": false - } - }, - "additionalProperties": false, - "type": "object", - "description": "Config for showing the log in the commits view" + "select": { + "type": "string", + "default": "\u003cspace\u003e" }, - "truncateCopiedCommitHashesTo": { - "type": "integer", - "description": "When copying commit hashes to the clipboard, truncate them to this\nlength. Set to 40 to disable truncation.", - "default": 12 + "goInto": { + "type": "string", + "default": "\u003center\u003e" + }, + "confirm": { + "type": "string", + "default": "\u003center\u003e" + }, + "confirmInEditor": { + "type": "string", + "default": "\u003ca-enter\u003e" + }, + "remove": { + "type": "string", + "default": "d" + }, + "new": { + "type": "string", + "default": "n" + }, + "edit": { + "type": "string", + "default": "e" + }, + "openFile": { + "type": "string", + "default": "o" + }, + "scrollUpMain": { + "type": "string", + "default": "\u003cpgup\u003e" + }, + "scrollDownMain": { + "type": "string", + "default": "\u003cpgdown\u003e" + }, + "scrollUpMain-alt1": { + "type": "string", + "default": "K" + }, + "scrollDownMain-alt1": { + "type": "string", + "default": "J" + }, + "scrollUpMain-alt2": { + "type": "string", + "default": "\u003cc-u\u003e" + }, + "scrollDownMain-alt2": { + "type": "string", + "default": "\u003cc-d\u003e" + }, + "executeShellCommand": { + "type": "string", + "default": ":" + }, + "createRebaseOptionsMenu": { + "type": "string", + "default": "m" + }, + "pushFiles": { + "type": "string", + "description": "'Files' appended for legacy reasons", + "default": "P" + }, + "pullFiles": { + "type": "string", + "description": "'Files' appended for legacy reasons", + "default": "p" + }, + "refresh": { + "type": "string", + "default": "R" + }, + "createPatchOptionsMenu": { + "type": "string", + "default": "\u003cc-p\u003e" + }, + "nextTab": { + "type": "string", + "default": "]" + }, + "prevTab": { + "type": "string", + "default": "[" + }, + "nextScreenMode": { + "type": "string", + "default": "+" + }, + "prevScreenMode": { + "type": "string", + "default": "_" + }, + "undo": { + "type": "string", + "default": "z" + }, + "redo": { + "type": "string", + "default": "\u003cc-z\u003e" + }, + "filteringMenu": { + "type": "string", + "default": "\u003cc-s\u003e" + }, + "diffingMenu": { + "type": "string", + "default": "W" + }, + "diffingMenu-alt": { + "type": "string", + "default": "\u003cc-e\u003e" + }, + "copyToClipboard": { + "type": "string", + "default": "\u003cc-o\u003e" + }, + "openRecentRepos": { + "type": "string", + "default": "\u003cc-r\u003e" + }, + "submitEditorText": { + "type": "string", + "default": "\u003center\u003e" + }, + "extrasMenu": { + "type": "string", + "default": "@" + }, + "toggleWhitespaceInDiffView": { + "type": "string", + "default": "\u003cc-w\u003e" + }, + "increaseContextInDiffView": { + "type": "string", + "default": "}" + }, + "decreaseContextInDiffView": { + "type": "string", + "default": "{" + }, + "increaseRenameSimilarityThreshold": { + "type": "string", + "default": ")" + }, + "decreaseRenameSimilarityThreshold": { + "type": "string", + "default": "(" + }, + "openDiffTool": { + "type": "string", + "default": "\u003cc-t\u003e" } }, "additionalProperties": false, - "type": "object", - "description": "Config relating to git" + "type": "object" }, - "update": { + "KeybindingWorktreesConfig": { "properties": { - "method": { + "viewWorktreeOptions": { + "type": "string", + "default": "w" + } + }, + "additionalProperties": false, + "type": "object" + }, + "LogConfig": { + "properties": { + "order": { "type": "string", "enum": [ - "prompt", - "background", - "never" + "date-order", + "author-date-order", + "topo-order", + "default" ], - "description": "One of: 'prompt' (default) | 'background' | 'never'", - "default": "prompt" + "description": "One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default'\n'topo-order' makes it easier to read the git log graph, but commits may not\nappear chronologically. See https://git-scm.com/docs/\n\nDeprecated: Configure this with `Log menu -\u003e Commit sort order` (\u003cc-l\u003e in the commits window by default).", + "default": "topo-order" }, - "days": { - "type": "integer", - "minimum": 0, - "description": "Period in days between update checks", - "default": 14 + "showGraph": { + "type": "string", + "enum": [ + "always", + "never", + "when-maximised" + ], + "description": "This determines whether the git graph is rendered in the commits panel\nOne of 'always' | 'never' | 'when-maximised'\n\nDeprecated: Configure this with `Log menu -\u003e Show git graph` (\u003cc-l\u003e in the commits window by default).", + "default": "always" + }, + "showWholeGraph": { + "type": "boolean", + "description": "displays the whole git graph by default in the commits view (equivalent to passing the `--all` argument to `git log`)", + "default": false } }, "additionalProperties": false, "type": "object", - "description": "Periodic update checks" + "description": "Config for showing the log in the commits view" }, - "refresher": { + "MergingConfig": { "properties": { - "refreshInterval": { - "type": "integer", - "minimum": 0, - "description": "File/submodule refresh interval in seconds.\nAuto-refresh can be disabled via option 'git.autoRefresh'.", - "default": 10 + "manualCommit": { + "type": "boolean", + "description": "If true, run merges in a subprocess so that if a commit message is required, Lazygit will not hang\nOnly applicable to unix users.", + "default": false }, - "fetchInterval": { - "type": "integer", - "minimum": 0, - "description": "Re-fetch interval in seconds.\nAuto-fetch can be disabled via option 'git.autoFetch'.", - "default": 60 + "args": { + "type": "string", + "description": "Extra args passed to `git merge`, e.g. --no-ff", + "examples": [ + "--no-ff" + ] + }, + "squashMergeMessage": { + "type": "string", + "description": "The commit message to use for a squash merge commit. Can contain \"{{selectedRef}}\" and \"{{currentBranch}}\" placeholders.", + "default": "Squash merge {{selectedRef}} into {{currentBranch}}" } }, "additionalProperties": false, "type": "object", - "description": "Background refreshes" + "description": "Config relating to merging" }, - "confirmOnQuit": { - "type": "boolean", - "description": "If true, show a confirmation popup before quitting Lazygit", - "default": false - }, - "quitOnTopLevelReturn": { - "type": "boolean", - "description": "If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close", - "default": false - }, - "os": { + "OSConfig": { "properties": { "edit": { "type": "string", @@ -873,893 +1527,333 @@ "type": "object", "description": "Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc" }, - "disableStartupPopups": { - "type": "boolean", - "description": "If true, don't display introductory popups upon opening Lazygit.", - "default": false - }, - "customCommands": { - "items": { - "properties": { - "key": { - "type": "string", - "description": "The key to trigger the command. Use a single letter or one of the values from https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md" - }, - "context": { - "type": "string", - "description": "The context in which to listen for the key. Valid values are: status, files, worktrees, localBranches, remotes, remoteBranches, tags, commits, reflogCommits, subCommits, commitFiles, stash, and global. Multiple contexts separated by comma are allowed; most useful for \"commits, subCommits\" or \"files, commitFiles\".", - "examples": [ - "status", - "files", - "worktrees", - "localBranches", - "remotes", - "remoteBranches", - "tags", - "commits", - "reflogCommits", - "subCommits", - "commitFiles", - "stash", - "global" - ] - }, - "command": { - "type": "string", - "description": "The command to run (using Go template syntax for placeholder values)", - "examples": [ - "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": { - "items": { - "properties": { - "type": { - "type": "string", - "description": "One of: 'input' | 'menu' | 'confirm' | 'menuFromCommand'" - }, - "key": { - "type": "string", - "description": "Used to reference the entered value from within the custom command. E.g. a prompt with `key: 'Branch'` can be referred to as `{{.Form.Branch}}` in the command" - }, - "title": { - "type": "string", - "description": "The title to display in the popup panel" - }, - "initialValue": { - "type": "string", - "description": "The initial value to appear in the text box.\nOnly for input prompts." - }, - "suggestions": { - "properties": { - "preset": { - "type": "string", - "enum": [ - "authors", - "branches", - "files", - "refs", - "remotes", - "remoteBranches", - "tags" - ], - "description": "Uses built-in logic to obtain the suggestions. One of 'authors' | 'branches' | 'files' | 'refs' | 'remotes' | 'remoteBranches' | 'tags'" - }, - "command": { - "type": "string", - "description": "Command to run such that each line in the output becomes a suggestion. Mutually exclusive with 'preset' field.", - "examples": [ - "git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD" - ] - } - }, - "additionalProperties": false, - "type": "object", - "description": "Shows suggestions as the input is entered\nOnly for input prompts." - }, - "body": { - "type": "string", - "description": "The message of the confirmation prompt.\nOnly for confirm prompts.", - "examples": [ - "Are you sure you want to push to the remote?" - ] - }, - "options": { - "items": { - "properties": { - "name": { - "type": "string", - "description": "The first part of the label" - }, - "description": { - "type": "string", - "description": "The second part of the label" - }, - "value": { - "type": "string", - "minLength": 1, - "description": "The value that will be used in the command", - "examples": [ - "feature" - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "type": "array", - "description": "Menu options.\nOnly for menu prompts." - }, - "command": { - "type": "string", - "description": "The command to run to generate menu options\nOnly for menuFromCommand prompts.", - "examples": [ - "git fetch {{.Form.Remote}} {{.Form.Branch}} \u0026\u0026 git checkout FETCH_HEAD" - ] - }, - "filter": { - "type": "string", - "description": "The regexp to run specifying groups which are going to be kept from the command's output.\nOnly for menuFromCommand prompts.", - "examples": [ - ".*{{.SelectedRemote.Name }}/(?P\u003cbranch\u003e.*)" - ] - }, - "valueFormat": { - "type": "string", - "description": "How to format matched groups from the filter to construct a menu item's value.\nOnly for menuFromCommand prompts.", - "examples": [ - "{{ .branch }}" - ] - }, - "labelFormat": { - "type": "string", - "description": "Like valueFormat but for the labels. If `labelFormat` is not specified, `valueFormat` is shown instead.\nOnly for menuFromCommand prompts.", - "examples": [ - "{{ .branch | green }}" - ] - } - }, - "additionalProperties": false, - "type": "object" - }, - "type": "array", - "description": "A list of prompts that will request user input before running the final command" - }, - "loadingText": { - "type": "string", - "description": "Text to display while waiting for command to finish", - "examples": [ - "Loading..." - ] - }, - "description": { - "type": "string", - "description": "Label for the custom command when displayed in the keybindings menu" - }, - "stream": { - "type": "boolean", - "description": "If true, stream the command's output to the Command Log panel" - }, - "showOutput": { - "type": "boolean", - "description": "If true, show the command's output in a popup within Lazygit" - }, - "outputTitle": { - "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." - }, - "after": { - "properties": { - "checkForConflicts": { - "type": "boolean" - } - }, - "additionalProperties": false, - "type": "object", - "description": "Actions to take after the command has completed" - } - }, - "additionalProperties": false, - "type": "object" - }, - "type": "array", - "uniqueItems": true, - "description": "User-configured commands that can be invoked from within Lazygit" - }, - "services": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-pull-request-urls" - }, - "notARepository": { - "type": "string", - "enum": [ - "prompt", - "create", - "skip", - "quit" - ], - "description": "What to do when opening Lazygit outside of a git repo.\n- 'prompt': (default) ask whether to initialize a new repo or open in the most recent repo\n- 'create': initialize a new repo\n- 'skip': open most recent repo\n- 'quit': exit Lazygit", - "default": "prompt" - }, - "promptToReturnFromSubprocess": { - "type": "boolean", - "description": "If true, display a confirmation when subprocess terminates. This allows you to view the output of the subprocess before returning to Lazygit.", - "default": true - }, - "keybinding": { + "PagingConfig": { "properties": { - "universal": { - "properties": { - "quit": { - "type": "string", - "default": "q" - }, - "quit-alt1": { - "type": "string", - "default": "\u003cc-c\u003e" - }, - "return": { - "type": "string", - "default": "\u003cesc\u003e" - }, - "quitWithoutChangingDirectory": { - "type": "string", - "default": "Q" - }, - "togglePanel": { - "type": "string", - "default": "\u003ctab\u003e" - }, - "prevItem": { - "type": "string", - "default": "\u003cup\u003e" - }, - "nextItem": { - "type": "string", - "default": "\u003cdown\u003e" - }, - "prevItem-alt": { - "type": "string", - "default": "k" - }, - "nextItem-alt": { - "type": "string", - "default": "j" - }, - "prevPage": { - "type": "string", - "default": "," - }, - "nextPage": { - "type": "string", - "default": "." - }, - "scrollLeft": { - "type": "string", - "default": "H" - }, - "scrollRight": { - "type": "string", - "default": "L" - }, - "gotoTop": { - "type": "string", - "default": "\u003c" - }, - "gotoBottom": { - "type": "string", - "default": "\u003e" - }, - "toggleRangeSelect": { - "type": "string", - "default": "v" - }, - "rangeSelectDown": { - "type": "string", - "default": "\u003cs-down\u003e" - }, - "rangeSelectUp": { - "type": "string", - "default": "\u003cs-up\u003e" - }, - "prevBlock": { - "type": "string", - "default": "\u003cleft\u003e" - }, - "nextBlock": { - "type": "string", - "default": "\u003cright\u003e" - }, - "prevBlock-alt": { - "type": "string", - "default": "h" - }, - "nextBlock-alt": { - "type": "string", - "default": "l" - }, - "nextBlock-alt2": { - "type": "string", - "default": "\u003ctab\u003e" - }, - "prevBlock-alt2": { - "type": "string", - "default": "\u003cbacktab\u003e" - }, - "jumpToBlock": { - "items": { - "type": "string" - }, - "type": "array", - "default": [ - "1", - "2", - "3", - "4", - "5" - ] - }, - "nextMatch": { - "type": "string", - "default": "n" - }, - "prevMatch": { - "type": "string", - "default": "N" - }, - "startSearch": { - "type": "string", - "default": "/" - }, - "optionMenu": { - "type": "string", - "default": "\u003cdisabled\u003e" - }, - "optionMenu-alt1": { - "type": "string", - "default": "?" - }, - "select": { - "type": "string", - "default": "\u003cspace\u003e" - }, - "goInto": { - "type": "string", - "default": "\u003center\u003e" - }, - "confirm": { - "type": "string", - "default": "\u003center\u003e" - }, - "confirmInEditor": { - "type": "string", - "default": "\u003ca-enter\u003e" - }, - "remove": { - "type": "string", - "default": "d" - }, - "new": { - "type": "string", - "default": "n" - }, - "edit": { - "type": "string", - "default": "e" - }, - "openFile": { - "type": "string", - "default": "o" - }, - "scrollUpMain": { - "type": "string", - "default": "\u003cpgup\u003e" - }, - "scrollDownMain": { - "type": "string", - "default": "\u003cpgdown\u003e" - }, - "scrollUpMain-alt1": { - "type": "string", - "default": "K" - }, - "scrollDownMain-alt1": { - "type": "string", - "default": "J" - }, - "scrollUpMain-alt2": { - "type": "string", - "default": "\u003cc-u\u003e" - }, - "scrollDownMain-alt2": { - "type": "string", - "default": "\u003cc-d\u003e" - }, - "executeShellCommand": { - "type": "string", - "default": ":" - }, - "createRebaseOptionsMenu": { - "type": "string", - "default": "m" - }, - "pushFiles": { - "type": "string", - "description": "'Files' appended for legacy reasons", - "default": "P" - }, - "pullFiles": { - "type": "string", - "description": "'Files' appended for legacy reasons", - "default": "p" - }, - "refresh": { - "type": "string", - "default": "R" - }, - "createPatchOptionsMenu": { - "type": "string", - "default": "\u003cc-p\u003e" - }, - "nextTab": { - "type": "string", - "default": "]" - }, - "prevTab": { - "type": "string", - "default": "[" - }, - "nextScreenMode": { - "type": "string", - "default": "+" - }, - "prevScreenMode": { - "type": "string", - "default": "_" - }, - "undo": { - "type": "string", - "default": "z" - }, - "redo": { - "type": "string", - "default": "\u003cc-z\u003e" - }, - "filteringMenu": { - "type": "string", - "default": "\u003cc-s\u003e" - }, - "diffingMenu": { - "type": "string", - "default": "W" - }, - "diffingMenu-alt": { - "type": "string", - "default": "\u003cc-e\u003e" - }, - "copyToClipboard": { - "type": "string", - "default": "\u003cc-o\u003e" - }, - "openRecentRepos": { - "type": "string", - "default": "\u003cc-r\u003e" - }, - "submitEditorText": { - "type": "string", - "default": "\u003center\u003e" - }, - "extrasMenu": { - "type": "string", - "default": "@" - }, - "toggleWhitespaceInDiffView": { - "type": "string", - "default": "\u003cc-w\u003e" - }, - "increaseContextInDiffView": { - "type": "string", - "default": "}" - }, - "decreaseContextInDiffView": { - "type": "string", - "default": "{" - }, - "increaseRenameSimilarityThreshold": { - "type": "string", - "default": ")" - }, - "decreaseRenameSimilarityThreshold": { - "type": "string", - "default": "(" - }, - "openDiffTool": { - "type": "string", - "default": "\u003cc-t\u003e" - } - }, - "additionalProperties": false, - "type": "object" + "colorArg": { + "type": "string", + "enum": [ + "always", + "never" + ], + "description": "Value of the --color arg in the git diff command. Some pagers want this to be set to 'always' and some want it set to 'never'", + "default": "always" }, - "status": { - "properties": { - "checkForUpdate": { - "type": "string", - "default": "u" - }, - "recentRepos": { - "type": "string", - "default": "\u003center\u003e" - }, - "allBranchesLogGraph": { - "type": "string", - "default": "a" - } - }, - "additionalProperties": false, - "type": "object" + "pager": { + "type": "string", + "description": "e.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat -s --wrap --width={{columnWidth}}", + "default": "", + "examples": [ + "delta --dark --paging=never", + "diff-so-fancy", + "ydiff -p cat -s --wrap --width={{columnWidth}}" + ] }, - "files": { - "properties": { - "commitChanges": { - "type": "string", - "default": "c" - }, - "commitChangesWithoutHook": { - "type": "string", - "default": "w" - }, - "amendLastCommit": { - "type": "string", - "default": "A" - }, - "commitChangesWithEditor": { - "type": "string", - "default": "C" - }, - "findBaseCommitForFixup": { - "type": "string", - "default": "\u003cc-f\u003e" - }, - "confirmDiscard": { - "type": "string", - "default": "x" - }, - "ignoreFile": { - "type": "string", - "default": "i" - }, - "refreshFiles": { - "type": "string", - "default": "r" - }, - "stashAllChanges": { - "type": "string", - "default": "s" - }, - "viewStashOptions": { - "type": "string", - "default": "S" - }, - "toggleStagedAll": { - "type": "string", - "default": "a" - }, - "viewResetOptions": { - "type": "string", - "default": "D" - }, - "fetch": { - "type": "string", - "default": "f" - }, - "toggleTreeView": { - "type": "string", - "default": "`" - }, - "openMergeTool": { - "type": "string", - "default": "M" - }, - "openStatusFilter": { - "type": "string", - "default": "\u003cc-b\u003e" - }, - "copyFileInfoToClipboard": { - "type": "string", - "default": "y" - }, - "collapseAll": { - "type": "string", - "default": "-" - }, - "expandAll": { - "type": "string", - "default": "=" - } - }, - "additionalProperties": false, - "type": "object" + "useConfig": { + "type": "boolean", + "description": "If true, Lazygit will use whatever pager is specified in `$GIT_PAGER`, `$PAGER`, or your *git config*. If the pager ends with something like ` | less` we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).", + "default": false }, - "branches": { - "properties": { - "createPullRequest": { - "type": "string", - "default": "o" - }, - "viewPullRequestOptions": { - "type": "string", - "default": "O" - }, - "copyPullRequestURL": { - "type": "string", - "default": "\u003cc-y\u003e" - }, - "checkoutBranchByName": { - "type": "string", - "default": "c" - }, - "forceCheckoutBranch": { - "type": "string", - "default": "F" - }, - "rebaseBranch": { - "type": "string", - "default": "r" - }, - "renameBranch": { - "type": "string", - "default": "R" - }, - "mergeIntoCurrentBranch": { - "type": "string", - "default": "M" - }, - "viewGitFlowOptions": { - "type": "string", - "default": "i" - }, - "fastForward": { - "type": "string", - "default": "f" - }, - "createTag": { - "type": "string", - "default": "T" - }, - "pushTag": { - "type": "string", - "default": "P" - }, - "setUpstream": { - "type": "string", - "default": "u" - }, - "fetchRemote": { - "type": "string", - "default": "f" - }, - "sortOrder": { - "type": "string", - "default": "s" - } - }, - "additionalProperties": false, - "type": "object" - }, - "worktrees": { - "properties": { - "viewWorktreeOptions": { - "type": "string", - "default": "w" - } - }, - "additionalProperties": false, - "type": "object" - }, - "commits": { - "properties": { - "squashDown": { - "type": "string", - "default": "s" - }, - "renameCommit": { - "type": "string", - "default": "r" - }, - "renameCommitWithEditor": { - "type": "string", - "default": "R" - }, - "viewResetOptions": { - "type": "string", - "default": "g" - }, - "markCommitAsFixup": { - "type": "string", - "default": "f" - }, - "createFixupCommit": { - "type": "string", - "default": "F" - }, - "squashAboveCommits": { - "type": "string", - "default": "S" - }, - "moveDownCommit": { - "type": "string", - "default": "\u003cc-j\u003e" - }, - "moveUpCommit": { - "type": "string", - "default": "\u003cc-k\u003e" - }, - "amendToCommit": { - "type": "string", - "default": "A" - }, - "resetCommitAuthor": { - "type": "string", - "default": "a" - }, - "pickCommit": { - "type": "string", - "default": "p" - }, - "revertCommit": { - "type": "string", - "default": "t" - }, - "cherryPickCopy": { - "type": "string", - "default": "C" - }, - "pasteCommits": { - "type": "string", - "default": "V" - }, - "markCommitAsBaseForRebase": { - "type": "string", - "default": "B" - }, - "tagCommit": { - "type": "string", - "default": "T" - }, - "checkoutCommit": { - "type": "string", - "default": "\u003cspace\u003e" - }, - "resetCherryPick": { - "type": "string", - "default": "\u003cc-R\u003e" - }, - "copyCommitAttributeToClipboard": { - "type": "string", - "default": "y" - }, - "openLogMenu": { - "type": "string", - "default": "\u003cc-l\u003e" - }, - "openInBrowser": { - "type": "string", - "default": "o" - }, - "viewBisectOptions": { - "type": "string", - "default": "b" - }, - "startInteractiveRebase": { - "type": "string", - "default": "i" - } - }, - "additionalProperties": false, - "type": "object" - }, - "amendAttribute": { - "properties": { - "resetAuthor": { - "type": "string", - "default": "a" - }, - "setAuthor": { - "type": "string", - "default": "A" - }, - "addCoAuthor": { - "type": "string", - "default": "c" - } - }, - "additionalProperties": false, - "type": "object" - }, - "stash": { - "properties": { - "popStash": { - "type": "string", - "default": "g" - }, - "renameStash": { - "type": "string", - "default": "r" - } - }, - "additionalProperties": false, - "type": "object" - }, - "commitFiles": { - "properties": { - "checkoutCommitFile": { - "type": "string", - "default": "c" - } - }, - "additionalProperties": false, - "type": "object" - }, - "main": { - "properties": { - "toggleSelectHunk": { - "type": "string", - "default": "a" - }, - "pickBothHunks": { - "type": "string", - "default": "b" - }, - "editSelectHunk": { - "type": "string", - "default": "E" - } - }, - "additionalProperties": false, - "type": "object" - }, - "submodules": { - "properties": { - "init": { - "type": "string", - "default": "i" - }, - "update": { - "type": "string", - "default": "u" - }, - "bulkMenu": { - "type": "string", - "default": "b" - } - }, - "additionalProperties": false, - "type": "object" - }, - "commitMessage": { - "properties": { - "commitMenu": { - "type": "string", - "default": "\u003cc-o\u003e" - } - }, - "additionalProperties": false, - "type": "object" + "externalDiffCommand": { + "type": "string", + "description": "e.g. 'difft --color=always'" } }, "additionalProperties": false, "type": "object", - "description": "Keybindings" + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md" + }, + "RefresherConfig": { + "properties": { + "refreshInterval": { + "type": "integer", + "minimum": 0, + "description": "File/submodule refresh interval in seconds.\nAuto-refresh can be disabled via option 'git.autoRefresh'.", + "default": 10 + }, + "fetchInterval": { + "type": "integer", + "minimum": 0, + "description": "Re-fetch interval in seconds.\nAuto-fetch can be disabled via option 'git.autoFetch'.", + "default": 60 + } + }, + "additionalProperties": false, + "type": "object", + "description": "Background refreshes" + }, + "SpinnerConfig": { + "properties": { + "frames": { + "items": { + "type": "string" + }, + "type": "array", + "description": "The frames of the spinner animation.", + "default": [ + "|", + "/", + "-", + "\\" + ] + }, + "rate": { + "type": "integer", + "minimum": 1, + "description": "The \"speed\" of the spinner in milliseconds.", + "default": 50 + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config relating to the spinner." + }, + "ThemeConfig": { + "properties": { + "activeBorderColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Border color of focused window", + "default": [ + "green", + "bold" + ] + }, + "inactiveBorderColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Border color of non-focused windows", + "default": [ + "default" + ] + }, + "searchingActiveBorderColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Border color of focused window when searching in that window", + "default": [ + "cyan", + "bold" + ] + }, + "optionsTextColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Color of keybindings help text in the bottom line", + "default": [ + "blue" + ] + }, + "selectedLineBgColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Background color of selected line.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line", + "default": [ + "blue" + ] + }, + "inactiveViewSelectedLineBgColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Background color of selected line when view doesn't have focus.", + "default": [ + "bold" + ] + }, + "cherryPickedCommitFgColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Foreground color of copied commit", + "default": [ + "blue" + ] + }, + "cherryPickedCommitBgColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Background color of copied commit", + "default": [ + "cyan" + ] + }, + "markedBaseCommitFgColor": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Foreground color of marked base commit (for rebase)", + "default": [ + "blue" + ] + }, + "markedBaseCommitBgColor": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Background color of marked base commit (for rebase)", + "default": [ + "yellow" + ] + }, + "unstagedChangesColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Color for file with unstaged changes", + "default": [ + "red" + ] + }, + "defaultFgColor": { + "items": { + "type": "string" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "description": "Default text color", + "default": [ + "default" + ] + } + }, + "additionalProperties": false, + "type": "object", + "description": "Config relating to colors and styles.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#color-attributes" + }, + "UpdateConfig": { + "properties": { + "method": { + "type": "string", + "enum": [ + "prompt", + "background", + "never" + ], + "description": "One of: 'prompt' (default) | 'background' | 'never'", + "default": "prompt" + }, + "days": { + "type": "integer", + "minimum": 0, + "description": "Period in days between update checks", + "default": 14 + } + }, + "additionalProperties": false, + "type": "object", + "description": "Periodic update checks" + }, + "UserConfig": { + "properties": { + "gui": { + "$ref": "#/$defs/GuiConfig", + "description": "Config relating to the Lazygit UI" + }, + "git": { + "$ref": "#/$defs/GitConfig", + "description": "Config relating to git" + }, + "update": { + "$ref": "#/$defs/UpdateConfig", + "description": "Periodic update checks" + }, + "refresher": { + "$ref": "#/$defs/RefresherConfig", + "description": "Background refreshes" + }, + "confirmOnQuit": { + "type": "boolean", + "description": "If true, show a confirmation popup before quitting Lazygit", + "default": false + }, + "quitOnTopLevelReturn": { + "type": "boolean", + "description": "If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close", + "default": false + }, + "os": { + "$ref": "#/$defs/OSConfig", + "description": "Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc" + }, + "disableStartupPopups": { + "type": "boolean", + "description": "If true, don't display introductory popups upon opening Lazygit.", + "default": false + }, + "customCommands": { + "items": { + "$ref": "#/$defs/CustomCommand" + }, + "type": "array", + "uniqueItems": true, + "description": "User-configured commands that can be invoked from within Lazygit" + }, + "services": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-pull-request-urls" + }, + "notARepository": { + "type": "string", + "enum": [ + "prompt", + "create", + "skip", + "quit" + ], + "description": "What to do when opening Lazygit outside of a git repo.\n- 'prompt': (default) ask whether to initialize a new repo or open in the most recent repo\n- 'create': initialize a new repo\n- 'skip': open most recent repo\n- 'quit': exit Lazygit", + "default": "prompt" + }, + "promptToReturnFromSubprocess": { + "type": "boolean", + "description": "If true, display a confirmation when subprocess terminates. This allows you to view the output of the subprocess before returning to Lazygit.", + "default": true + }, + "keybinding": { + "$ref": "#/$defs/KeybindingConfig", + "description": "Keybindings" + } + }, + "additionalProperties": false, + "type": "object" } - }, - "additionalProperties": false, - "type": "object" + } } diff --git a/vendor/github.com/iancoleman/orderedmap/LICENSE b/vendor/github.com/iancoleman/orderedmap/LICENSE deleted file mode 100644 index 2732e3795..000000000 --- a/vendor/github.com/iancoleman/orderedmap/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Ian Coleman - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, Subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or Substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/iancoleman/orderedmap/orderedmap.go b/vendor/github.com/iancoleman/orderedmap/orderedmap.go deleted file mode 100644 index 61587d9c7..000000000 --- a/vendor/github.com/iancoleman/orderedmap/orderedmap.go +++ /dev/null @@ -1,266 +0,0 @@ -package orderedmap - -import ( - "bytes" - "encoding/json" - "sort" -) - -type Pair struct { - key string - value interface{} -} - -func (kv *Pair) Key() string { - return kv.key -} - -func (kv *Pair) Value() interface{} { - return kv.value -} - -type ByPair struct { - Pairs []*Pair - LessFunc func(a *Pair, j *Pair) bool -} - -func (a ByPair) Len() int { return len(a.Pairs) } -func (a ByPair) Swap(i, j int) { a.Pairs[i], a.Pairs[j] = a.Pairs[j], a.Pairs[i] } -func (a ByPair) Less(i, j int) bool { return a.LessFunc(a.Pairs[i], a.Pairs[j]) } - -type OrderedMap struct { - keys []string - values map[string]interface{} - escapeHTML bool -} - -func New() *OrderedMap { - o := OrderedMap{} - o.keys = []string{} - o.values = map[string]interface{}{} - o.escapeHTML = true - return &o -} - -func (o *OrderedMap) SetEscapeHTML(on bool) { - o.escapeHTML = on -} - -func (o *OrderedMap) Get(key string) (interface{}, bool) { - val, exists := o.values[key] - return val, exists -} - -func (o *OrderedMap) Set(key string, value interface{}) { - _, exists := o.values[key] - if !exists { - o.keys = append(o.keys, key) - } - o.values[key] = value -} - -func (o *OrderedMap) Delete(key string) { - // check key is in use - _, ok := o.values[key] - if !ok { - return - } - // remove from keys - for i, k := range o.keys { - if k == key { - o.keys = append(o.keys[:i], o.keys[i+1:]...) - break - } - } - // remove from values - delete(o.values, key) -} - -func (o *OrderedMap) Keys() []string { - return o.keys -} - -func (o *OrderedMap) Values() map[string]interface{} { - return o.values -} - -// SortKeys Sort the map keys using your sort func -func (o *OrderedMap) SortKeys(sortFunc func(keys []string)) { - sortFunc(o.keys) -} - -// Sort Sort the map using your sort func -func (o *OrderedMap) Sort(lessFunc func(a *Pair, b *Pair) bool) { - pairs := make([]*Pair, len(o.keys)) - for i, key := range o.keys { - pairs[i] = &Pair{key, o.values[key]} - } - - sort.Sort(ByPair{pairs, lessFunc}) - - for i, pair := range pairs { - o.keys[i] = pair.key - } -} - -func (o *OrderedMap) UnmarshalJSON(b []byte) error { - if o.values == nil { - o.values = map[string]interface{}{} - } - err := json.Unmarshal(b, &o.values) - if err != nil { - return err - } - dec := json.NewDecoder(bytes.NewReader(b)) - if _, err = dec.Token(); err != nil { // skip '{' - return err - } - o.keys = make([]string, 0, len(o.values)) - return decodeOrderedMap(dec, o) -} - -func decodeOrderedMap(dec *json.Decoder, o *OrderedMap) error { - hasKey := make(map[string]bool, len(o.values)) - for { - token, err := dec.Token() - if err != nil { - return err - } - if delim, ok := token.(json.Delim); ok && delim == '}' { - return nil - } - key := token.(string) - if hasKey[key] { - // duplicate key - for j, k := range o.keys { - if k == key { - copy(o.keys[j:], o.keys[j+1:]) - break - } - } - o.keys[len(o.keys)-1] = key - } else { - hasKey[key] = true - o.keys = append(o.keys, key) - } - - token, err = dec.Token() - if err != nil { - return err - } - if delim, ok := token.(json.Delim); ok { - switch delim { - case '{': - if values, ok := o.values[key].(map[string]interface{}); ok { - newMap := OrderedMap{ - keys: make([]string, 0, len(values)), - values: values, - escapeHTML: o.escapeHTML, - } - if err = decodeOrderedMap(dec, &newMap); err != nil { - return err - } - o.values[key] = newMap - } else if oldMap, ok := o.values[key].(OrderedMap); ok { - newMap := OrderedMap{ - keys: make([]string, 0, len(oldMap.values)), - values: oldMap.values, - escapeHTML: o.escapeHTML, - } - if err = decodeOrderedMap(dec, &newMap); err != nil { - return err - } - o.values[key] = newMap - } else if err = decodeOrderedMap(dec, &OrderedMap{}); err != nil { - return err - } - case '[': - if values, ok := o.values[key].([]interface{}); ok { - if err = decodeSlice(dec, values, o.escapeHTML); err != nil { - return err - } - } else if err = decodeSlice(dec, []interface{}{}, o.escapeHTML); err != nil { - return err - } - } - } - } -} - -func decodeSlice(dec *json.Decoder, s []interface{}, escapeHTML bool) error { - for index := 0; ; index++ { - token, err := dec.Token() - if err != nil { - return err - } - if delim, ok := token.(json.Delim); ok { - switch delim { - case '{': - if index < len(s) { - if values, ok := s[index].(map[string]interface{}); ok { - newMap := OrderedMap{ - keys: make([]string, 0, len(values)), - values: values, - escapeHTML: escapeHTML, - } - if err = decodeOrderedMap(dec, &newMap); err != nil { - return err - } - s[index] = newMap - } else if oldMap, ok := s[index].(OrderedMap); ok { - newMap := OrderedMap{ - keys: make([]string, 0, len(oldMap.values)), - values: oldMap.values, - escapeHTML: escapeHTML, - } - if err = decodeOrderedMap(dec, &newMap); err != nil { - return err - } - s[index] = newMap - } else if err = decodeOrderedMap(dec, &OrderedMap{}); err != nil { - return err - } - } else if err = decodeOrderedMap(dec, &OrderedMap{}); err != nil { - return err - } - case '[': - if index < len(s) { - if values, ok := s[index].([]interface{}); ok { - if err = decodeSlice(dec, values, escapeHTML); err != nil { - return err - } - } else if err = decodeSlice(dec, []interface{}{}, escapeHTML); err != nil { - return err - } - } else if err = decodeSlice(dec, []interface{}{}, escapeHTML); err != nil { - return err - } - case ']': - return nil - } - } - } -} - -func (o OrderedMap) MarshalJSON() ([]byte, error) { - var buf bytes.Buffer - buf.WriteByte('{') - encoder := json.NewEncoder(&buf) - encoder.SetEscapeHTML(o.escapeHTML) - for i, k := range o.keys { - if i > 0 { - buf.WriteByte(',') - } - // add key - if err := encoder.Encode(k); err != nil { - return nil, err - } - buf.WriteByte(':') - // add value - if err := encoder.Encode(o.values[k]); err != nil { - return nil, err - } - } - buf.WriteByte('}') - return buf.Bytes(), nil -} diff --git a/vendor/github.com/iancoleman/orderedmap/readme.md b/vendor/github.com/iancoleman/orderedmap/readme.md deleted file mode 100644 index cfe09c2fd..000000000 --- a/vendor/github.com/iancoleman/orderedmap/readme.md +++ /dev/null @@ -1,81 +0,0 @@ -# orderedmap - -[![Build Status](https://travis-ci.com/iancoleman/orderedmap.svg)](https://travis-ci.com/iancoleman/orderedmap) - -A golang data type equivalent to python's collections.OrderedDict - -Retains order of keys in maps - -Can be JSON serialized / deserialized - -# Usage - -```go -package main - -import ( - "encoding/json" - "github.com/iancoleman/orderedmap" -) - -func main() { - - // use New() instead of o := map[string]interface{}{} - o := orderedmap.New() - - // use SetEscapeHTML() to whether escape problematic HTML characters or not, defaults is true - o.SetEscapeHTML(false) - - // use Set instead of o["a"] = 1 - o.Set("a", 1) - - // add some value with special characters - o.Set("b", "\\.<>[]{}_-") - - // use Get instead of i, ok := o["a"] - val, ok := o.Get("a") - - // use Keys instead of for k, v := range o - keys := o.Keys() - for _, k := range keys { - v, _ := o.Get(k) - } - - // use o.Delete instead of delete(o, key) - o.Delete("a") - - // serialize to a json string using encoding/json - bytes, err := json.Marshal(o) - prettyBytes, err := json.MarshalIndent(o, "", " ") - - // deserialize a json string using encoding/json - // all maps (including nested maps) will be parsed as orderedmaps - s := `{"a": 1}` - err := json.Unmarshal([]byte(s), &o) - - // sort the keys - o.SortKeys(sort.Strings) - - // sort by Pair - o.Sort(func(a *orderedmap.Pair, b *orderedmap.Pair) bool { - return a.Value().(float64) < b.Value().(float64) - }) -} -``` - -# Caveats - -* OrderedMap only takes strings for the key, as per [the JSON spec](http://json.org/). - -# Tests - -``` -go test -``` - -# Alternatives - -None of the alternatives offer JSON serialization. - -* [cevaris/ordered_map](https://github.com/cevaris/ordered_map) -* [mantyr/iterator](https://github.com/mantyr/iterator) diff --git a/vendor/modules.txt b/vendor/modules.txt index 7d77d84dd..c46999dd3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -109,9 +109,6 @@ github.com/gobwas/glob/util/strings # github.com/gookit/color v1.4.2 ## explicit; go 1.12 github.com/gookit/color -# github.com/iancoleman/orderedmap v0.3.0 -## explicit; go 1.16 -github.com/iancoleman/orderedmap # github.com/imdario/mergo v0.3.11 ## explicit; go 1.13 github.com/imdario/mergo