mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-23 12:18:51 +02:00
Add default lazygit config generation in Config.md from JSON schema (#3565)
- **PR Description** This uses the JSON schema generated in https://github.com/jesseduffield/lazygit/pull/3039 to generate and replace the default lazygit config in Config.md when running `go generate ./...` Relevant issue: https://github.com/jesseduffield/lazygit/issues/3441 The generated config contains all the entries that have default values set in `user_config.go`
This commit is contained in:
commit
b75c177c31
657
docs/Config.md
657
docs/Config.md
@ -29,268 +29,503 @@ to the top of your config file or via [Visual Studio Code settings.json config][
|
|||||||
|
|
||||||
## Default
|
## Default
|
||||||
|
|
||||||
|
<!-- START CONFIG YAML: AUTOMATICALLY GENERATED with `go generate ./..., DO NOT UPDATE MANUALLY -->
|
||||||
```yaml
|
```yaml
|
||||||
|
# Config relating to the Lazygit UI
|
||||||
gui:
|
gui:
|
||||||
# stuff relating to the UI
|
# The number of lines you scroll by when scrolling the main window
|
||||||
windowSize: 'normal' # one of 'normal' | 'half' | 'full' default is 'normal'
|
scrollHeight: 2
|
||||||
scrollHeight: 2 # how many lines you scroll by
|
|
||||||
scrollPastBottom: true # enable scrolling past the bottom
|
# If true, allow scrolling past the bottom of the content in the main window
|
||||||
scrollOffMargin: 2 # how many lines to keep before/after the cursor when it reaches the top/bottom of the view; see 'Scroll-off Margin' section below
|
scrollPastBottom: true
|
||||||
scrollOffBehavior: 'margin' # one of 'margin' | 'jump'; see 'Scroll-off Margin' section below
|
|
||||||
sidePanelWidth: 0.3333 # number from 0 to 1
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#scroll-off-margin
|
||||||
expandFocusedSidePanel: false
|
scrollOffMargin: 2
|
||||||
mainPanelSplitMode: 'flexible' # one of 'horizontal' | 'flexible' | 'vertical'
|
|
||||||
enlargedSideViewLocation: 'left' # one of 'left' | 'top'
|
# One of: 'margin' (default) | 'jump'
|
||||||
language: 'auto' # one of 'auto' | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
|
scrollOffBehavior: margin
|
||||||
timeFormat: '02 Jan 06' # https://pkg.go.dev/time#Time.Format
|
|
||||||
shortTimeFormat: '3:04PM'
|
# If true, capture mouse events.
|
||||||
|
# When mouse events are captured, it's a little harder to select text: e.g. requiring you to hold the option key when on macOS.
|
||||||
|
mouseEvents: true
|
||||||
|
|
||||||
|
# Fraction of the total screen width to use for the left side section. You may want to pick a small number (e.g. 0.2) if you're using a narrow screen, so that you can see more of the main section.
|
||||||
|
# Number from 0 to 1.0.
|
||||||
|
sidePanelWidth: 0.3333
|
||||||
|
|
||||||
|
# Sometimes the main window is split in two (e.g. when the selected file has both staged and unstaged changes). This setting controls how the two sections are split.
|
||||||
|
# Options are:
|
||||||
|
# - 'horizontal': split the window horizontally
|
||||||
|
# - 'vertical': split the window vertically
|
||||||
|
# - 'flexible': (default) split the window horizontally if the window is wide enough, otherwise split vertically
|
||||||
|
mainPanelSplitMode: flexible
|
||||||
|
|
||||||
|
# How the window is split when in half screen mode (i.e. after hitting '+' once).
|
||||||
|
# Possible values:
|
||||||
|
# - 'left': split the window horizontally (side panel on the left, main view on the right)
|
||||||
|
# - 'top': split the window vertically (side panel on top, main view below)
|
||||||
|
enlargedSideViewLocation: left
|
||||||
|
|
||||||
|
# One of 'auto' (default) | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
|
||||||
|
language: auto
|
||||||
|
|
||||||
|
# Format used when displaying time e.g. commit time.
|
||||||
|
# Uses Go's time format syntax: https://pkg.go.dev/time#Time.Format
|
||||||
|
timeFormat: 02 Jan 06
|
||||||
|
|
||||||
|
# Format used when displaying time if the time is less than 24 hours ago.
|
||||||
|
# Uses Go's time format syntax: https://pkg.go.dev/time#Time.Format
|
||||||
|
shortTimeFormat: 3:04PM
|
||||||
|
|
||||||
|
# Config relating to colors and styles.
|
||||||
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#color-attributes
|
||||||
theme:
|
theme:
|
||||||
|
# Border color of focused window
|
||||||
activeBorderColor:
|
activeBorderColor:
|
||||||
- green
|
- green
|
||||||
- bold
|
- bold
|
||||||
|
|
||||||
|
# Border color of non-focused windows
|
||||||
inactiveBorderColor:
|
inactiveBorderColor:
|
||||||
- white
|
- default
|
||||||
|
|
||||||
|
# Border color of focused window when searching in that window
|
||||||
searchingActiveBorderColor:
|
searchingActiveBorderColor:
|
||||||
- cyan
|
- cyan
|
||||||
- bold
|
- bold
|
||||||
|
|
||||||
|
# Color of keybindings help text in the bottom line
|
||||||
optionsTextColor:
|
optionsTextColor:
|
||||||
- blue
|
- blue
|
||||||
|
|
||||||
|
# Background color of selected line.
|
||||||
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- blue # set to `default` to have no background colour
|
- blue
|
||||||
cherryPickedCommitBgColor:
|
|
||||||
- cyan
|
# Foreground color of copied commit
|
||||||
cherryPickedCommitFgColor:
|
cherryPickedCommitFgColor:
|
||||||
- blue
|
- blue
|
||||||
|
|
||||||
|
# Background color of copied commit
|
||||||
|
cherryPickedCommitBgColor:
|
||||||
|
- cyan
|
||||||
|
|
||||||
|
# Foreground color of marked base commit (for rebase)
|
||||||
|
markedBaseCommitFgColor:
|
||||||
|
- blue
|
||||||
|
|
||||||
|
# Background color of marked base commit (for rebase)
|
||||||
|
markedBaseCommitBgColor:
|
||||||
|
- yellow
|
||||||
|
|
||||||
|
# Color for file with unstaged changes
|
||||||
unstagedChangesColor:
|
unstagedChangesColor:
|
||||||
- red
|
- red
|
||||||
|
|
||||||
|
# Default text color
|
||||||
defaultFgColor:
|
defaultFgColor:
|
||||||
- default
|
- default
|
||||||
|
|
||||||
|
# Config relating to the commit length indicator
|
||||||
commitLength:
|
commitLength:
|
||||||
|
# If true, show an indicator of commit message length
|
||||||
show: true
|
show: true
|
||||||
mouseEvents: true
|
|
||||||
skipDiscardChangeWarning: false
|
# If true, show the '5 of 20' footer at the bottom of list views
|
||||||
skipStashWarning: false
|
showListFooter: true
|
||||||
showFileTree: true # for rendering changes files in a tree format
|
|
||||||
showListFooter: true # for seeing the '5 of 20' message in list panels
|
# If true, display the files in the file views as a tree. If false, display the files as a flat list.
|
||||||
|
# This can be toggled from within Lazygit with the '~' key, but that will not change the default.
|
||||||
|
showFileTree: true
|
||||||
|
|
||||||
|
# If true, show a random tip in the command log when Lazygit starts
|
||||||
showRandomTip: true
|
showRandomTip: true
|
||||||
showBranchCommitHash: false # show commit hashes alongside branch names
|
|
||||||
showBottomLine: true # for hiding the bottom information line (unless it has important information to tell you)
|
# If true, show the command log
|
||||||
showPanelJumps: true # for showing the jump-to-panel keybindings as panel subtitles
|
|
||||||
showCommandLog: true
|
showCommandLog: true
|
||||||
showIcons: false # deprecated: use nerdFontsVersion instead
|
|
||||||
nerdFontsVersion: "" # nerd fonts version to use ("2" or "3"); empty means don't show nerd font icons
|
# If true, show the bottom line that contains keybinding info and useful buttons. If false, this line will be hidden except to display a loader for an in-progress action.
|
||||||
showFileIcons: true # for hiding file icons in the file views
|
showBottomLine: true
|
||||||
commitHashLength: 8 # length of commit hash in commits view. 0 shows '*' if NF icons aren't enabled
|
|
||||||
|
# If true, show jump-to-window keybindings in window titles.
|
||||||
|
showPanelJumps: true
|
||||||
|
|
||||||
|
# Nerd fonts version to use.
|
||||||
|
# One of: '2' | '3' | empty string (default)
|
||||||
|
# If empty, do not show icons.
|
||||||
|
nerdFontsVersion: ""
|
||||||
|
|
||||||
|
# If true (default), file icons are shown in the file views. Only relevant if NerdFontsVersion is not empty.
|
||||||
|
showFileIcons: true
|
||||||
|
|
||||||
|
# Length of commit hash in commits view. 0 shows '*' if NF icons aren't on.
|
||||||
|
commitHashLength: 8
|
||||||
|
|
||||||
|
# Height of the command log view
|
||||||
commandLogSize: 8
|
commandLogSize: 8
|
||||||
splitDiff: 'auto' # one of 'auto' | 'always'
|
|
||||||
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
|
# Whether to split the main window when viewing file changes.
|
||||||
border: 'rounded' # one of 'single' | 'double' | 'rounded' | 'hidden'
|
# One of: 'auto' | 'always'
|
||||||
animateExplosion: true # shows an explosion animation when nuking the working tree
|
# If 'auto', only split the main window when a file has both staged and unstaged changes
|
||||||
portraitMode: 'auto' # one of 'auto' | 'never' | 'always'
|
splitDiff: auto
|
||||||
filterMode: 'substring' # one of 'substring' | 'fuzzy'; see 'Filtering' section below
|
|
||||||
|
# Default size for focused window. Window size can be changed from within Lazygit with '+' and '_' (but this won't change the default).
|
||||||
|
# One of: 'normal' (default) | 'half' | 'full'
|
||||||
|
windowSize: normal
|
||||||
|
|
||||||
|
# Window border style.
|
||||||
|
# One of 'rounded' (default) | 'single' | 'double' | 'hidden'
|
||||||
|
border: rounded
|
||||||
|
|
||||||
|
# If true, show a seriously epic explosion animation when nuking the working tree.
|
||||||
|
animateExplosion: true
|
||||||
|
|
||||||
|
# Whether to stack UI components on top of each other.
|
||||||
|
# One of 'auto' (default) | 'always' | 'never'
|
||||||
|
portraitMode: auto
|
||||||
|
|
||||||
|
# How things are filtered when typing '/'.
|
||||||
|
# One of 'substring' (default) | 'fuzzy'
|
||||||
|
filterMode: substring
|
||||||
|
|
||||||
|
# Config relating to the spinner.
|
||||||
spinner:
|
spinner:
|
||||||
frames: ['|', '/', '-', '\\']
|
# The frames of the spinner animation.
|
||||||
rate: 50 # spinner rate in milliseconds
|
frames:
|
||||||
statusPanelView: 'dashboard' # one of 'dashboard' | 'allBranchesLog'
|
- '|'
|
||||||
|
- /
|
||||||
|
- '-'
|
||||||
|
- \
|
||||||
|
|
||||||
|
# The "speed" of the spinner in milliseconds.
|
||||||
|
rate: 50
|
||||||
|
|
||||||
|
# Status panel view.
|
||||||
|
# One of 'dashboard' (default) | 'allBranchesLog'
|
||||||
|
statusPanelView: dashboard
|
||||||
|
|
||||||
|
# Config relating to git
|
||||||
git:
|
git:
|
||||||
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
|
||||||
paging:
|
paging:
|
||||||
|
# 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'
|
||||||
colorArg: always
|
colorArg: always
|
||||||
useConfig: false
|
|
||||||
|
# e.g.
|
||||||
|
# diff-so-fancy
|
||||||
|
# delta --dark --paging=never
|
||||||
|
# ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||||
|
pager: ""
|
||||||
|
|
||||||
|
# e.g. 'difft --color=always'
|
||||||
|
externalDiffCommand: ""
|
||||||
|
|
||||||
|
# Config relating to committing
|
||||||
commit:
|
commit:
|
||||||
signOff: false
|
# Automatic WYSIWYG wrapping of the commit message as you type
|
||||||
autoWrapCommitMessage: true # automatic WYSIWYG wrapping of the commit message as you type
|
autoWrapCommitMessage: true
|
||||||
autoWrapWidth: 72 # if autoWrapCommitMessage is true, the width to wrap to
|
|
||||||
|
# If autoWrapCommitMessage is true, the width to wrap to
|
||||||
|
autoWrapWidth: 72
|
||||||
|
|
||||||
|
# Config relating to merging
|
||||||
merging:
|
merging:
|
||||||
# only applicable to unix users
|
# Extra args passed to `git merge`, e.g. --no-ff
|
||||||
manualCommit: false
|
args: ""
|
||||||
# extra args passed to `git merge`, e.g. --no-ff
|
|
||||||
args: ''
|
# list of branches that are considered 'main' branches, used when displaying commits
|
||||||
|
mainBranches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
|
||||||
|
# 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'
|
||||||
|
skipHookPrefix: WIP
|
||||||
|
|
||||||
|
# If true, periodically fetch from remote
|
||||||
|
autoFetch: true
|
||||||
|
|
||||||
|
# If true, periodically refresh files and submodules
|
||||||
|
autoRefresh: true
|
||||||
|
|
||||||
|
# If true, pass the --all arg to git fetch
|
||||||
|
fetchAll: true
|
||||||
|
|
||||||
|
# Command used when displaying the current branch git log in the main window
|
||||||
|
branchLogCmd: git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --
|
||||||
|
|
||||||
|
# Command used to display git log of all branches in the main window
|
||||||
|
allBranchesLogCmd: git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium
|
||||||
|
|
||||||
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix
|
||||||
|
commitPrefix:
|
||||||
|
# pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use "^\\w+\\/(\\w+-\\w+).*"
|
||||||
|
pattern: ""
|
||||||
|
|
||||||
|
# Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use "[$1] "
|
||||||
|
replace: ""
|
||||||
|
|
||||||
|
# Config for showing the log in the commits view
|
||||||
log:
|
log:
|
||||||
# one of date-order, author-date-order, topo-order or default.
|
# One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default'
|
||||||
# topo-order makes it easier to read the git log graph, but commits may not
|
# 'topo-order' makes it easier to read the git log graph, but commits may not
|
||||||
# appear chronologically. See https://git-scm.com/docs/git-log#_commit_ordering
|
# appear chronologically. See https://git-scm.com/docs/
|
||||||
#
|
#
|
||||||
# Deprecated: Configure this with `Log menu -> Commit sort order` (<c-l> in the commits window by default).
|
# Deprecated: Configure this with `Log menu -> Commit sort order` (<c-l> in the commits window by default).
|
||||||
order: 'topo-order'
|
order: topo-order
|
||||||
# one of always, never, when-maximised
|
|
||||||
# this determines whether the git graph is rendered in the commits panel
|
# This determines whether the git graph is rendered in the commits panel
|
||||||
|
# One of 'always' | 'never' | 'when-maximised'
|
||||||
#
|
#
|
||||||
# Deprecated: Configure this with `Log menu -> Show git graph` (<c-l> in the commits window by default).
|
# Deprecated: Configure this with `Log menu -> Show git graph` (<c-l> in the commits window by default).
|
||||||
showGraph: 'always'
|
showGraph: always
|
||||||
# displays the whole git graph by default in the commits panel (equivalent to passing the `--all` argument to `git log`)
|
|
||||||
showWholeGraph: false
|
# When copying commit hashes to the clipboard, truncate them to this
|
||||||
skipHookPrefix: WIP
|
# length. Set to 40 to disable truncation.
|
||||||
# The main branches. We colour commits green if they belong to one of these branches,
|
truncateCopiedCommitHashesTo: 12
|
||||||
# so that you can easily see which commits are unique to your branch (coloured in yellow)
|
|
||||||
mainBranches: [master, main]
|
# Periodic update checks
|
||||||
autoFetch: true
|
|
||||||
autoRefresh: true
|
|
||||||
fetchAll: true # Pass --all flag when running git fetch. Set to false to fetch only origin (or the current branch's upstream remote if there is one)
|
|
||||||
branchLogCmd: 'git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --'
|
|
||||||
allBranchesLogCmd: 'git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium'
|
|
||||||
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
|
|
||||||
disableForcePushing: false
|
|
||||||
parseEmoji: false
|
|
||||||
truncateCopiedCommitHashesTo: 12 # When copying commit hashes to the clipboard, truncate them to this length. Set to 40 to disable truncation.
|
|
||||||
os:
|
|
||||||
copyToClipboardCmd: '' # See 'Custom Command for Copying to Clipboard' section
|
|
||||||
editPreset: '' # see 'Configuring File Editing' section
|
|
||||||
edit: ''
|
|
||||||
editAtLine: ''
|
|
||||||
editAtLineAndWait: ''
|
|
||||||
open: ''
|
|
||||||
openLink: ''
|
|
||||||
refresher:
|
|
||||||
refreshInterval: 10 # File/submodule refresh interval in seconds. Auto-refresh can be disabled via option 'git.autoRefresh'.
|
|
||||||
fetchInterval: 60 # Re-fetch interval in seconds. Auto-fetch can be disabled via option 'git.autoFetch'.
|
|
||||||
update:
|
update:
|
||||||
method: prompt # can be: prompt | background | never
|
# One of: 'prompt' (default) | 'background' | 'never'
|
||||||
days: 14 # how often an update is checked for
|
method: prompt
|
||||||
confirmOnQuit: false
|
|
||||||
# determines whether hitting 'esc' will quit the application when there is nothing to cancel/close
|
# Period in days between update checks
|
||||||
quitOnTopLevelReturn: false
|
days: 14
|
||||||
disableStartupPopups: false
|
|
||||||
notARepository: 'prompt' # one of: 'prompt' | 'create' | 'skip' | 'quit'
|
# Background refreshes
|
||||||
promptToReturnFromSubprocess: true # display confirmation when subprocess terminates
|
refresher:
|
||||||
|
# File/submodule refresh interval in seconds.
|
||||||
|
# Auto-refresh can be disabled via option 'git.autoRefresh'.
|
||||||
|
refreshInterval: 10
|
||||||
|
|
||||||
|
# Re-fetch interval in seconds.
|
||||||
|
# Auto-fetch can be disabled via option 'git.autoFetch'.
|
||||||
|
fetchInterval: 60
|
||||||
|
|
||||||
|
# Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc
|
||||||
|
os:
|
||||||
|
# Command for editing a file. Should contain "{{filename}}".
|
||||||
|
edit: ""
|
||||||
|
|
||||||
|
# Command for editing a file at a given line number. Should contain
|
||||||
|
# "{{filename}}", and may optionally contain "{{line}}".
|
||||||
|
editAtLine: ""
|
||||||
|
|
||||||
|
# Same as EditAtLine, except that the command needs to wait until the
|
||||||
|
# window is closed.
|
||||||
|
editAtLineAndWait: ""
|
||||||
|
|
||||||
|
# For opening a directory in an editor
|
||||||
|
openDirInEditor: ""
|
||||||
|
|
||||||
|
# A built-in preset that sets all of the above settings. Supported presets
|
||||||
|
# are defined in the getPreset function in editor_presets.go.
|
||||||
|
editPreset: ""
|
||||||
|
|
||||||
|
# Command for opening a file, as if the file is double-clicked. Should
|
||||||
|
# contain "{{filename}}", but doesn't support "{{line}}".
|
||||||
|
open: ""
|
||||||
|
|
||||||
|
# Command for opening a link. Should contain "{{link}}".
|
||||||
|
openLink: ""
|
||||||
|
|
||||||
|
# EditCommand is the command for editing a file.
|
||||||
|
# Deprecated: use Edit instead. Note that semantics are different:
|
||||||
|
# EditCommand is just the command itself, whereas Edit contains a
|
||||||
|
# "{{filename}}" variable.
|
||||||
|
editCommand: ""
|
||||||
|
|
||||||
|
# EditCommandTemplate is the command template for editing a file
|
||||||
|
# Deprecated: use EditAtLine instead.
|
||||||
|
editCommandTemplate: ""
|
||||||
|
|
||||||
|
# OpenCommand is the command for opening a file
|
||||||
|
# Deprecated: use Open instead.
|
||||||
|
openCommand: ""
|
||||||
|
|
||||||
|
# OpenLinkCommand is the command for opening a link
|
||||||
|
# Deprecated: use OpenLink instead.
|
||||||
|
openLinkCommand: ""
|
||||||
|
|
||||||
|
# CopyToClipboardCmd is the command for copying to clipboard.
|
||||||
|
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-clipboard
|
||||||
|
copyToClipboardCmd: ""
|
||||||
|
|
||||||
|
# What to do when opening Lazygit outside of a git repo.
|
||||||
|
# - 'prompt': (default) ask whether to initialize a new repo or open in the most recent repo
|
||||||
|
# - 'create': initialize a new repo
|
||||||
|
# - 'skip': open most recent repo
|
||||||
|
# - 'quit': exit Lazygit
|
||||||
|
notARepository: prompt
|
||||||
|
|
||||||
|
# If true, display a confirmation when subprocess terminates. This allows you to view the output of the subprocess before returning to Lazygit.
|
||||||
|
promptToReturnFromSubprocess: true
|
||||||
|
|
||||||
|
# Keybindings
|
||||||
keybinding:
|
keybinding:
|
||||||
universal:
|
universal:
|
||||||
quit: 'q'
|
quit: q
|
||||||
quit-alt1: '<c-c>' # alternative/alias of quit
|
quit-alt1: <c-c>
|
||||||
return: '<esc>' # return to previous menu, will quit if there's nowhere to return
|
return: <esc>
|
||||||
quitWithoutChangingDirectory: 'Q'
|
quitWithoutChangingDirectory: Q
|
||||||
togglePanel: '<tab>' # goto the next panel
|
togglePanel: <tab>
|
||||||
prevItem: '<up>' # go one line up
|
prevItem: <up>
|
||||||
nextItem: '<down>' # go one line down
|
nextItem: <down>
|
||||||
prevItem-alt: 'k' # go one line up
|
prevItem-alt: k
|
||||||
nextItem-alt: 'j' # go one line down
|
nextItem-alt: j
|
||||||
prevPage: ',' # go to next page in list
|
prevPage: ','
|
||||||
nextPage: '.' # go to previous page in list
|
nextPage: .
|
||||||
gotoTop: '<' # go to top of list
|
scrollLeft: H
|
||||||
gotoBottom: '>' # go to bottom of list
|
scrollRight: L
|
||||||
scrollLeft: 'H' # scroll left within list view
|
gotoTop: <
|
||||||
scrollRight: 'L' # scroll right within list view
|
gotoBottom: '>'
|
||||||
prevBlock: '<left>' # goto the previous block / panel
|
toggleRangeSelect: v
|
||||||
nextBlock: '<right>' # goto the next block / panel
|
rangeSelectDown: <s-down>
|
||||||
prevBlock-alt: 'h' # goto the previous block / panel
|
rangeSelectUp: <s-up>
|
||||||
nextBlock-alt: 'l' # goto the next block / panel
|
prevBlock: <left>
|
||||||
jumpToBlock: ['1', '2', '3', '4', '5'] # goto the Nth block / panel
|
nextBlock: <right>
|
||||||
nextMatch: 'n'
|
prevBlock-alt: h
|
||||||
prevMatch: 'N'
|
nextBlock-alt: l
|
||||||
optionMenu: <disabled> # show help menu
|
nextBlock-alt2: <tab>
|
||||||
optionMenu-alt1: '?' # show help menu
|
prevBlock-alt2: <backtab>
|
||||||
select: '<space>'
|
jumpToBlock:
|
||||||
goInto: '<enter>'
|
- "1"
|
||||||
openRecentRepos: '<c-r>'
|
- "2"
|
||||||
confirm: '<enter>'
|
- "3"
|
||||||
remove: 'd'
|
- "4"
|
||||||
new: 'n'
|
- "5"
|
||||||
edit: 'e'
|
nextMatch: "n"
|
||||||
openFile: 'o'
|
prevMatch: "N"
|
||||||
scrollUpMain: '<pgup>' # main panel scroll up
|
startSearch: /
|
||||||
scrollDownMain: '<pgdown>' # main panel scroll down
|
optionMenu: <disabled>
|
||||||
scrollUpMain-alt1: 'K' # main panel scroll up
|
optionMenu-alt1: '?'
|
||||||
scrollDownMain-alt1: 'J' # main panel scroll down
|
select: <space>
|
||||||
scrollUpMain-alt2: '<c-u>' # main panel scroll up
|
goInto: <enter>
|
||||||
scrollDownMain-alt2: '<c-d>' # main panel scroll down
|
confirm: <enter>
|
||||||
|
confirmInEditor: <a-enter>
|
||||||
|
remove: d
|
||||||
|
new: "n"
|
||||||
|
edit: e
|
||||||
|
openFile: o
|
||||||
|
scrollUpMain: <pgup>
|
||||||
|
scrollDownMain: <pgdown>
|
||||||
|
scrollUpMain-alt1: K
|
||||||
|
scrollDownMain-alt1: J
|
||||||
|
scrollUpMain-alt2: <c-u>
|
||||||
|
scrollDownMain-alt2: <c-d>
|
||||||
executeCustomCommand: ':'
|
executeCustomCommand: ':'
|
||||||
createRebaseOptionsMenu: 'm'
|
createRebaseOptionsMenu: m
|
||||||
pushFiles: 'P'
|
|
||||||
pullFiles: 'p'
|
# 'Files' appended for legacy reasons
|
||||||
refresh: 'R'
|
pushFiles: P
|
||||||
createPatchOptionsMenu: '<c-p>'
|
|
||||||
|
# 'Files' appended for legacy reasons
|
||||||
|
pullFiles: p
|
||||||
|
refresh: R
|
||||||
|
createPatchOptionsMenu: <c-p>
|
||||||
nextTab: ']'
|
nextTab: ']'
|
||||||
prevTab: '['
|
prevTab: '['
|
||||||
nextScreenMode: '+'
|
nextScreenMode: +
|
||||||
prevScreenMode: '_'
|
prevScreenMode: _
|
||||||
undo: 'z'
|
undo: z
|
||||||
redo: '<c-z>'
|
redo: <c-z>
|
||||||
filteringMenu: '<c-s>'
|
filteringMenu: <c-s>
|
||||||
diffingMenu: 'W'
|
diffingMenu: W
|
||||||
diffingMenu-alt: '<c-e>' # deprecated
|
diffingMenu-alt: <c-e>
|
||||||
copyToClipboard: '<c-o>'
|
copyToClipboard: <c-o>
|
||||||
submitEditorText: '<enter>'
|
openRecentRepos: <c-r>
|
||||||
|
submitEditorText: <enter>
|
||||||
extrasMenu: '@'
|
extrasMenu: '@'
|
||||||
toggleWhitespaceInDiffView: '<c-w>'
|
toggleWhitespaceInDiffView: <c-w>
|
||||||
increaseContextInDiffView: '}'
|
increaseContextInDiffView: '}'
|
||||||
decreaseContextInDiffView: '{'
|
decreaseContextInDiffView: '{'
|
||||||
toggleRangeSelect: 'v'
|
openDiffTool: <c-t>
|
||||||
rangeSelectUp: '<s-up>'
|
|
||||||
rangeSelectDown: '<s-down>'
|
|
||||||
status:
|
status:
|
||||||
checkForUpdate: 'u'
|
checkForUpdate: u
|
||||||
recentRepos: '<enter>'
|
recentRepos: <enter>
|
||||||
|
allBranchesLogGraph: a
|
||||||
files:
|
files:
|
||||||
commitChanges: 'c'
|
commitChanges: c
|
||||||
commitChangesWithoutHook: 'w' # commit changes without pre-commit hook
|
commitChangesWithoutHook: w
|
||||||
amendLastCommit: 'A'
|
amendLastCommit: A
|
||||||
commitChangesWithEditor: 'C'
|
commitChangesWithEditor: C
|
||||||
findBaseCommitForFixup: '<c-f>'
|
findBaseCommitForFixup: <c-f>
|
||||||
confirmDiscard: 'x'
|
confirmDiscard: x
|
||||||
ignoreFile: 'i'
|
ignoreFile: i
|
||||||
refreshFiles: 'r'
|
refreshFiles: r
|
||||||
stashAllChanges: 's'
|
stashAllChanges: s
|
||||||
viewStashOptions: 'S'
|
viewStashOptions: S
|
||||||
toggleStagedAll: 'a' # stage/unstage all
|
toggleStagedAll: a
|
||||||
viewResetOptions: 'D'
|
viewResetOptions: D
|
||||||
fetch: 'f'
|
fetch: f
|
||||||
toggleTreeView: '`'
|
toggleTreeView: '`'
|
||||||
openMergeTool: 'M'
|
openMergeTool: M
|
||||||
openStatusFilter: '<c-b>'
|
openStatusFilter: <c-b>
|
||||||
|
copyFileInfoToClipboard: "y"
|
||||||
branches:
|
branches:
|
||||||
createPullRequest: 'o'
|
createPullRequest: o
|
||||||
viewPullRequestOptions: 'O'
|
viewPullRequestOptions: O
|
||||||
checkoutBranchByName: 'c'
|
copyPullRequestURL: <c-y>
|
||||||
forceCheckoutBranch: 'F'
|
checkoutBranchByName: c
|
||||||
rebaseBranch: 'r'
|
forceCheckoutBranch: F
|
||||||
renameBranch: 'R'
|
rebaseBranch: r
|
||||||
mergeIntoCurrentBranch: 'M'
|
renameBranch: R
|
||||||
viewGitFlowOptions: 'i'
|
mergeIntoCurrentBranch: M
|
||||||
fastForward: 'f' # fast-forward this branch from its upstream
|
viewGitFlowOptions: i
|
||||||
createTag: 'T'
|
fastForward: f
|
||||||
pushTag: 'P'
|
createTag: T
|
||||||
setUpstream: 'u' # set as upstream of checked-out branch
|
pushTag: P
|
||||||
fetchRemote: 'f'
|
setUpstream: u
|
||||||
|
fetchRemote: f
|
||||||
|
sortOrder: s
|
||||||
|
worktrees:
|
||||||
|
viewWorktreeOptions: w
|
||||||
commits:
|
commits:
|
||||||
squashDown: 's'
|
squashDown: s
|
||||||
renameCommit: 'r'
|
renameCommit: r
|
||||||
renameCommitWithEditor: 'R'
|
renameCommitWithEditor: R
|
||||||
viewResetOptions: 'g'
|
viewResetOptions: g
|
||||||
markCommitAsFixup: 'f'
|
markCommitAsFixup: f
|
||||||
createFixupCommit: 'F' # create fixup commit for this commit
|
createFixupCommit: F
|
||||||
squashAboveCommits: 'S'
|
squashAboveCommits: S
|
||||||
moveDownCommit: '<c-j>' # move commit down one
|
moveDownCommit: <c-j>
|
||||||
moveUpCommit: '<c-k>' # move commit up one
|
moveUpCommit: <c-k>
|
||||||
amendToCommit: 'A'
|
amendToCommit: A
|
||||||
amendAttributeMenu: 'a'
|
resetCommitAuthor: a
|
||||||
pickCommit: 'p' # pick commit (when mid-rebase)
|
pickCommit: p
|
||||||
revertCommit: 't'
|
revertCommit: t
|
||||||
cherryPickCopy: 'C'
|
cherryPickCopy: C
|
||||||
pasteCommits: 'V'
|
pasteCommits: V
|
||||||
tagCommit: 'T'
|
markCommitAsBaseForRebase: B
|
||||||
checkoutCommit: '<space>'
|
tagCommit: T
|
||||||
resetCherryPick: '<c-R>'
|
checkoutCommit: <space>
|
||||||
copyCommitMessageToClipboard: '<c-y>'
|
resetCherryPick: <c-R>
|
||||||
openLogMenu: '<c-l>'
|
copyCommitAttributeToClipboard: "y"
|
||||||
viewBisectOptions: 'b'
|
openLogMenu: <c-l>
|
||||||
stash:
|
openInBrowser: o
|
||||||
popStash: 'g'
|
viewBisectOptions: b
|
||||||
renameStash: 'r'
|
startInteractiveRebase: i
|
||||||
commitFiles:
|
|
||||||
checkoutCommitFile: 'c'
|
|
||||||
main:
|
|
||||||
toggleSelectHunk: 'a'
|
|
||||||
pickBothHunks: 'b'
|
|
||||||
submodules:
|
|
||||||
init: 'i'
|
|
||||||
update: 'u'
|
|
||||||
bulkMenu: 'b'
|
|
||||||
commitMessage:
|
|
||||||
commitMenu: '<c-o>'
|
|
||||||
amendAttribute:
|
amendAttribute:
|
||||||
addCoAuthor: 'c'
|
resetAuthor: a
|
||||||
resetAuthor: 'a'
|
setAuthor: A
|
||||||
setAuthor: 'A'
|
addCoAuthor: c
|
||||||
|
stash:
|
||||||
|
popStash: g
|
||||||
|
renameStash: r
|
||||||
|
commitFiles:
|
||||||
|
checkoutCommitFile: c
|
||||||
|
main:
|
||||||
|
toggleSelectHunk: a
|
||||||
|
pickBothHunks: b
|
||||||
|
editSelectHunk: E
|
||||||
|
submodules:
|
||||||
|
init: i
|
||||||
|
update: u
|
||||||
|
bulkMenu: b
|
||||||
|
commitMessage:
|
||||||
|
commitMenu: <c-o>
|
||||||
```
|
```
|
||||||
|
<!-- END CONFIG YAML -->
|
||||||
|
|
||||||
## Platform Defaults
|
## Platform Defaults
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -11,6 +11,7 @@ require (
|
|||||||
github.com/gdamore/tcell/v2 v2.7.4
|
github.com/gdamore/tcell/v2 v2.7.4
|
||||||
github.com/go-errors/errors v1.5.1
|
github.com/go-errors/errors v1.5.1
|
||||||
github.com/gookit/color v1.4.2
|
github.com/gookit/color v1.4.2
|
||||||
|
github.com/iancoleman/orderedmap v0.3.0
|
||||||
github.com/imdario/mergo v0.3.11
|
github.com/imdario/mergo v0.3.11
|
||||||
github.com/integrii/flaggy v1.4.0
|
github.com/integrii/flaggy v1.4.0
|
||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||||
|
2
go.sum
2
go.sum
@ -171,6 +171,8 @@ 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/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 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
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-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/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=
|
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
@ -19,8 +19,6 @@ type UserConfig struct {
|
|||||||
ConfirmOnQuit bool `yaml:"confirmOnQuit"`
|
ConfirmOnQuit bool `yaml:"confirmOnQuit"`
|
||||||
// If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close
|
// If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close
|
||||||
QuitOnTopLevelReturn bool `yaml:"quitOnTopLevelReturn"`
|
QuitOnTopLevelReturn bool `yaml:"quitOnTopLevelReturn"`
|
||||||
// Keybindings
|
|
||||||
Keybinding KeybindingConfig `yaml:"keybinding"`
|
|
||||||
// Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc
|
// Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc
|
||||||
OS OSConfig `yaml:"os,omitempty"`
|
OS OSConfig `yaml:"os,omitempty"`
|
||||||
// If true, don't display introductory popups upon opening Lazygit.
|
// If true, don't display introductory popups upon opening Lazygit.
|
||||||
@ -38,6 +36,8 @@ type UserConfig struct {
|
|||||||
NotARepository string `yaml:"notARepository" jsonschema:"enum=prompt,enum=create,enum=skip,enum=quit"`
|
NotARepository string `yaml:"notARepository" jsonschema:"enum=prompt,enum=create,enum=skip,enum=quit"`
|
||||||
// If true, display a confirmation when subprocess terminates. This allows you to view the output of the subprocess before returning to Lazygit.
|
// If true, display a confirmation when subprocess terminates. This allows you to view the output of the subprocess before returning to Lazygit.
|
||||||
PromptToReturnFromSubprocess bool `yaml:"promptToReturnFromSubprocess"`
|
PromptToReturnFromSubprocess bool `yaml:"promptToReturnFromSubprocess"`
|
||||||
|
// Keybindings
|
||||||
|
Keybinding KeybindingConfig `yaml:"keybinding"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RefresherConfig struct {
|
type RefresherConfig struct {
|
||||||
@ -252,7 +252,7 @@ type PagingConfig struct {
|
|||||||
// diff-so-fancy
|
// diff-so-fancy
|
||||||
// delta --dark --paging=never
|
// delta --dark --paging=never
|
||||||
// ydiff -p cat -s --wrap --width={{columnWidth}}
|
// ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||||
Pager PagerType `yaml:"pager" jsonschema:"minLength=1"`
|
Pager PagerType `yaml:"pager"`
|
||||||
// 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).
|
// 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).
|
||||||
UseConfig bool `yaml:"useConfig"`
|
UseConfig bool `yaml:"useConfig"`
|
||||||
// e.g. 'difft --color=always'
|
// e.g. 'difft --color=always'
|
||||||
@ -294,9 +294,9 @@ type LogConfig struct {
|
|||||||
|
|
||||||
type CommitPrefixConfig struct {
|
type CommitPrefixConfig struct {
|
||||||
// pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use "^\\w+\\/(\\w+-\\w+).*"
|
// pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use "^\\w+\\/(\\w+-\\w+).*"
|
||||||
Pattern string `yaml:"pattern" jsonschema:"example=^\\w+\\/(\\w+-\\w+).*,minLength=1"`
|
Pattern string `yaml:"pattern" jsonschema:"example=^\\w+\\/(\\w+-\\w+).*"`
|
||||||
// Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use "[$1] "
|
// Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use "[$1] "
|
||||||
Replace string `yaml:"replace" jsonschema:"example=[$1] ,minLength=1"`
|
Replace string `yaml:"replace" jsonschema:"example=[$1]"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateConfig struct {
|
type UpdateConfig struct {
|
||||||
@ -684,6 +684,7 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
CommandLogSize: 8,
|
CommandLogSize: 8,
|
||||||
SplitDiff: "auto",
|
SplitDiff: "auto",
|
||||||
SkipRewordInEditorWarning: false,
|
SkipRewordInEditorWarning: false,
|
||||||
|
WindowSize: "normal",
|
||||||
Border: "rounded",
|
Border: "rounded",
|
||||||
AnimateExplosion: true,
|
AnimateExplosion: true,
|
||||||
PortraitMode: "auto",
|
PortraitMode: "auto",
|
||||||
@ -735,8 +736,14 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
Method: "prompt",
|
Method: "prompt",
|
||||||
Days: 14,
|
Days: 14,
|
||||||
},
|
},
|
||||||
ConfirmOnQuit: false,
|
ConfirmOnQuit: false,
|
||||||
QuitOnTopLevelReturn: false,
|
QuitOnTopLevelReturn: false,
|
||||||
|
OS: OSConfig{},
|
||||||
|
DisableStartupPopups: false,
|
||||||
|
CustomCommands: []CustomCommand(nil),
|
||||||
|
Services: map[string]string(nil),
|
||||||
|
NotARepository: "prompt",
|
||||||
|
PromptToReturnFromSubprocess: true,
|
||||||
Keybinding: KeybindingConfig{
|
Keybinding: KeybindingConfig{
|
||||||
Universal: KeybindingUniversalConfig{
|
Universal: KeybindingUniversalConfig{
|
||||||
Quit: "q",
|
Quit: "q",
|
||||||
@ -903,11 +910,5 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
CommitMenu: "<c-o>",
|
CommitMenu: "<c-o>",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OS: OSConfig{},
|
|
||||||
DisableStartupPopups: false,
|
|
||||||
CustomCommands: []CustomCommand(nil),
|
|
||||||
Services: map[string]string(nil),
|
|
||||||
NotARepository: "prompt",
|
|
||||||
PromptToReturnFromSubprocess: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
269
pkg/jsonschema/generate_config_docs.go
Normal file
269
pkg/jsonschema/generate_config_docs.go
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
package jsonschema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/iancoleman/orderedmap"
|
||||||
|
"github.com/jesseduffield/lazycore/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Default any
|
||||||
|
Children []*Node
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IndentLevel = 2
|
||||||
|
DocumentationCommentStart = "<!-- START CONFIG YAML: AUTOMATICALLY GENERATED with `go generate ./..., DO NOT UPDATE MANUALLY -->\n"
|
||||||
|
DocumentationCommentEnd = "<!-- END CONFIG YAML -->"
|
||||||
|
DocumentationCommentStartLen = len(DocumentationCommentStart)
|
||||||
|
)
|
||||||
|
|
||||||
|
func insertBlankLines(buffer bytes.Buffer) bytes.Buffer {
|
||||||
|
lines := strings.Split(strings.TrimRight(buffer.String(), "\n"), "\n")
|
||||||
|
|
||||||
|
var newBuffer bytes.Buffer
|
||||||
|
|
||||||
|
previousIndent := -1
|
||||||
|
wasComment := false
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
trimmedLine := strings.TrimLeft(line, " ")
|
||||||
|
indent := len(line) - len(trimmedLine)
|
||||||
|
isComment := strings.HasPrefix(trimmedLine, "#")
|
||||||
|
if isComment && !wasComment && indent <= previousIndent {
|
||||||
|
newBuffer.WriteString("\n")
|
||||||
|
}
|
||||||
|
newBuffer.WriteString(line)
|
||||||
|
newBuffer.WriteString("\n")
|
||||||
|
previousIndent = indent
|
||||||
|
wasComment = isComment
|
||||||
|
}
|
||||||
|
|
||||||
|
return newBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareMarshalledConfig(buffer bytes.Buffer) []byte {
|
||||||
|
buffer = insertBlankLines(buffer)
|
||||||
|
|
||||||
|
// Remove all `---` lines
|
||||||
|
lines := strings.Split(strings.TrimRight(buffer.String(), "\n"), "\n")
|
||||||
|
|
||||||
|
var newBuffer bytes.Buffer
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.TrimSpace(line) != "---" {
|
||||||
|
newBuffer.WriteString(line)
|
||||||
|
newBuffer.WriteString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config := newBuffer.Bytes()
|
||||||
|
|
||||||
|
// Add markdown yaml block tag
|
||||||
|
config = append([]byte("```yaml\n"), config...)
|
||||||
|
config = append(config, []byte("```\n")...)
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func setComment(yamlNode *yaml.Node, description string) {
|
||||||
|
// Workaround for the way yaml formats the HeadComment if it contains
|
||||||
|
// blank lines: it renders these without a leading "#", but we want a
|
||||||
|
// leading "#" even on blank lines. However, yaml respects it if the
|
||||||
|
// HeadComment already contains a leading "#", so we prefix all lines
|
||||||
|
// (including blank ones) with "#".
|
||||||
|
yamlNode.HeadComment = strings.Join(
|
||||||
|
lo.Map(strings.Split(description, "\n"), func(s string, _ int) string {
|
||||||
|
if s == "" {
|
||||||
|
return "#" // avoid trailing space on blank lines
|
||||||
|
}
|
||||||
|
return "# " + s
|
||||||
|
}),
|
||||||
|
"\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) MarshalYAML() (interface{}, error) {
|
||||||
|
node := yaml.Node{
|
||||||
|
Kind: yaml.MappingNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
keyNode := yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: n.Name,
|
||||||
|
}
|
||||||
|
if n.Description != "" {
|
||||||
|
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 {
|
||||||
|
childrenNode := yaml.Node{
|
||||||
|
Kind: yaml.MappingNode,
|
||||||
|
}
|
||||||
|
for _, child := range n.Children {
|
||||||
|
childYaml, err := child.MarshalYAML()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
childKey := yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: child.Name,
|
||||||
|
}
|
||||||
|
if child.Description != "" {
|
||||||
|
setComment(&childKey, child.Description)
|
||||||
|
}
|
||||||
|
childYaml = childYaml.(*yaml.Node)
|
||||||
|
childrenNode.Content = append(childrenNode.Content, childYaml.(*yaml.Node).Content...)
|
||||||
|
}
|
||||||
|
node.Content = append(node.Content, &keyNode, &childrenNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading Config.md file %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
startConfigSectionIndex := bytes.Index(markdown, []byte(DocumentationCommentStart))
|
||||||
|
if startConfigSectionIndex == -1 {
|
||||||
|
return errors.New("Default config starting comment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
endConfigSectionIndex := bytes.Index(markdown[startConfigSectionIndex+DocumentationCommentStartLen:], []byte(DocumentationCommentEnd))
|
||||||
|
if endConfigSectionIndex == -1 {
|
||||||
|
return errors.New("Default config closing comment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
endConfigSectionIndex = endConfigSectionIndex + startConfigSectionIndex + DocumentationCommentStartLen
|
||||||
|
|
||||||
|
newMarkdown := make([]byte, 0, len(markdown)-endConfigSectionIndex+startConfigSectionIndex+len(config))
|
||||||
|
newMarkdown = append(newMarkdown, markdown[:startConfigSectionIndex+DocumentationCommentStartLen]...)
|
||||||
|
newMarkdown = append(newMarkdown, config...)
|
||||||
|
newMarkdown = append(newMarkdown, markdown[endConfigSectionIndex:]...)
|
||||||
|
|
||||||
|
if err := os.WriteFile(configPath, newMarkdown, 0o644); err != nil {
|
||||||
|
return fmt.Errorf("Error writing to file %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateConfigDocs() {
|
||||||
|
content, err := os.ReadFile(GetSchemaDir() + "/config.json")
|
||||||
|
if err != nil {
|
||||||
|
panic("Error reading config.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
encoder := yaml.NewEncoder(&buffer)
|
||||||
|
encoder.SetIndent(IndentLevel)
|
||||||
|
|
||||||
|
for _, child := range rootNode.Children {
|
||||||
|
err := encoder.Encode(child)
|
||||||
|
if err != nil {
|
||||||
|
panic("Failed to Marshal document")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encoder.Close()
|
||||||
|
|
||||||
|
config := prepareMarshalledConfig(buffer)
|
||||||
|
|
||||||
|
err = writeToConfigDocs(config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
@ -11,4 +11,5 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Generating jsonschema in %s...\n", jsonschema.GetSchemaDir())
|
fmt.Printf("Generating jsonschema in %s...\n", jsonschema.GetSchemaDir())
|
||||||
jsonschema.GenerateSchema()
|
jsonschema.GenerateSchema()
|
||||||
|
jsonschema.GenerateConfigDocs()
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,8 @@
|
|||||||
"half",
|
"half",
|
||||||
"full"
|
"full"
|
||||||
],
|
],
|
||||||
"description": "Default size for focused window. Window size can be changed from within Lazygit with '+' and '_' (but this won't change the default).\nOne of: 'normal' (default) | 'half' | 'full'"
|
"description": "Default size for focused window. Window size can be changed from within Lazygit with '+' and '_' (but this won't change the default).\nOne of: 'normal' (default) | 'half' | 'full'",
|
||||||
|
"default": "normal"
|
||||||
},
|
},
|
||||||
"border": {
|
"border": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -428,7 +429,6 @@
|
|||||||
},
|
},
|
||||||
"pager": {
|
"pager": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
|
||||||
"description": "e.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat -s --wrap --width={{columnWidth}}",
|
"description": "e.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat -s --wrap --width={{columnWidth}}",
|
||||||
"default": "",
|
"default": "",
|
||||||
"examples": [
|
"examples": [
|
||||||
@ -543,7 +543,6 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"pattern": {
|
"pattern": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
|
||||||
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
|
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
|
||||||
"examples": [
|
"examples": [
|
||||||
"^\\w+\\/(\\w+-\\w+).*"
|
"^\\w+\\/(\\w+-\\w+).*"
|
||||||
@ -551,10 +550,9 @@
|
|||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
|
||||||
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
|
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
|
||||||
"examples": [
|
"examples": [
|
||||||
"[$1] "
|
"[$1]"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -567,7 +565,6 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"pattern": {
|
"pattern": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
|
||||||
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
|
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
|
||||||
"examples": [
|
"examples": [
|
||||||
"^\\w+\\/(\\w+-\\w+).*"
|
"^\\w+\\/(\\w+-\\w+).*"
|
||||||
@ -575,10 +572,9 @@
|
|||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
|
||||||
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
|
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
|
||||||
"examples": [
|
"examples": [
|
||||||
"[$1] "
|
"[$1]"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -684,6 +680,291 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close"
|
"description": "If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close"
|
||||||
},
|
},
|
||||||
|
"os": {
|
||||||
|
"properties": {
|
||||||
|
"edit": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command for editing a file. Should contain \"{{filename}}\"."
|
||||||
|
},
|
||||||
|
"editAtLine": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command for editing a file at a given line number. Should contain\n\"{{filename}}\", and may optionally contain \"{{line}}\"."
|
||||||
|
},
|
||||||
|
"editAtLineAndWait": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Same as EditAtLine, except that the command needs to wait until the\nwindow is closed."
|
||||||
|
},
|
||||||
|
"editInTerminal": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether lazygit suspends until an edit process returns\nPointer to bool so that we can distinguish unset (nil) from false.\nWe're naming this `editInTerminal` for backwards compatibility"
|
||||||
|
},
|
||||||
|
"openDirInEditor": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "For opening a directory in an editor"
|
||||||
|
},
|
||||||
|
"editPreset": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A built-in preset that sets all of the above settings. Supported presets\nare defined in the getPreset function in editor_presets.go.",
|
||||||
|
"examples": [
|
||||||
|
"vim",
|
||||||
|
"nvim",
|
||||||
|
"emacs",
|
||||||
|
"nano",
|
||||||
|
"vscode",
|
||||||
|
"sublime",
|
||||||
|
"kakoune",
|
||||||
|
"helix",
|
||||||
|
"xcode"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"open": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command for opening a file, as if the file is double-clicked. Should\ncontain \"{{filename}}\", but doesn't support \"{{line}}\"."
|
||||||
|
},
|
||||||
|
"openLink": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Command for opening a link. Should contain \"{{link}}\"."
|
||||||
|
},
|
||||||
|
"editCommand": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "EditCommand is the command for editing a file.\nDeprecated: use Edit instead. Note that semantics are different:\nEditCommand is just the command itself, whereas Edit contains a\n\"{{filename}}\" variable."
|
||||||
|
},
|
||||||
|
"editCommandTemplate": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "EditCommandTemplate is the command template for editing a file\nDeprecated: use EditAtLine instead."
|
||||||
|
},
|
||||||
|
"openCommand": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "OpenCommand is the command for opening a file\nDeprecated: use Open instead."
|
||||||
|
},
|
||||||
|
"openLinkCommand": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "OpenLinkCommand is the command for opening a link\nDeprecated: use OpenLink instead."
|
||||||
|
},
|
||||||
|
"copyToClipboardCmd": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "CopyToClipboardCmd is the command for copying to clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-clipboard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"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.\nLazygit sets this to true upon first runninng the program so that you don't see introductory popups every time you open the program."
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"enum": [
|
||||||
|
"status",
|
||||||
|
"files",
|
||||||
|
"worktrees",
|
||||||
|
"localBranches",
|
||||||
|
"remotes",
|
||||||
|
"remoteBranches",
|
||||||
|
"tags",
|
||||||
|
"commits",
|
||||||
|
"reflogCommits",
|
||||||
|
"subCommits",
|
||||||
|
"commitFiles",
|
||||||
|
"stash",
|
||||||
|
"global"
|
||||||
|
],
|
||||||
|
"description": "The context in which to listen for the key"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"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": {
|
"keybinding": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"universal": {
|
"universal": {
|
||||||
@ -1333,291 +1614,6 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Keybindings"
|
"description": "Keybindings"
|
||||||
},
|
|
||||||
"os": {
|
|
||||||
"properties": {
|
|
||||||
"edit": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command for editing a file. Should contain \"{{filename}}\"."
|
|
||||||
},
|
|
||||||
"editAtLine": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command for editing a file at a given line number. Should contain\n\"{{filename}}\", and may optionally contain \"{{line}}\"."
|
|
||||||
},
|
|
||||||
"editAtLineAndWait": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Same as EditAtLine, except that the command needs to wait until the\nwindow is closed."
|
|
||||||
},
|
|
||||||
"editInTerminal": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether lazygit suspends until an edit process returns\nPointer to bool so that we can distinguish unset (nil) from false.\nWe're naming this `editInTerminal` for backwards compatibility"
|
|
||||||
},
|
|
||||||
"openDirInEditor": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "For opening a directory in an editor"
|
|
||||||
},
|
|
||||||
"editPreset": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A built-in preset that sets all of the above settings. Supported presets\nare defined in the getPreset function in editor_presets.go.",
|
|
||||||
"examples": [
|
|
||||||
"vim",
|
|
||||||
"nvim",
|
|
||||||
"emacs",
|
|
||||||
"nano",
|
|
||||||
"vscode",
|
|
||||||
"sublime",
|
|
||||||
"kakoune",
|
|
||||||
"helix",
|
|
||||||
"xcode"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"open": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command for opening a file, as if the file is double-clicked. Should\ncontain \"{{filename}}\", but doesn't support \"{{line}}\"."
|
|
||||||
},
|
|
||||||
"openLink": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command for opening a link. Should contain \"{{link}}\"."
|
|
||||||
},
|
|
||||||
"editCommand": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "EditCommand is the command for editing a file.\nDeprecated: use Edit instead. Note that semantics are different:\nEditCommand is just the command itself, whereas Edit contains a\n\"{{filename}}\" variable."
|
|
||||||
},
|
|
||||||
"editCommandTemplate": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "EditCommandTemplate is the command template for editing a file\nDeprecated: use EditAtLine instead."
|
|
||||||
},
|
|
||||||
"openCommand": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "OpenCommand is the command for opening a file\nDeprecated: use Open instead."
|
|
||||||
},
|
|
||||||
"openLinkCommand": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "OpenLinkCommand is the command for opening a link\nDeprecated: use OpenLink instead."
|
|
||||||
},
|
|
||||||
"copyToClipboardCmd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "CopyToClipboardCmd is the command for copying to clipboard.\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-clipboard"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"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.\nLazygit sets this to true upon first runninng the program so that you don't see introductory popups every time you open the program."
|
|
||||||
},
|
|
||||||
"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",
|
|
||||||
"enum": [
|
|
||||||
"status",
|
|
||||||
"files",
|
|
||||||
"worktrees",
|
|
||||||
"localBranches",
|
|
||||||
"remotes",
|
|
||||||
"remoteBranches",
|
|
||||||
"tags",
|
|
||||||
"commits",
|
|
||||||
"reflogCommits",
|
|
||||||
"subCommits",
|
|
||||||
"commitFiles",
|
|
||||||
"stash",
|
|
||||||
"global"
|
|
||||||
],
|
|
||||||
"description": "The context in which to listen for the key"
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"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
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
21
vendor/github.com/iancoleman/orderedmap/LICENSE
generated
vendored
Normal file
21
vendor/github.com/iancoleman/orderedmap/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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.
|
266
vendor/github.com/iancoleman/orderedmap/orderedmap.go
generated
vendored
Normal file
266
vendor/github.com/iancoleman/orderedmap/orderedmap.go
generated
vendored
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
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
|
||||||
|
}
|
81
vendor/github.com/iancoleman/orderedmap/readme.md
generated
vendored
Normal file
81
vendor/github.com/iancoleman/orderedmap/readme.md
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# orderedmap
|
||||||
|
|
||||||
|
[](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)
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@ -110,6 +110,9 @@ github.com/gobwas/glob/util/strings
|
|||||||
# github.com/gookit/color v1.4.2
|
# github.com/gookit/color v1.4.2
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/gookit/color
|
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
|
# github.com/imdario/mergo v0.3.11
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/imdario/mergo
|
github.com/imdario/mergo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user