mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Rework the custom pager config (rename to diff renderer) (#5870)
For a long time lazygit has used the term "custom pager" to refer to what's really a "diff renderer". A pager is a program that allows you to view output page by page (hence the name), e.g. less; lazygit's custom diff renderers are not pagers. It used the term only because the feature is implemented using git's `GIT_PAGER` env var, but that's an implementation detail. Rename the 'git.pagers' config to 'git.diffRenderers', and restructure its elements while we're at it to make things clearer: - Add a 'type' field to explicitly specify which type of diff renderer it is (the two fundamentally different ones are 'stdinFilter' and 'extDiff'). - Add a third type, 'rawGit', which has an 'args' field that makes it easy to use 'git diff --color-words' as a custom renderer - Unify the old 'pager' and 'externalDiffCommand' fields to a single 'command' field for both types Existing config files are migrated automatically.
This commit is contained in:
commit
d8d09e1f94
12
README.md
12
README.md
|
|
@ -118,7 +118,7 @@ If you're a mere mortal like me and you're tired of hearing how powerful git is
|
|||
- [Changing Directory On Exit](#changing-directory-on-exit)
|
||||
- [Undo/Redo](#undoredo)
|
||||
- [Configuration](#configuration)
|
||||
- [Custom Pagers](#custom-pagers)
|
||||
- [Custom Diff Renderers](#custom-diff-renderers)
|
||||
- [Custom Commands](#custom-commands)
|
||||
- [Git flow support](#git-flow-support)
|
||||
- [Contributing](#contributing)
|
||||
|
|
@ -423,6 +423,7 @@ nix-shell -p lazygit
|
|||
# or with flakes enabled
|
||||
nix run nixpkgs#lazygit
|
||||
```
|
||||
|
||||
Or you can add lazygit to your `configuration.nix` using the `environment.systemPackages` option.
|
||||
More details can be found via NixOS search [page](https://search.nixos.org/).
|
||||
|
||||
|
|
@ -431,6 +432,7 @@ More details can be found via NixOS search [page](https://search.nixos.org/).
|
|||
This repository includes a nix flake that provides the latest development version and additional development tools:
|
||||
|
||||
**Run lazygit directly from the repository:**
|
||||
|
||||
```sh
|
||||
nix run github:jesseduffield/lazygit
|
||||
# or from a local clone
|
||||
|
|
@ -438,6 +440,7 @@ nix run .
|
|||
```
|
||||
|
||||
**Build lazygit from source:**
|
||||
|
||||
```sh
|
||||
nix build github:jesseduffield/lazygit
|
||||
# or from a local clone
|
||||
|
|
@ -446,6 +449,7 @@ nix build .
|
|||
|
||||
**Development environment:**
|
||||
For contributors, the flake provides a development shell with Go toolchain, development tools, and dependencies:
|
||||
|
||||
```sh
|
||||
nix develop github:jesseduffield/lazygit
|
||||
# or from a local clone
|
||||
|
|
@ -453,12 +457,14 @@ nix develop
|
|||
```
|
||||
|
||||
The development shell includes:
|
||||
|
||||
- Go toolchain
|
||||
- git and make
|
||||
- Proper environment variables for development
|
||||
|
||||
**Using in other flakes:**
|
||||
The flake also provides an overlay for easy integration into other flake-based projects:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.lazygit.url = "github:jesseduffield/lazygit";
|
||||
|
|
@ -584,9 +590,9 @@ See the [docs](/docs/Undoing.md)
|
|||
|
||||
Check out the [configuration docs](docs/Config.md).
|
||||
|
||||
### Custom Pagers
|
||||
### Custom Diff Renderers
|
||||
|
||||
See the [docs](docs/Custom_Pagers.md)
|
||||
See the [docs](docs/Custom_DiffRenderers.md)
|
||||
|
||||
### Custom Commands
|
||||
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ gui:
|
|||
|
||||
# The number of spaces per tab; used for everything that's shown in the main
|
||||
# view, but probably mostly relevant for diffs.
|
||||
# Note that when using a pager, the pager has its own tab width setting, so you
|
||||
# need to pass it separately in the pager command.
|
||||
# Note that when using a diff renderer, the renderer has its own tab width
|
||||
# setting, so you need to pass it separately in the renderer command.
|
||||
tabWidth: 4
|
||||
|
||||
# If true, capture mouse events.
|
||||
|
|
@ -360,38 +360,39 @@ gui:
|
|||
|
||||
# Config relating to git
|
||||
git:
|
||||
# Array of pagers. Each entry has the following format:
|
||||
# Array of diff renderers. Each entry has the following format:
|
||||
#
|
||||
# # A name for the pager, shown in the notification when cycling pagers.
|
||||
# # If not set, the name is derived from the first word of the pager
|
||||
# # command (or of the external diff command).
|
||||
# # The type of diff renderer. One of: 'stdinFilter' (default) | 'extDiff'
|
||||
# # | 'rawGit'
|
||||
# type: "stdinFilter"
|
||||
#
|
||||
# # A name for the diff renderer, shown in the notification when cycling
|
||||
# # renderers. If not set, the name is derived from the first word of the
|
||||
# # renderer command.
|
||||
# name: ""
|
||||
#
|
||||
# # 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'
|
||||
# # Value of the --color arg in the git diff command. Only used for type
|
||||
# # 'stdinFilter'. Some renderers want this to be set to 'always' and some
|
||||
# # want it set to 'never'.
|
||||
# colorArg: "always"
|
||||
#
|
||||
# # The command to use for rendering diffs. This is either a stdinFilter or
|
||||
# # an external diff command, depending on the type field; not applicable if
|
||||
# # the type is 'rawGit'.
|
||||
# # e.g.
|
||||
# # diff-so-fancy
|
||||
# # delta --dark --paging=never
|
||||
# # ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
# pager: ""
|
||||
# # ydiff -p cat
|
||||
# # difft --color=always
|
||||
# command: ""
|
||||
#
|
||||
# # e.g. 'difft --color=always'
|
||||
# externalDiffCommand: ""
|
||||
# # Extra arguments (array of strings) passed to the git command. Only
|
||||
# # applicable if the type is 'rawGit'.
|
||||
# args: []
|
||||
#
|
||||
# # If true, Lazygit will use git's `diff.external` config for paging.
|
||||
# # The advantage over `externalDiffCommand` is that this can be
|
||||
# # configured per file type in .gitattributes; see
|
||||
# # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
# useExternalDiffGitConfig: false
|
||||
#
|
||||
# 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually
|
||||
# exclusive; set at most one per entry.
|
||||
#
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_DiffRenderers.md
|
||||
# for more information.
|
||||
pagers: []
|
||||
diffRenderers: []
|
||||
|
||||
# Config relating to committing
|
||||
commit:
|
||||
|
|
@ -714,8 +715,8 @@ keybinding:
|
|||
prevTab: '['
|
||||
nextScreenMode: +
|
||||
prevScreenMode: _
|
||||
cyclePagers: '|'
|
||||
cyclePagersReverse: \
|
||||
cycleDiffRenderers: '|'
|
||||
cycleDiffRenderersReverse: \
|
||||
undo: z
|
||||
redo: Z
|
||||
filteringMenu: <ctrl+s>
|
||||
|
|
|
|||
84
docs-master/Custom_DiffRenderers.md
Normal file
84
docs-master/Custom_DiffRenderers.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Custom Diff Renderers
|
||||
|
||||
Custom diff renderers are useful for showing a better rendering of a diff than git's builtin raw diff, and using one is strongly recommended (I personally prefer delta myself, but that's a matter of personal preference). There are three types of diff renderers that lazygit supports:
|
||||
|
||||
- **stdin filters**, e.g. [delta](#delta) and [diff-so-fancy](#diff-so-fancy). They take git's raw output as stdin and produce something nicer on stdout, and they are hooked up using git's GIT_PAGER mechanism. (These used to be called "custom pagers" in earlier lazygit versions.)
|
||||
- **external diff programs**, e.g. difftastic; these are called using git's `--ext-diff` flag, and they take over diff generation from git completely rather than post-processing git's output.
|
||||
- **git's raw output using custom arguments**; mainly useful for `--color-words` (or `--word-diff` if you are color blind).
|
||||
|
||||
Diff renderers are configured with the `diffRenderers` array in the `git` section of lazygit's config file; it is an array because you can have multiple entries that you can cycle through with the `|` key. This can be useful if you usually prefer a particular diff renderer, but want to use a different one for certain kinds of diffs.
|
||||
|
||||
Fields that are shared by all renderer types:
|
||||
|
||||
- **type** The type of diff renderer; choices are `stdinFilter`, `extDiff`, or `rawGit`. `stdinFilter` is the default, because it's the most common one; so you can omit this if you use delta.
|
||||
- **name** A name that is shown in the status bar toast when cycling renderers; defaults to the first word of the renderer command, but can be useful e.g. to distinguish "delta" from "delta side-by-side" if you have entries for both.
|
||||
|
||||
Fields only for `stdinFilter`:
|
||||
|
||||
- **command** The command line to use for `GIT_PAGER`.
|
||||
|
||||
- **colorArg** whether you want the `--color=always` arg in your `git diff` command. Some diff renderers want it set to `always`, others want it set to `never`. The default is `always`, since that's what most renderers need.
|
||||
|
||||
Fields only for `extDiff`:
|
||||
|
||||
- **command** The command line to use for the `diff.external` git config. If left empty, it uses the global value of git's `diff.external` config; this can be useful if you also want to use it for diffs on the command line, and it also has the advantage that you can configure it per file type in `.gitattributes`; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
|
||||
You can include the `{{diffContext}}` template variable to pass lazygit's current diff context size (the value controlled by the `{`/`}` keybindings) to the diff tool.
|
||||
|
||||
Fields only for `rawGit`:
|
||||
|
||||
- **args** The additional arguments to use in the `git diff` or `git show` call (e.g. `--color-words`)
|
||||
|
||||
Here's an example for a multi-renderer setup:
|
||||
|
||||
```yaml
|
||||
git:
|
||||
diffRenderers:
|
||||
- command: delta --dark --paging=never
|
||||
- command: ydiff -p cat
|
||||
colorArg: never
|
||||
- type: extDiff
|
||||
command: difft --color=always --context={{diffContext}}
|
||||
- type: rawGit
|
||||
args: --color-words
|
||||
name: color-words
|
||||
- type: rawGit # git's default diff
|
||||
name: default
|
||||
```
|
||||
|
||||
## Delta:
|
||||
|
||||
```yaml
|
||||
git:
|
||||
diffRenderers:
|
||||
- command: delta --dark --paging=never
|
||||
```
|
||||
|
||||

|
||||
|
||||
A cool feature of delta is --hyperlinks, which renders clickable links for the line numbers in the left margin, and lazygit supports these. To use them, set the `command:` field to `delta --dark --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"`; this allows you to click on an underlined line number in the diff to jump right to that same line in your editor.
|
||||
|
||||
Note that delta's `--navigate` option doesn't work in lazygit, for technical reasons.
|
||||
|
||||
## Diff-so-fancy
|
||||
|
||||
```yaml
|
||||
git:
|
||||
diffRenderers:
|
||||
- command: diff-so-fancy
|
||||
```
|
||||
|
||||

|
||||
|
||||
## ydiff
|
||||
|
||||
```yaml
|
||||
gui:
|
||||
sidePanelWidth: 0.2 # gives you more space to show things side-by-side
|
||||
git:
|
||||
diffRenderers:
|
||||
- colorArg: never
|
||||
command: ydiff -p cat
|
||||
```
|
||||
|
||||

|
||||
|
|
@ -1,108 +0,0 @@
|
|||
# Custom Pagers
|
||||
|
||||
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing `e` in the Status panel).
|
||||
|
||||
Multiple pagers are supported; you can cycle through them with the `|` key. This can be useful if you usually prefer a particular pager, but want to use a different one for certain kinds of diffs.
|
||||
|
||||
Pagers are configured with the `pagers` array in the git section; here's an example for a multi-pager setup (use an empty object `{}` for the default builtin diff display that doesn't use a pager):
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- pager: delta --dark --paging=never
|
||||
- pager: ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
colorArg: never
|
||||
- externalDiffCommand: difft --color=always
|
||||
- {} # default, no pager used
|
||||
```
|
||||
|
||||
The `colorArg` key is for whether you want the `--color=always` arg in your `git diff` command. Some pagers want it set to `always`, others want it set to `never`. The default is `always`, since that's what most pagers need.
|
||||
|
||||
## Delta:
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- pager: delta --dark --paging=never
|
||||
```
|
||||
|
||||

|
||||
|
||||
A cool feature of delta is --hyperlinks, which renders clickable links for the line numbers in the left margin, and lazygit supports these. To use them, set the `pager:` config to `delta --dark --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"`; this allows you to click on an underlined line number in the diff to jump right to that same line in your editor.
|
||||
|
||||
Note that delta's `--navigate` option doesn't work in lazygit, for technical reasons.
|
||||
|
||||
## Diff-so-fancy
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- pager: diff-so-fancy
|
||||
```
|
||||
|
||||

|
||||
|
||||
## ydiff
|
||||
|
||||
```yaml
|
||||
gui:
|
||||
sidePanelWidth: 0.2 # gives you more space to show things side-by-side
|
||||
git:
|
||||
pagers:
|
||||
- colorArg: never
|
||||
pager: ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
Be careful with this one, I think the homebrew and pip versions are behind master. I needed to directly download the ydiff script to get the no-pager functionality working.
|
||||
|
||||
## Using external diff commands
|
||||
|
||||
Some diff tools can't work as a simple pager like the ones above do, because they need access to the entire diff, so just post-processing git's diff is not enough for them. The most notable example is probably [difftastic](https://difftastic.wilfred.me.uk).
|
||||
|
||||
These can be used in lazygit by using the `externalDiffCommand` config; in the case of difftastic, that could be
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- externalDiffCommand: difft --color=always --context={{diffContext}}
|
||||
```
|
||||
|
||||
The `colorArg` option is not used in this case. You can include the `{{diffContext}}` template variable to pass lazygit's current diff context size (the value controlled by the `{`/`}` keybindings) to the diff tool.
|
||||
|
||||
You can add whatever extra arguments you prefer for your difftool; for instance
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- externalDiffCommand: difft --color=always --context={{diffContext}} --display=inline --syntax-highlight=off
|
||||
```
|
||||
|
||||
This can also be used for normal git diffs with custom parameters, such as `--color-words` or `--word-diff` which some people find useful. To do that, save a script like this to, say, `~/bin/color-words.sh`:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
|
||||
git diff --color-words --no-index --color=always --no-ext-diff --unified=$LAZYGIT_DIFF_CONTEXT "$2" "$5"
|
||||
```
|
||||
|
||||
And then use it in your git config like so:
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- externalDiffCommand: LAZYGIT_DIFF_CONTEXT={{diffContext}} ~/bin/color-words.sh
|
||||
```
|
||||
|
||||
Instead of setting this command in lazygit's `externalDiffCommand` config, you can also tell lazygit to use the external diff command that is configured in git itself (`diff.external`), by using
|
||||
|
||||
```yaml
|
||||
git:
|
||||
pagers:
|
||||
- useExternalDiffGitConfig: true
|
||||
```
|
||||
|
||||
This can be useful if you also want to use it for diffs on the command line, and it also has the advantage that you can configure it per file type in `.gitattributes`; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
|
||||
`pager`, `externalDiffCommand`, and `useExternalDiffGitConfig` are alternative ways of producing the diff, so a pager entry may use at most one of them.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
* [Configuration](./Config.md).
|
||||
* [Custom Commands](./Custom_Command_Keybindings.md)
|
||||
* [Custom Pagers](./Custom_Pagers.md)
|
||||
* [Custom Diff Renderers](./Custom_DiffRenderers.md)
|
||||
* [Dev docs](./dev)
|
||||
* [Keybindings](./keybindings)
|
||||
* [Undo/Redo](./Undoing.md)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | Refresh | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||
| `` + `` | Next screen mode (normal/half/fullscreen) | |
|
||||
| `` _ `` | Prev screen mode | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | Cancel | |
|
||||
| `` ? `` | Open keybindings menu | |
|
||||
| `` <ctrl+s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | 更新 | Gitの状態を更新します(`git status`、`git branch`などをバックグラウンドで実行してパネルの内容を更新します)。これは`git fetch`を実行しません。 |
|
||||
| `` + `` | 次の画面モード(通常/半分/全画面) | |
|
||||
| `` _ `` | 前の画面モード | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | キャンセル | |
|
||||
| `` ? `` | キーバインディングメニューを開く | |
|
||||
| `` <ctrl+s> `` | フィルターオプションを表示 | コミットログのフィルタリングオプションを表示し、フィルタに一致するコミットのみを表示します。 |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | 새로고침 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||
| `` + `` | 다음 스크린 모드 (normal/half/fullscreen) | |
|
||||
| `` _ `` | 이전 스크린 모드 | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | 취소 | |
|
||||
| `` ? `` | 매뉴 열기 | |
|
||||
| `` <ctrl+s> `` | View filter-by-path options | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | Verversen | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||
| `` + `` | Volgende scherm modus (normaal/half/groot) | |
|
||||
| `` _ `` | Vorige scherm modus | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | Annuleren | |
|
||||
| `` ? `` | Open menu | |
|
||||
| `` <ctrl+s> `` | Bekijk scoping opties | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | Odśwież | Odśwież stan git (tj. uruchom `git status`, `git branch`, itp. w tle, aby zaktualizować zawartość paneli). To nie uruchamia `git fetch`. |
|
||||
| `` + `` | Następny tryb ekranu (normalny/półpełny/pełnoekranowy) | |
|
||||
| `` _ `` | Poprzedni tryb ekranu | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | Anuluj | |
|
||||
| `` ? `` | Otwórz menu przypisań klawiszy | |
|
||||
| `` <ctrl+s> `` | Pokaż opcje filtrowania | Pokaż opcje filtrowania dziennika commitów, tak aby pokazywane były tylko commity pasujące do filtra. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | Atualizar | Atualize o estado do git (ou seja, execute `git status`, `git branch`, etc em segundo plano para atualizar o conteúdo de painéis). Isso não executa `git fetch`. |
|
||||
| `` + `` | Modo de tela seguinte (normal/metade/tela cheia) | |
|
||||
| `` _ `` | Modo de tela anterior | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | Cancelar | |
|
||||
| `` ? `` | Abrir o menu de atalhos do teclado | |
|
||||
| `` <ctrl+s> `` | Ver opções de filtro | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | Обновить | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||
| `` + `` | Следующий режим экрана (нормальный/полуэкранный/полноэкранный) | |
|
||||
| `` _ `` | Предыдущий режим экрана | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | Отменить | |
|
||||
| `` ? `` | Открыть меню | |
|
||||
| `` <ctrl+s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | 刷新 | 刷新Git状态(即在后台运行`git status`、`git branch`等命令以更新面板内容)。此操作不会执行`git fetch`。 |
|
||||
| `` + `` | 下一屏模式(正常/半屏/全屏) | |
|
||||
| `` _ `` | 上一屏模式 | |
|
||||
| `` \| `` | 切换分页器 | 从已配置的分页器列表中选择下一个分页器 |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | 取消 | |
|
||||
| `` ? `` | 打开菜单 | |
|
||||
| `` <ctrl+s> `` | 查看按路径过滤选项 | 查看用于过滤提交日志的选项,以便仅显示与过滤器匹配的提交。 |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` R `` | 重新整理 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||
| `` + `` | 下一個螢幕模式(常規/半螢幕/全螢幕) | |
|
||||
| `` _ `` | 上一個螢幕模式 | |
|
||||
| `` \| `` | Cycle pagers | Choose the next pager in the list of configured pagers. |
|
||||
| `` \ `` | Cycle pagers (reverse) | Choose the previous pager in the list of configured pagers. |
|
||||
| `` \| `` | Cycle diff renderers | Choose the next renderer in the list of configured diff renderers. |
|
||||
| `` \ `` | Cycle diff renderers (reverse) | Choose the previous renderer in the list of configured diff renderers. |
|
||||
| `` <esc> `` | 取消 | |
|
||||
| `` ? `` | 開啟選單 | |
|
||||
| `` <ctrl+s> `` | 檢視篩選路徑選項 | View options for filtering the commit log, so that only commits matching the filter are shown. |
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func NewGitCommand(
|
|||
version *git_commands.GitVersion,
|
||||
osCommand *oscommands.OSCommand,
|
||||
gitConfig git_config.IGitConfig,
|
||||
pagerConfig *config.PagerConfig,
|
||||
diffRendererConfigManager *config.DiffRendererConfigManager,
|
||||
) (*GitCommand, error) {
|
||||
repoPaths, err := git_commands.GetRepoPaths(osCommand.Cmd, version)
|
||||
if err != nil {
|
||||
|
|
@ -82,7 +82,7 @@ func NewGitCommand(
|
|||
osCommand,
|
||||
gitConfig,
|
||||
repoPaths,
|
||||
pagerConfig,
|
||||
diffRendererConfigManager,
|
||||
), nil
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ func NewGitCommandAux(
|
|||
osCommand *oscommands.OSCommand,
|
||||
gitConfig git_config.IGitConfig,
|
||||
repoPaths *git_commands.RepoPaths,
|
||||
pagerConfig *config.PagerConfig,
|
||||
diffRendererConfigManager *config.DiffRendererConfigManager,
|
||||
) *GitCommand {
|
||||
cmd := NewGitCmdObjBuilder(cmn.Log, osCommand.Cmd, repoPaths.WorktreePath())
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ func NewGitCommandAux(
|
|||
// common ones are: cmn, osCommand, dotGitDir, configCommands
|
||||
configCommands := git_commands.NewConfigCommands(cmn, gitConfig)
|
||||
|
||||
gitCommon := git_commands.NewGitCommon(cmn, version, cmd, osCommand, repoPaths, configCommands, pagerConfig)
|
||||
gitCommon := git_commands.NewGitCommon(cmn, version, cmd, osCommand, repoPaths, configCommands, diffRendererConfigManager)
|
||||
|
||||
fileLoader := git_commands.NewFileLoader(gitCommon, cmd, configCommands)
|
||||
statusCommands := git_commands.NewStatusCommands(gitCommon)
|
||||
|
|
|
|||
|
|
@ -241,23 +241,15 @@ func (self *CommitCommands) AmendHeadCmdObj() *oscommands.CmdObj {
|
|||
}
|
||||
|
||||
func (self *CommitCommands) ShowCmdObj(hash string, filterPaths []string) *oscommands.CmdObj {
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
|
||||
extDiffCmd := self.pagerConfig.GetExternalDiffCommand(contextSize)
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig()
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Config("diff.noprefix=false").
|
||||
ConfigIf(extDiffCmd != "", "diff.external="+extDiffCmd).
|
||||
ArgIfElse(extDiffCmd != "" || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true).
|
||||
Arg("--submodule").
|
||||
Arg("--color="+self.pagerConfig.GetColorArg()).
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
Arg("--color=" + self.diffRendererConfigManager.GetColorArg()).
|
||||
Arg("--stat").
|
||||
Arg("--decorate").
|
||||
Arg("-p").
|
||||
Arg(hash).
|
||||
ArgIf(self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)).
|
||||
Arg("--").
|
||||
Arg(filterPaths...).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize uint64
|
||||
similarityThreshold int
|
||||
ignoreWhitespace bool
|
||||
pagerConfig *config.PagingConfig
|
||||
diffRendererConfig *config.DiffRendererConfig
|
||||
expected []string
|
||||
}
|
||||
|
||||
|
|
@ -266,8 +266,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--find-renames=50%", "--"},
|
||||
diffRendererConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
{
|
||||
testName: "Default case with filter path",
|
||||
|
|
@ -275,8 +275,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--find-renames=50%", "--", "file.txt"},
|
||||
diffRendererConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom context size",
|
||||
|
|
@ -284,8 +284,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 77,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--find-renames=50%", "--"},
|
||||
diffRendererConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--unified=77", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom similarity threshold",
|
||||
|
|
@ -293,8 +293,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 33,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--find-renames=33%", "--"},
|
||||
diffRendererConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--unified=3", "--find-renames=33%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff, ignoring whitespace",
|
||||
|
|
@ -302,8 +302,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 77,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: true,
|
||||
pagerConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space", "--find-renames=50%", "--"},
|
||||
diffRendererConfig: nil,
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--unified=77", "--ignore-all-space", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with external diff command",
|
||||
|
|
@ -311,8 +311,8 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: &config.PagingConfig{ExternalDiffCommand: "difft --color=always"},
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "-c", "diff.noprefix=false", "show", "--ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--find-renames=50%", "--"},
|
||||
diffRendererConfig: &config.DiffRendererConfig{Type: "extDiff", Command: "difft --color=always"},
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "-c", "diff.noprefix=false", "show", "--ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff using git's external diff config",
|
||||
|
|
@ -320,16 +320,16 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: &config.PagingConfig{UseExternalDiffGitConfig: true},
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--find-renames=50%", "--"},
|
||||
diffRendererConfig: &config.DiffRendererConfig{Type: "extDiff"},
|
||||
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--stat", "--decorate", "-p", "1234567890", "--"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
userConfig := config.GetDefaultConfig()
|
||||
if s.pagerConfig != nil {
|
||||
userConfig.Git.Pagers = []config.PagingConfig{*s.pagerConfig}
|
||||
if s.diffRendererConfig != nil {
|
||||
userConfig.Git.DiffRenderers = []config.DiffRendererConfig{*s.diffRendererConfig}
|
||||
}
|
||||
userConfig.Git.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||
userConfig.Git.DiffContextSize = s.contextSize
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import (
|
|||
|
||||
type GitCommon struct {
|
||||
*common.Common
|
||||
version *GitVersion
|
||||
cmd oscommands.ICmdObjBuilder
|
||||
os *oscommands.OSCommand
|
||||
repoPaths *RepoPaths
|
||||
config *ConfigCommands
|
||||
pagerConfig *config.PagerConfig
|
||||
version *GitVersion
|
||||
cmd oscommands.ICmdObjBuilder
|
||||
os *oscommands.OSCommand
|
||||
repoPaths *RepoPaths
|
||||
config *ConfigCommands
|
||||
diffRendererConfigManager *config.DiffRendererConfigManager
|
||||
}
|
||||
|
||||
func NewGitCommon(
|
||||
|
|
@ -23,15 +23,15 @@ func NewGitCommon(
|
|||
osCommand *oscommands.OSCommand,
|
||||
repoPaths *RepoPaths,
|
||||
config *ConfigCommands,
|
||||
pagerConfig *config.PagerConfig,
|
||||
diffRendererConfigManager *config.DiffRendererConfigManager,
|
||||
) *GitCommon {
|
||||
return &GitCommon{
|
||||
Common: cmn,
|
||||
version: version,
|
||||
cmd: cmd,
|
||||
os: osCommand,
|
||||
repoPaths: repoPaths,
|
||||
config: config,
|
||||
pagerConfig: pagerConfig,
|
||||
Common: cmn,
|
||||
version: version,
|
||||
cmd: cmd,
|
||||
os: osCommand,
|
||||
repoPaths: repoPaths,
|
||||
config: config,
|
||||
diffRendererConfigManager: diffRendererConfigManager,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func buildGitCommon(deps commonDeps) *GitCommon {
|
|||
gitCommon.Common.SetUserConfig(config.GetDefaultConfig())
|
||||
}
|
||||
|
||||
gitCommon.pagerConfig = config.NewPagerConfig(func() *config.UserConfig {
|
||||
gitCommon.diffRendererConfigManager = config.NewDiffRendererConfigManager(func() *config.UserConfig {
|
||||
return gitCommon.Common.UserConfig()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -17,23 +17,14 @@ func NewDiffCommands(gitCommon *GitCommon) *DiffCommands {
|
|||
}
|
||||
|
||||
// This is for generating diffs to be shown in the UI (e.g. rendering a range
|
||||
// diff to the main view). It uses a custom pager if one is configured.
|
||||
// diff to the main view). It uses a custom diff renderer if one is configured.
|
||||
func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj {
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
extDiffCmd := self.pagerConfig.GetExternalDiffCommand(contextSize)
|
||||
useExtDiff := extDiffCmd != ""
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig()
|
||||
ignoreWhitespace := self.UserConfig().Git.IgnoreWhitespaceInDiffView
|
||||
|
||||
return self.cmd.New(
|
||||
NewGitCmd("diff").
|
||||
Config("diff.noprefix=false").
|
||||
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true).
|
||||
Arg("--submodule").
|
||||
Arg(fmt.Sprintf("--color=%s", self.pagerConfig.GetColorArg())).
|
||||
ArgIf(ignoreWhitespace, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
Arg(fmt.Sprintf("--color=%s", self.diffRendererConfigManager.GetColorArg())).
|
||||
Arg(diffArgs...).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
ToArgv(),
|
||||
|
|
@ -41,8 +32,8 @@ func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj {
|
|||
}
|
||||
|
||||
// This is a basic generic diff command that can be used for any diff operation
|
||||
// (e.g. copying a diff to the clipboard). It will not use a custom pager, and
|
||||
// does not use user configs such as ignore whitespace.
|
||||
// (e.g. copying a diff to the clipboard). It will not use a custom diff renderer,
|
||||
// and does not use user configs such as ignore whitespace.
|
||||
// If you want to diff specific refs (one or two), you need to add them yourself
|
||||
// in additionalArgs; it is recommended to also pass `--` after that. If you
|
||||
// want to restrict the diff to specific paths, pass them in additionalArgs
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package git_commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
)
|
||||
|
||||
// OptionalLocksEnvVar is the name of the environment variable that tells git
|
||||
|
|
@ -111,6 +113,20 @@ func (self *GitCommandBuilder) GitDirIf(condition bool, path string) *GitCommand
|
|||
return self
|
||||
}
|
||||
|
||||
func (self *GitCommandBuilder) AddCommonDiffArgs(diffRendererConfigManager *config.DiffRendererConfigManager, userConfig *config.UserConfig, forUI bool) *GitCommandBuilder {
|
||||
contextSize := userConfig.Git.DiffContextSize
|
||||
extDiffCmd := diffRendererConfigManager.GetExternalDiffCommand(contextSize)
|
||||
useExtDiff := forUI && diffRendererConfigManager.GetDiffRendererType() == config.DiffRendererType_ExtDiff
|
||||
|
||||
return self.
|
||||
ConfigIf(forUI && extDiffCmd != "", "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff, "--ext-diff", "--no-ext-diff").
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
ArgIf(forUI && userConfig.Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", userConfig.Git.RenameSimilarityThreshold)).
|
||||
ArgIf(forUI, diffRendererConfigManager.GetRawGitArgs()...)
|
||||
}
|
||||
|
||||
func (self *GitCommandBuilder) ToArgv() []string {
|
||||
return append([]string{"git"}, self.args...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,21 +81,13 @@ func (self *StashCommands) Hash(index int) (string, error) {
|
|||
}
|
||||
|
||||
func (self *StashCommands) ShowStashEntryCmdObj(index int) *oscommands.CmdObj {
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
extDiffCmd := self.pagerConfig.GetExternalDiffCommand(contextSize)
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig()
|
||||
|
||||
// "-u" is the same as "--include-untracked", but the latter fails in older git versions for some reason
|
||||
cmdArgs := NewGitCmd("stash").Arg("show").
|
||||
AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), true).
|
||||
Arg("-p").
|
||||
Arg("--stat").
|
||||
Arg("-u").
|
||||
ConfigIf(extDiffCmd != "", "diff.external="+extDiffCmd).
|
||||
ArgIfElse(extDiffCmd != "" || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
Arg(fmt.Sprintf("--color=%s", self.pagerConfig.GetColorArg())).
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
ArgIf(self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)).
|
||||
Arg(fmt.Sprintf("--color=%s", self.diffRendererConfigManager.GetColorArg())).
|
||||
Arg(fmt.Sprintf("refs/stash@{%d}", index)).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
ToArgv()
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize uint64
|
||||
similarityThreshold int
|
||||
ignoreWhitespace bool
|
||||
pagerConfig *config.PagingConfig
|
||||
diffRendererConfig *config.DiffRendererConfig
|
||||
expected []string
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "-u", "--no-ext-diff", "--color=always", "--unified=3", "--find-renames=50%", "refs/stash@{5}"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "--no-ext-diff", "--unified=3", "--find-renames=50%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom context size",
|
||||
|
|
@ -122,7 +122,7 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize: 77,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "-u", "--no-ext-diff", "--color=always", "--unified=77", "--find-renames=50%", "refs/stash@{5}"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "--no-ext-diff", "--unified=77", "--find-renames=50%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom similarity threshold",
|
||||
|
|
@ -130,7 +130,7 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 33,
|
||||
ignoreWhitespace: false,
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "-u", "--no-ext-diff", "--color=always", "--unified=3", "--find-renames=33%", "refs/stash@{5}"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "--no-ext-diff", "--unified=3", "--find-renames=33%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff with external diff command",
|
||||
|
|
@ -138,8 +138,8 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: &config.PagingConfig{ExternalDiffCommand: "difft --color=always"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "stash", "show", "-p", "--stat", "-u", "--ext-diff", "--color=always", "--unified=3", "--find-renames=50%", "refs/stash@{5}"},
|
||||
diffRendererConfig: &config.DiffRendererConfig{Type: "extDiff", Command: "difft --color=always"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "stash", "show", "--ext-diff", "--unified=3", "--find-renames=50%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
{
|
||||
testName: "Show diff using git's external diff config",
|
||||
|
|
@ -147,16 +147,16 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: false,
|
||||
pagerConfig: &config.PagingConfig{UseExternalDiffGitConfig: true},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "-u", "--ext-diff", "--color=always", "--unified=3", "--find-renames=50%", "refs/stash@{5}"},
|
||||
diffRendererConfig: &config.DiffRendererConfig{Type: "extDiff"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "--ext-diff", "--unified=3", "--find-renames=50%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
{
|
||||
testName: "Default case",
|
||||
testName: "Ignore whitespace",
|
||||
index: 5,
|
||||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
ignoreWhitespace: true,
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "-u", "--no-ext-diff", "--color=always", "--unified=3", "--ignore-all-space", "--find-renames=50%", "refs/stash@{5}"},
|
||||
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "--no-ext-diff", "--unified=3", "--ignore-all-space", "--find-renames=50%", "-p", "--stat", "-u", "--color=always", "refs/stash@{5}"},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -166,8 +166,8 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||
userConfig.Git.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||
userConfig.Git.DiffContextSize = s.contextSize
|
||||
userConfig.Git.RenameSimilarityThreshold = s.similarityThreshold
|
||||
if s.pagerConfig != nil {
|
||||
userConfig.Git.Pagers = []config.PagingConfig{*s.pagerConfig}
|
||||
if s.diffRendererConfig != nil {
|
||||
userConfig.Git.DiffRenderers = []config.DiffRendererConfig{*s.diffRendererConfig}
|
||||
}
|
||||
repoPaths := RepoPaths{
|
||||
worktreePath: "/path/to/worktree",
|
||||
|
|
|
|||
|
|
@ -393,17 +393,13 @@ func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool,
|
|||
// in the working tree. When pathOverrides is non-empty, those paths are used instead of
|
||||
// the node's path (used to diff only filtered/visible files within a directory).
|
||||
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool, pathOverrides []string) *oscommands.CmdObj {
|
||||
colorArg := self.pagerConfig.GetColorArg()
|
||||
colorArg := self.diffRendererConfigManager.GetColorArg()
|
||||
if plain {
|
||||
colorArg = "never"
|
||||
}
|
||||
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
prevPath := node.GetPreviousPath()
|
||||
noIndex := !node.GetIsTracked() && !node.GetHasStagedChanges() && !cached && node.GetIsFile()
|
||||
extDiffCmd := self.pagerConfig.GetExternalDiffCommand(contextSize)
|
||||
useExtDiff := extDiffCmd != "" && !plain
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig() && !plain
|
||||
|
||||
paths := pathOverrides
|
||||
if len(paths) == 0 {
|
||||
|
|
@ -411,13 +407,9 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
|||
}
|
||||
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !plain).
|
||||
Arg("--submodule").
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
||||
ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)).
|
||||
ArgIf(cached, "--cached").
|
||||
ArgIf(noIndex, "--no-index").
|
||||
Arg("--").
|
||||
|
|
@ -443,29 +435,19 @@ func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bo
|
|||
}
|
||||
|
||||
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileNames []string, plain bool) *oscommands.CmdObj {
|
||||
contextSize := self.UserConfig().Git.DiffContextSize
|
||||
|
||||
colorArg := self.pagerConfig.GetColorArg()
|
||||
colorArg := self.diffRendererConfigManager.GetColorArg()
|
||||
if plain {
|
||||
colorArg = "never"
|
||||
}
|
||||
|
||||
extDiffCmd := self.pagerConfig.GetExternalDiffCommand(contextSize)
|
||||
useExtDiff := extDiffCmd != "" && !plain
|
||||
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig() && !plain
|
||||
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
Config("diff.noprefix=false").
|
||||
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
|
||||
AddCommonDiffArgs(self.diffRendererConfigManager, self.UserConfig(), !plain).
|
||||
Arg("--submodule").
|
||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||
Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)).
|
||||
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
||||
Arg(from).
|
||||
Arg(to).
|
||||
ArgIf(reverse, "-R").
|
||||
ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
Arg("--").
|
||||
Arg(fileNames...).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--find-renames=50%", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "cached",
|
||||
|
|
@ -236,7 +236,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--find-renames=50%", "--cached", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--cached", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "plain",
|
||||
|
|
@ -251,7 +251,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=never", "--find-renames=50%", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=never", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "File not tracked and file has no staged changes",
|
||||
|
|
@ -266,7 +266,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--find-renames=50%", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Default case (ignore whitespace)",
|
||||
|
|
@ -281,7 +281,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--ignore-all-space", "--find-renames=50%", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--ignore-all-space", "--find-renames=50%", "--submodule", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom context size",
|
||||
|
|
@ -296,7 +296,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 17,
|
||||
similarityThreshold: 50,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=17", "--color=always", "--find-renames=50%", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=17", "--find-renames=50%", "--submodule", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom similarity threshold",
|
||||
|
|
@ -311,7 +311,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||
contextSize: 3,
|
||||
similarityThreshold: 33,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--find-renames=33%", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--unified=3", "--find-renames=33%", "--submodule", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||
ignoreWhitespace: false,
|
||||
contextSize: 3,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--find-renames=50%", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Show diff with custom context size",
|
||||
|
|
@ -372,7 +372,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||
ignoreWhitespace: false,
|
||||
contextSize: 123,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=123", "--find-renames=50%", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--unified=123", "--find-renames=50%", "--submodule", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Default case (ignore whitespace)",
|
||||
|
|
@ -384,7 +384,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||
ignoreWhitespace: true,
|
||||
contextSize: 3,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--find-renames=50%", "--color=always", "1234567890", "0987654321", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--unified=3", "--ignore-all-space", "--find-renames=50%", "--submodule", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||
},
|
||||
{
|
||||
testName: "Renamed file passes both paths so the rename is detected",
|
||||
|
|
@ -397,7 +397,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||
ignoreWhitespace: false,
|
||||
contextSize: 3,
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--find-renames=50%", "--color=always", "1234567890", "0987654321", "--", "new.txt", "old.txt"}, expectedResult, nil),
|
||||
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--unified=3", "--find-renames=50%", "--submodule", "--color=always", "1234567890", "0987654321", "--", "new.txt", "old.txt"}, expectedResult, nil),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ func (p *winPty) closeHpc() {
|
|||
// Windows 11 24H2 it waits for the console host to exit, and since closing
|
||||
// only delivers CTRL_CLOSE_EVENT to the attached client without terminating
|
||||
// it, a client that keeps running (git still computing an expensive diff, a
|
||||
// pager waiting for input) keeps the host — and with it ClosePseudoConsole —
|
||||
// alive arbitrarily long. Close is called while holding the global PtyMutex
|
||||
// and while the task's onDone once is executing, where blocking wedges every
|
||||
// subsequent task for the view (and with it the UI), so none of this may
|
||||
// happen on the caller's thread.
|
||||
// diff renderer waiting for input) keeps the host — and with it
|
||||
// ClosePseudoConsole — alive arbitrarily long. Close is called while holding
|
||||
// the global PtyMutex and while the task's onDone once is executing, where
|
||||
// blocking wedges every subsequent task for the view (and with it the UI), so
|
||||
// none of this may happen on the caller's thread.
|
||||
//
|
||||
// Within the teardown, the pipe ends must be closed before the
|
||||
// pseudoconsole, and without holding p.mu: closing the pseudoconsole flushes
|
||||
|
|
|
|||
|
|
@ -288,6 +288,8 @@ func computeMigratedConfig(path string, content []byte, changes *ChangesSet) ([]
|
|||
}{
|
||||
{[]string{"gui", "skipUnstageLineWarning"}, "skipDiscardChangeWarning"},
|
||||
{[]string{"keybinding", "universal", "executeCustomCommand"}, "executeShellCommand"},
|
||||
{[]string{"keybinding", "universal", "cyclePagers"}, "cycleDiffRenderers"},
|
||||
{[]string{"keybinding", "universal", "cyclePagersReverse"}, "cycleDiffRenderersReverse"},
|
||||
{[]string{"gui", "windowSize"}, "screenMode"},
|
||||
{[]string{"keybinding", "files", "openMergeTool"}, "openMergeOptions"},
|
||||
}
|
||||
|
|
@ -347,7 +349,12 @@ func computeMigratedConfig(path string, content []byte, changes *ChangesSet) ([]
|
|||
return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err)
|
||||
}
|
||||
|
||||
err = migratePagers(&rootNode, changes)
|
||||
err = migratePaging(&rootNode, changes)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err)
|
||||
}
|
||||
|
||||
err = migratePagersToDiffRenderers(&rootNode, changes)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err)
|
||||
}
|
||||
|
|
@ -512,7 +519,9 @@ func migrateAllBranchesLogCmd(rootNode *yaml.Node, changes *ChangesSet) error {
|
|||
})
|
||||
}
|
||||
|
||||
func migratePagers(rootNode *yaml.Node, changes *ChangesSet) error {
|
||||
// Migrate the single 'paging' node to an array of 'pagers'. This is not the final structure, we
|
||||
// migrate it to diffRenderers from there in a separate step below.
|
||||
func migratePaging(rootNode *yaml.Node, changes *ChangesSet) error {
|
||||
return yaml_utils.TransformNode(rootNode, []string{"git"}, func(gitNode *yaml.Node) error {
|
||||
pagingKeyNode, pagingValueNode := yaml_utils.LookupKey(gitNode, "paging")
|
||||
if pagingKeyNode == nil || pagingValueNode.Kind != yaml.MappingNode {
|
||||
|
|
@ -521,10 +530,11 @@ func migratePagers(rootNode *yaml.Node, changes *ChangesSet) error {
|
|||
}
|
||||
|
||||
pagersKeyNode, _ := yaml_utils.LookupKey(gitNode, "pagers")
|
||||
if pagersKeyNode != nil {
|
||||
// Conversely, if there *is* already a "pagers" array, we also have nothing to do.
|
||||
// This covers the case where the user keeps both the "paging" section and the "pagers"
|
||||
// array for the sake of easier testing of old versions.
|
||||
diffRenderersKeyNode, _ := yaml_utils.LookupKey(gitNode, "diffRenderers")
|
||||
if pagersKeyNode != nil || diffRenderersKeyNode != nil {
|
||||
// Conversely, if there is already a newer array config, we also have nothing to do.
|
||||
// This covers the case where the user keeps both formats for the sake of easier testing
|
||||
// of old versions.
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -532,6 +542,7 @@ func migratePagers(rootNode *yaml.Node, changes *ChangesSet) error {
|
|||
pagingContentCopy := pagingValueNode.Content
|
||||
pagingValueNode.Kind = yaml.SequenceNode
|
||||
pagingValueNode.Tag = "!!seq"
|
||||
pagingValueNode.Style &^= yaml.FlowStyle
|
||||
pagingValueNode.Content = []*yaml.Node{{
|
||||
Kind: yaml.MappingNode,
|
||||
Content: pagingContentCopy,
|
||||
|
|
@ -543,6 +554,90 @@ func migratePagers(rootNode *yaml.Node, changes *ChangesSet) error {
|
|||
})
|
||||
}
|
||||
|
||||
func migratePagersToDiffRenderers(rootNode *yaml.Node, changes *ChangesSet) error {
|
||||
return yaml_utils.TransformNode(rootNode, []string{"git"}, func(gitNode *yaml.Node) error {
|
||||
pagersKeyNode, pagersValueNode := yaml_utils.LookupKey(gitNode, "pagers")
|
||||
if pagersKeyNode == nil || pagersValueNode.Kind != yaml.SequenceNode {
|
||||
// If there's no "pagers" section (or it's not a sequence), there's nothing to do
|
||||
return nil
|
||||
}
|
||||
|
||||
diffRenderersKeyNode, _ := yaml_utils.LookupKey(gitNode, "diffRenderers")
|
||||
if diffRenderersKeyNode != nil {
|
||||
// Conversely, if there *is* already a "diffRenderers" array, we also have nothing to do.
|
||||
// This covers the case where the user keeps both the "pagers" and the "diffRenderers"
|
||||
// arrays for the sake of easier testing of old versions.
|
||||
return nil
|
||||
}
|
||||
|
||||
pagersKeyNode.Value = "diffRenderers"
|
||||
changes.Add("Renamed git.pagers to git.diffRenderers")
|
||||
|
||||
for _, diffRendererNode := range pagersValueNode.Content {
|
||||
if diffRendererNode.Kind != yaml.MappingNode {
|
||||
continue
|
||||
}
|
||||
|
||||
pagerKeyNode, pagerValueNode := yaml_utils.LookupKey(diffRendererNode, "pager")
|
||||
externalDiffCommandKeyNode, externalDiffCommandValueNode := yaml_utils.LookupKey(diffRendererNode, "externalDiffCommand")
|
||||
useExternalDiffGitConfigKeyNode, useExternalDiffGitConfigValueNode := yaml_utils.LookupKey(diffRendererNode, "useExternalDiffGitConfig")
|
||||
|
||||
hasPager := hasNonNullScalarValue(pagerValueNode)
|
||||
hasExternalDiffCommand := hasNonNullScalarValue(externalDiffCommandValueNode)
|
||||
useExternalDiffGitConfig := yamlBoolValue(useExternalDiffGitConfigValueNode)
|
||||
|
||||
if hasPager {
|
||||
pagerKeyNode.Value = "command"
|
||||
changes.Add("Renamed 'pager' to 'command' in git pager")
|
||||
} else if hasExternalDiffCommand {
|
||||
externalDiffCommandKeyNode.Value = "command"
|
||||
yaml_utils.AddStringKey(diffRendererNode, "type", "extDiff")
|
||||
changes.Add("Changed 'externalDiffCommand' to 'command' with 'type: extDiff' in git pager")
|
||||
} else if useExternalDiffGitConfig {
|
||||
yaml_utils.RemoveKey(diffRendererNode, "useExternalDiffGitConfig")
|
||||
yaml_utils.AddStringKey(diffRendererNode, "type", "extDiff")
|
||||
changes.Add("Changed 'useExternalDiffGitConfig: true' to 'type: extDiff' in git pager")
|
||||
} else {
|
||||
yaml_utils.AddStringKey(diffRendererNode, "type", "rawGit")
|
||||
diffRendererNode.Style &^= yaml.FlowStyle
|
||||
changes.Add("Changed git pager without a command to 'type: rawGit'")
|
||||
}
|
||||
|
||||
if pagerKeyNode != nil && !hasPager {
|
||||
yaml_utils.RemoveKey(diffRendererNode, "pager")
|
||||
changes.Add("Removed empty 'pager' from git pager")
|
||||
}
|
||||
if externalDiffCommandKeyNode != nil && !hasExternalDiffCommand {
|
||||
yaml_utils.RemoveKey(diffRendererNode, "externalDiffCommand")
|
||||
changes.Add("Removed empty 'externalDiffCommand' from git pager")
|
||||
}
|
||||
if useExternalDiffGitConfigKeyNode != nil && !useExternalDiffGitConfig {
|
||||
yaml_utils.RemoveKey(diffRendererNode, "useExternalDiffGitConfig")
|
||||
if useExternalDiffGitConfigValueNode.Tag == "!!null" {
|
||||
changes.Add("Removed empty 'useExternalDiffGitConfig' from git pager")
|
||||
} else {
|
||||
changes.Add("Removed 'useExternalDiffGitConfig: false' from git pager")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func hasNonNullScalarValue(node *yaml.Node) bool {
|
||||
return node != nil && node.Kind == yaml.ScalarNode && node.Tag != "!!null" && node.Value != ""
|
||||
}
|
||||
|
||||
func yamlBoolValue(node *yaml.Node) bool {
|
||||
if node == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var value bool
|
||||
return node.Decode(&value) == nil && value
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetDebug() bool {
|
||||
return c.debug
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,24 +83,28 @@ func TestMigrationOfRenamedKeys(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "Rename several",
|
||||
input: `gui:
|
||||
windowSize: half
|
||||
skipUnstageLineWarning: true
|
||||
keybinding:
|
||||
universal:
|
||||
executeCustomCommand: a
|
||||
`,
|
||||
expected: `gui:
|
||||
screenMode: half
|
||||
skipDiscardChangeWarning: true
|
||||
keybinding:
|
||||
universal:
|
||||
executeShellCommand: a
|
||||
`,
|
||||
input: "gui:\n" +
|
||||
" windowSize: half\n" +
|
||||
" skipUnstageLineWarning: true\n" +
|
||||
"keybinding:\n" +
|
||||
" universal:\n" +
|
||||
" executeCustomCommand: a\n" +
|
||||
" cyclePagers: b\n" +
|
||||
" cyclePagersReverse: c\n",
|
||||
expected: "gui:\n" +
|
||||
" screenMode: half\n" +
|
||||
" skipDiscardChangeWarning: true\n" +
|
||||
"keybinding:\n" +
|
||||
" universal:\n" +
|
||||
" executeShellCommand: a\n" +
|
||||
" cycleDiffRenderers: b\n" +
|
||||
" cycleDiffRenderersReverse: c\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{
|
||||
"Renamed 'gui.skipUnstageLineWarning' to 'skipDiscardChangeWarning'",
|
||||
"Renamed 'keybinding.universal.executeCustomCommand' to 'executeShellCommand'",
|
||||
"Renamed 'keybinding.universal.cyclePagers' to 'cycleDiffRenderers'",
|
||||
"Renamed 'keybinding.universal.cyclePagersReverse' to 'cycleDiffRenderersReverse'",
|
||||
"Renamed 'gui.windowSize' to 'screenMode'",
|
||||
},
|
||||
},
|
||||
|
|
@ -470,629 +474,6 @@ func TestCustomCommandsOutputMigration(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var largeConfiguration = []byte(`
|
||||
# Config relating to the Lazygit UI
|
||||
gui:
|
||||
# The number of lines you scroll by when scrolling the main window
|
||||
scrollHeight: 2
|
||||
|
||||
# If true, allow scrolling past the bottom of the content in the main window
|
||||
scrollPastBottom: true
|
||||
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#scroll-off-margin
|
||||
scrollOffMargin: 2
|
||||
|
||||
# One of: 'margin' (default) | 'jump'
|
||||
scrollOffBehavior: margin
|
||||
|
||||
# The number of spaces per tab; used for everything that's shown in the main view, but probably mostly relevant for diffs.
|
||||
# Note that when using a pager, the pager has its own tab width setting, so you need to pass it separately in the pager command.
|
||||
tabWidth: 4
|
||||
|
||||
# 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
|
||||
|
||||
# If true, do not show a warning when amending a commit.
|
||||
skipAmendWarning: false
|
||||
|
||||
# If true, do not show a warning when discarding changes in the staging view.
|
||||
skipDiscardChangeWarning: false
|
||||
|
||||
# If true, do not show warning when applying/popping the stash
|
||||
skipStashWarning: false
|
||||
|
||||
# If true, do not show a warning when attempting to commit without any staged files; instead stage all unstaged files.
|
||||
skipNoStagedFilesWarning: false
|
||||
|
||||
# If true, do not show a warning when rewording a commit via an external editor
|
||||
skipRewordInEditorWarning: false
|
||||
|
||||
# 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
|
||||
|
||||
# If true, increase the height of the focused side window; creating an accordion effect.
|
||||
expandFocusedSidePanel: false
|
||||
|
||||
# The weight of the expanded side panel, relative to the other panels. 2 means
|
||||
# twice as tall as the other panels. Only relevant if expandFocusedSidePanel is true.
|
||||
expandedSidePanelWeight: 2
|
||||
|
||||
# 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
|
||||
|
||||
# If true, wrap lines in the staging view to the width of the view. This
|
||||
# makes it much easier to work with diffs that have long lines, e.g.
|
||||
# paragraphs of markdown text.
|
||||
wrapLinesInStagingView: true
|
||||
|
||||
# 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:
|
||||
# Border color of focused window
|
||||
activeBorderColor:
|
||||
- green
|
||||
- bold
|
||||
|
||||
# Border color of non-focused windows
|
||||
inactiveBorderColor:
|
||||
- default
|
||||
|
||||
# Border color of focused window when searching in that window
|
||||
searchingActiveBorderColor:
|
||||
- cyan
|
||||
- bold
|
||||
|
||||
# Color of keybindings help text in the bottom line
|
||||
optionsTextColor:
|
||||
- blue
|
||||
|
||||
# Background color of selected line.
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
|
||||
selectedLineBgColor:
|
||||
- blue
|
||||
|
||||
# Background color of selected line when view doesn't have focus.
|
||||
inactiveViewSelectedLineBgColor:
|
||||
- bold
|
||||
|
||||
# Foreground color of copied commit
|
||||
cherryPickedCommitFgColor:
|
||||
- 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:
|
||||
- red
|
||||
|
||||
# Default text color
|
||||
defaultFgColor:
|
||||
- default
|
||||
|
||||
# Config relating to the commit length indicator
|
||||
commitLength:
|
||||
# If true, show an indicator of commit message length
|
||||
show: true
|
||||
|
||||
# If true, show the '5 of 20' footer at the bottom of list views
|
||||
showListFooter: true
|
||||
|
||||
# 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 the number of lines changed per file in the Files view
|
||||
showNumstatInFilesView: false
|
||||
|
||||
# If true, show a random tip in the command log when Lazygit starts
|
||||
showRandomTip: true
|
||||
|
||||
# If true, show the command log
|
||||
showCommandLog: true
|
||||
|
||||
# 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.
|
||||
showBottomLine: true
|
||||
|
||||
# If true, show jump-to-window keybindings in window titles.
|
||||
showPanelJumps: true
|
||||
|
||||
# Deprecated: use nerdFontsVersion instead
|
||||
showIcons: false
|
||||
|
||||
# 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 author name in (non-expanded) commits view. 2 means show initials only.
|
||||
commitAuthorShortLength: 2
|
||||
|
||||
# Length of author name in expanded commits view. 2 means show initials only.
|
||||
commitAuthorLongLength: 17
|
||||
|
||||
# Length of commit hash in commits view. 0 shows '*' if NF icons aren't on.
|
||||
commitHashLength: 8
|
||||
|
||||
# If true, show commit hashes alongside branch names in the branches view.
|
||||
showBranchCommitHash: false
|
||||
|
||||
# Whether to show the divergence from the base branch in the branches view.
|
||||
# One of: 'none' | 'onlyArrow' | 'arrowAndNumber'
|
||||
showDivergenceFromBaseBranch: none
|
||||
|
||||
# Height of the command log view
|
||||
commandLogSize: 8
|
||||
|
||||
# Whether to split the main window when viewing file changes.
|
||||
# One of: 'auto' | 'always'
|
||||
# If 'auto', only split the main window when a file has both staged and unstaged changes
|
||||
splitDiff: auto
|
||||
|
||||
# Default size for focused window. Can be changed from within Lazygit with '+' and '_' (but this won't change the default).
|
||||
# One of: 'normal' (default) | 'half' | 'full'
|
||||
screenMode: normal
|
||||
|
||||
# Window border style.
|
||||
# One of 'rounded' (default) | 'single' | 'double' | 'hidden' | 'bold'
|
||||
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:
|
||||
# The frames of the spinner animation.
|
||||
frames:
|
||||
- '|'
|
||||
- /
|
||||
- '-'
|
||||
- \
|
||||
|
||||
# The "speed" of the spinner in milliseconds.
|
||||
rate: 50
|
||||
|
||||
# Status panel view.
|
||||
# One of 'dashboard' (default) | 'allBranchesLog'
|
||||
statusPanelView: dashboard
|
||||
|
||||
# If true, jump to the Files panel after popping a stash
|
||||
switchToFilesAfterStashPop: true
|
||||
|
||||
# If true, jump to the Files panel after applying a stash
|
||||
switchToFilesAfterStashApply: true
|
||||
|
||||
# If true, when using the panel jump keys (default 1 through 5) and target panel is already active, go to next tab instead
|
||||
switchTabsWithPanelJumpKeys: false
|
||||
|
||||
# Config relating to git
|
||||
git:
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
|
||||
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
|
||||
|
||||
# e.g.
|
||||
# diff-so-fancy
|
||||
# delta --dark --paging=never
|
||||
# ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
pager: ""
|
||||
|
||||
useConfig: false
|
||||
|
||||
# e.g. 'difft --color=always'
|
||||
externalDiffCommand: ""
|
||||
|
||||
# Config relating to committing
|
||||
commit:
|
||||
# If true, pass '--signoff' flag when committing
|
||||
signOff: false
|
||||
|
||||
# Automatic WYSIWYG wrapping of the commit message as you type
|
||||
autoWrapCommitMessage: true
|
||||
|
||||
# If autoWrapCommitMessage is true, the width to wrap to
|
||||
autoWrapWidth: 72
|
||||
|
||||
# Config relating to merging
|
||||
merging:
|
||||
# If true, run merges in a subprocess so that if a commit message is required, Lazygit will not hang
|
||||
# Only applicable to unix users.
|
||||
manualCommit: false
|
||||
|
||||
# Extra args passed to , e.g. --no-ff
|
||||
args: ""
|
||||
|
||||
# The commit message to use for a squash merge commit. Can contain "{{selectedRef}}" and "{{currentBranch}}" placeholders.
|
||||
squashMergeMessage: Squash merge {{selectedRef}} into {{currentBranch}}
|
||||
|
||||
# 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, poll the repo periodically for external ref changes (commits,
|
||||
# branch updates, checkouts made outside lazygit) and refresh when one
|
||||
# is detected. Independent of autoRefresh, which only governs the files
|
||||
# panel.
|
||||
autoDetectExternalChanges: true
|
||||
|
||||
# If true, pass the --all arg to git fetch
|
||||
fetchAll: true
|
||||
|
||||
# If true, lazygit will automatically stage files that used to have merge
|
||||
# conflicts but no longer do; and it will also ask you if you want to
|
||||
# continue a merge or rebase if you've resolved all conflicts. If false, it
|
||||
# won't do either of these things.
|
||||
autoStageResolvedConflicts: 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.
|
||||
# Deprecated: Use allBranchesLogCmds instead.
|
||||
allBranchesLogCmd: git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium
|
||||
|
||||
# If true, do not spawn a separate process when using GPG
|
||||
overrideGpg: false
|
||||
|
||||
# If true, do not allow force pushes
|
||||
disableForcePushing: false
|
||||
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-branch-name-prefix
|
||||
branchPrefix: ""
|
||||
|
||||
# If true, parse emoji strings in commit messages e.g. render :rocket: as 🚀
|
||||
# (This should really be under 'gui', not 'git')
|
||||
parseEmoji: false
|
||||
|
||||
# Config for showing the log in the commits view
|
||||
log:
|
||||
# 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
|
||||
# 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).
|
||||
order: topo-order
|
||||
|
||||
# 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).
|
||||
showGraph: always
|
||||
|
||||
# displays the whole git graph by default in the commits view (equivalent to passing the --all argument to git log)
|
||||
showWholeGraph: false
|
||||
|
||||
# When copying commit hashes to the clipboard, truncate them to this
|
||||
# length. Set to 40 to disable truncation.
|
||||
truncateCopiedCommitHashesTo: 12
|
||||
|
||||
# Periodic update checks
|
||||
update:
|
||||
# One of: 'prompt' (default) | 'background' | 'never'
|
||||
method: prompt
|
||||
|
||||
# Period in days between update checks
|
||||
days: 14
|
||||
|
||||
# Background refreshes
|
||||
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
|
||||
|
||||
# Interval in seconds at which lazygit polls for external ref changes
|
||||
# (commits, branch updates, checkouts made outside lazygit).
|
||||
# Detection can be disabled via option 'git.autoDetectExternalChanges'.
|
||||
externalChangeCheckInterval: 2
|
||||
|
||||
# If true, show a confirmation popup before quitting Lazygit
|
||||
confirmOnQuit: false
|
||||
|
||||
# If true, exit Lazygit when the user presses escape in a context where there is nothing to cancel/close
|
||||
quitOnTopLevelReturn: false
|
||||
|
||||
# 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: ""
|
||||
|
||||
# Whether lazygit suspends until an edit process returns
|
||||
editInTerminal: false
|
||||
|
||||
# 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-and-pasting-from-clipboard
|
||||
copyToClipboardCmd: ""
|
||||
|
||||
# ReadFromClipboardCmd is the command for reading the clipboard.
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-command-for-copying-to-and-pasting-from-clipboard
|
||||
readFromClipboardCmd: ""
|
||||
|
||||
# If true, don't display introductory popups upon opening Lazygit.
|
||||
disableStartupPopups: false
|
||||
|
||||
# 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:
|
||||
universal:
|
||||
quit: q
|
||||
quit-alt1: <c-c>
|
||||
return: <esc>
|
||||
quitWithoutChangingDirectory: Q
|
||||
togglePanel: <tab>
|
||||
prevItem: <up>
|
||||
nextItem: <down>
|
||||
prevItem-alt: k
|
||||
nextItem-alt: j
|
||||
prevPage: ','
|
||||
nextPage: .
|
||||
scrollLeft: H
|
||||
scrollRight: L
|
||||
gotoTop: <
|
||||
gotoBottom: '>'
|
||||
toggleRangeSelect: v
|
||||
rangeSelectDown: <s-down>
|
||||
rangeSelectUp: <s-up>
|
||||
prevBlock: <left>
|
||||
nextBlock: <right>
|
||||
prevBlock-alt: h
|
||||
nextBlock-alt: l
|
||||
nextBlock-alt2: <tab>
|
||||
prevBlock-alt2: <backtab>
|
||||
jumpToBlock:
|
||||
- "1"
|
||||
- "2"
|
||||
- "3"
|
||||
- "4"
|
||||
- "5"
|
||||
nextMatch: "n"
|
||||
prevMatch: "N"
|
||||
startSearch: /
|
||||
optionMenu: <disabled>
|
||||
optionMenu-alt1: '?'
|
||||
select: <space>
|
||||
goInto: <enter>
|
||||
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>
|
||||
executeShellCommand: ':'
|
||||
createRebaseOptionsMenu: m
|
||||
|
||||
# 'Files' appended for legacy reasons
|
||||
pushFiles: P
|
||||
|
||||
# 'Files' appended for legacy reasons
|
||||
pullFiles: p
|
||||
refresh: R
|
||||
createPatchOptionsMenu: <c-p>
|
||||
nextTab: ']'
|
||||
prevTab: '['
|
||||
nextScreenMode: +
|
||||
prevScreenMode: _
|
||||
undo: z
|
||||
redo: Z
|
||||
filteringMenu: <c-s>
|
||||
diffingMenu: W
|
||||
diffingMenu-alt: <c-e>
|
||||
copyToClipboard: <c-o>
|
||||
openRecentRepos: <c-r>
|
||||
submitEditorText: <enter>
|
||||
extrasMenu: '@'
|
||||
toggleWhitespaceInDiffView: <c-w>
|
||||
increaseContextInDiffView: '}'
|
||||
decreaseContextInDiffView: '{'
|
||||
increaseRenameSimilarityThreshold: )
|
||||
decreaseRenameSimilarityThreshold: (
|
||||
openDiffTool: <c-t>
|
||||
status:
|
||||
checkForUpdate: u
|
||||
recentRepos: <enter>
|
||||
allBranchesLogGraph: a
|
||||
files:
|
||||
commitChanges: c
|
||||
commitChangesWithoutHook: w
|
||||
amendLastCommit: A
|
||||
commitChangesWithEditor: C
|
||||
findBaseCommitForFixup: <c-f>
|
||||
confirmDiscard: x
|
||||
ignoreFile: i
|
||||
refreshFiles: r
|
||||
stashAllChanges: s
|
||||
viewStashOptions: S
|
||||
toggleStagedAll: a
|
||||
viewResetOptions: D
|
||||
fetch: f
|
||||
openMergeOptions: M
|
||||
openStatusFilter: <c-b>
|
||||
copyFileInfoToClipboard: "y"
|
||||
collapseAll: '-'
|
||||
expandAll: =
|
||||
branches:
|
||||
createPullRequest: o
|
||||
viewPullRequestOptions: O
|
||||
copyPullRequestURL: <c-y>
|
||||
checkoutBranchByName: c
|
||||
forceCheckoutBranch: F
|
||||
rebaseBranch: r
|
||||
renameBranch: R
|
||||
mergeIntoCurrentBranch: M
|
||||
viewGitFlowOptions: i
|
||||
fastForward: f
|
||||
createTag: T
|
||||
pushTag: P
|
||||
setUpstream: u
|
||||
fetchRemote: f
|
||||
sortOrder: s
|
||||
worktrees:
|
||||
viewWorktreeOptions: w
|
||||
commits:
|
||||
squashDown: s
|
||||
renameCommit: r
|
||||
renameCommitWithEditor: R
|
||||
viewResetOptions: g
|
||||
markCommitAsFixup: f
|
||||
createFixupCommit: F
|
||||
squashAboveCommits: S
|
||||
moveDownCommit: <c-j>
|
||||
moveUpCommit: <c-k>
|
||||
amendToCommit: A
|
||||
resetCommitAuthor: a
|
||||
pickCommit: p
|
||||
revertCommit: t
|
||||
cherryPickCopy: C
|
||||
pasteCommits: V
|
||||
markCommitAsBaseForRebase: B
|
||||
tagCommit: T
|
||||
checkoutCommit: <space>
|
||||
resetCherryPick: <c-R>
|
||||
copyCommitAttributeToClipboard: "y"
|
||||
openLogMenu: <c-l>
|
||||
openInBrowser: o
|
||||
viewBisectOptions: b
|
||||
startInteractiveRebase: i
|
||||
amendAttribute:
|
||||
resetAuthor: 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>
|
||||
`)
|
||||
|
||||
func BenchmarkMigrationOnLargeConfiguration(b *testing.B) {
|
||||
for b.Loop() {
|
||||
changes := NewChangesSet()
|
||||
_, _, _ = computeMigratedConfig("path doesn't matter", largeConfiguration, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllBranchesLogCmdMigrations(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
|
|
@ -1218,6 +599,7 @@ func TestPagerMigration(t *testing.T) {
|
|||
expectedDidChange bool
|
||||
expectedChanges []string
|
||||
}{
|
||||
// Migrate 'paging' to 'pagers' array
|
||||
{
|
||||
name: "Incomplete Configuration Passes uneventfully",
|
||||
input: "git:",
|
||||
|
|
@ -1226,68 +608,203 @@ func TestPagerMigration(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "No paging section",
|
||||
input: `git:
|
||||
autoFetch: true
|
||||
`,
|
||||
expected: `git:
|
||||
autoFetch: true
|
||||
`,
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "Both paging and pagers exist",
|
||||
input: `git:
|
||||
paging:
|
||||
pager: delta --dark --paging=never
|
||||
pagers:
|
||||
- diff: diff-so-fancy
|
||||
`,
|
||||
expected: `git:
|
||||
paging:
|
||||
pager: delta --dark --paging=never
|
||||
pagers:
|
||||
- diff: diff-so-fancy
|
||||
`,
|
||||
input: "git:\n" +
|
||||
" autoFetch: true\n",
|
||||
expected: "git:\n" +
|
||||
" autoFetch: true\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "paging is not an object",
|
||||
input: `git:
|
||||
paging: 5
|
||||
`,
|
||||
expected: `git:
|
||||
paging: 5
|
||||
`,
|
||||
input: "git:\n" +
|
||||
" paging: 5\n",
|
||||
expected: "git:\n" +
|
||||
" paging: 5\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "paging is moved to pagers array (keeping the order)",
|
||||
input: `git:
|
||||
paging:
|
||||
pager: delta --dark --paging=never
|
||||
autoFetch: true
|
||||
`,
|
||||
expected: `git:
|
||||
pagers:
|
||||
- pager: delta --dark --paging=never
|
||||
autoFetch: true
|
||||
`,
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Moved git.paging object to git.pagers array"},
|
||||
name: "pagers is not an array",
|
||||
input: "git:\n" +
|
||||
" pagers: 5\n",
|
||||
expected: "git:\n" +
|
||||
" pagers: 5\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "paging is moved to pagers array even if empty",
|
||||
input: `git:
|
||||
paging: {}
|
||||
`,
|
||||
expected: `git:
|
||||
pagers: [{}]
|
||||
`,
|
||||
name: "paging and pagers coexist",
|
||||
input: "git:\n" +
|
||||
" paging:\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" pagers:\n" +
|
||||
" - pager: diff-so-fancy\n",
|
||||
expected: "git:\n" +
|
||||
" paging:\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: diff-so-fancy\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Moved git.paging object to git.pagers array"},
|
||||
expectedChanges: []string{
|
||||
"Renamed git.pagers to git.diffRenderers",
|
||||
"Renamed 'pager' to 'command' in git pager",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "paging and diffRenderers coexist",
|
||||
input: "git:\n" +
|
||||
" paging:\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: diff-so-fancy\n",
|
||||
expected: "git:\n" +
|
||||
" paging:\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: diff-so-fancy\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "pagers and diffRenderers coexist",
|
||||
input: "git:\n" +
|
||||
" pagers:\n" +
|
||||
" - pager: delta --dark --paging=never\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: diff-so-fancy\n",
|
||||
expected: "git:\n" +
|
||||
" pagers:\n" +
|
||||
" - pager: delta --dark --paging=never\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: diff-so-fancy\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "paging is moved to diffRenderers array preserving fields and order",
|
||||
input: "git:\n" +
|
||||
" paging:\n" +
|
||||
" name: delta\n" +
|
||||
" colorArg: never\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" autoFetch: true\n",
|
||||
expected: "git:\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - name: delta\n" +
|
||||
" colorArg: never\n" +
|
||||
" command: delta --dark --paging=never\n" +
|
||||
" autoFetch: true\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{
|
||||
"Moved git.paging object to git.pagers array",
|
||||
"Renamed git.pagers to git.diffRenderers",
|
||||
"Renamed 'pager' to 'command' in git pager",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "paging is moved to diffRenderers array even if empty",
|
||||
input: "git:\n" +
|
||||
" paging: {}\n",
|
||||
expected: "git:\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - type: rawGit\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{
|
||||
"Moved git.paging object to git.pagers array",
|
||||
"Renamed git.pagers to git.diffRenderers",
|
||||
"Changed git pager without a command to 'type: rawGit'",
|
||||
},
|
||||
},
|
||||
|
||||
// Migrate 'pagers' array to 'diffRenderers' array
|
||||
{
|
||||
name: "empty pagers array is renamed",
|
||||
input: "git:\n" +
|
||||
" pagers: []\n",
|
||||
expected: "git:\n" +
|
||||
" diffRenderers: []\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Renamed git.pagers to git.diffRenderers"},
|
||||
},
|
||||
{
|
||||
name: "pagers array entries are adapted",
|
||||
input: "git:\n" +
|
||||
" pagers:\n" +
|
||||
" - name: delta\n" +
|
||||
" colorArg: never\n" +
|
||||
" pager: delta --dark --paging=never\n" +
|
||||
" - name: difft\n" +
|
||||
" colorArg: never\n" +
|
||||
" externalDiffCommand: difft --color=always\n" +
|
||||
" - name: git-config\n" +
|
||||
" colorArg: never\n" +
|
||||
" useExternalDiffGitConfig: TRUE\n" +
|
||||
" - name: git\n" +
|
||||
" colorArg: never\n" +
|
||||
" autoFetch: true\n",
|
||||
expected: "git:\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - name: delta\n" +
|
||||
" colorArg: never\n" +
|
||||
" command: delta --dark --paging=never\n" +
|
||||
" - name: difft\n" +
|
||||
" colorArg: never\n" +
|
||||
" command: difft --color=always\n" +
|
||||
" type: extDiff\n" +
|
||||
" - name: git-config\n" +
|
||||
" colorArg: never\n" +
|
||||
" type: extDiff\n" +
|
||||
" - name: git\n" +
|
||||
" colorArg: never\n" +
|
||||
" type: rawGit\n" +
|
||||
" autoFetch: true\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{
|
||||
"Renamed git.pagers to git.diffRenderers",
|
||||
"Renamed 'pager' to 'command' in git pager",
|
||||
"Changed 'externalDiffCommand' to 'command' with 'type: extDiff' in git pager",
|
||||
"Changed 'useExternalDiffGitConfig: true' to 'type: extDiff' in git pager",
|
||||
"Changed git pager without a command to 'type: rawGit'",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "zero-valued mechanism fields do not take precedence and are removed",
|
||||
input: "git:\n" +
|
||||
" pagers:\n" +
|
||||
" - pager: delta --dark --paging=never\n" +
|
||||
" externalDiffCommand: null\n" +
|
||||
" useExternalDiffGitConfig: false\n" +
|
||||
" - pager: \"\"\n" +
|
||||
" externalDiffCommand: difft --color=always\n" +
|
||||
" useExternalDiffGitConfig: false\n" +
|
||||
" - pager: null\n" +
|
||||
" externalDiffCommand: \"\"\n" +
|
||||
" useExternalDiffGitConfig: YES\n" +
|
||||
" - pager: \"\"\n" +
|
||||
" externalDiffCommand:\n" +
|
||||
" useExternalDiffGitConfig: false\n" +
|
||||
" - useExternalDiffGitConfig: null\n",
|
||||
expected: "git:\n" +
|
||||
" diffRenderers:\n" +
|
||||
" - command: delta --dark --paging=never\n" +
|
||||
" - command: difft --color=always\n" +
|
||||
" type: extDiff\n" +
|
||||
" - type: extDiff\n" +
|
||||
" - type: rawGit\n" +
|
||||
" - type: rawGit\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{
|
||||
"Renamed git.pagers to git.diffRenderers",
|
||||
"Renamed 'pager' to 'command' in git pager",
|
||||
"Removed empty 'externalDiffCommand' from git pager",
|
||||
"Removed 'useExternalDiffGitConfig: false' from git pager",
|
||||
"Changed 'externalDiffCommand' to 'command' with 'type: extDiff' in git pager",
|
||||
"Removed empty 'pager' from git pager",
|
||||
"Changed 'useExternalDiffGitConfig: true' to 'type: extDiff' in git pager",
|
||||
"Changed git pager without a command to 'type: rawGit'",
|
||||
"Removed empty 'useExternalDiffGitConfig' from git pager",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
159
pkg/config/diff_renderer_config_manager.go
Normal file
159
pkg/config/diff_renderer_config_manager.go
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type DiffRendererConfigManager struct {
|
||||
getUserConfig func() *UserConfig
|
||||
diffRendererIndex int
|
||||
}
|
||||
|
||||
type DiffRendererType int
|
||||
|
||||
const (
|
||||
DiffRendererType_StdinFilter DiffRendererType = iota
|
||||
DiffRendererType_ExtDiff
|
||||
DiffRendererType_RawGit
|
||||
)
|
||||
|
||||
func NewDiffRendererConfigManager(getUserConfig func() *UserConfig) *DiffRendererConfigManager {
|
||||
return &DiffRendererConfigManager{getUserConfig: getUserConfig}
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) currentDiffRendererConfig() *DiffRendererConfig {
|
||||
diffRenderers := self.getUserConfig().Git.DiffRenderers
|
||||
if len(diffRenderers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Guard against the diff renderer index being out of range, which can happen if the user
|
||||
// has removed diff renderers from their config file while lazygit is running.
|
||||
if self.diffRendererIndex >= len(diffRenderers) {
|
||||
self.diffRendererIndex = 0
|
||||
}
|
||||
|
||||
return &diffRenderers[self.diffRendererIndex]
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfig) getType() DiffRendererType {
|
||||
switch self.Type {
|
||||
case "stdinFilter", "":
|
||||
return DiffRendererType_StdinFilter
|
||||
case "extDiff":
|
||||
return DiffRendererType_ExtDiff
|
||||
case "rawGit":
|
||||
return DiffRendererType_RawGit
|
||||
}
|
||||
panic("invalid diff renderer type: " + self.Type)
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) GetDiffRendererType() DiffRendererType {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil {
|
||||
return DiffRendererType_RawGit
|
||||
}
|
||||
return currentDiffRendererConfig.getType()
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) GetStdinFilterCommand(width int) string {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil || currentDiffRendererConfig.getType() != DiffRendererType_StdinFilter {
|
||||
return ""
|
||||
}
|
||||
|
||||
templateValues := map[string]string{
|
||||
"columnWidth": strconv.Itoa(width/2 - 6),
|
||||
}
|
||||
|
||||
commandTemplate := string(currentDiffRendererConfig.Command)
|
||||
return utils.ResolvePlaceholderString(commandTemplate, templateValues)
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) GetColorArg() string {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil || currentDiffRendererConfig.getType() != DiffRendererType_StdinFilter {
|
||||
return "always"
|
||||
}
|
||||
|
||||
colorArg := currentDiffRendererConfig.ColorArg
|
||||
if colorArg == "" {
|
||||
return "always"
|
||||
}
|
||||
return colorArg
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) GetExternalDiffCommand(diffContext uint64) string {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil || currentDiffRendererConfig.getType() != DiffRendererType_ExtDiff {
|
||||
return ""
|
||||
}
|
||||
|
||||
templateValues := map[string]string{
|
||||
"diffContext": strconv.Itoa(int(diffContext)),
|
||||
}
|
||||
|
||||
return utils.ResolvePlaceholderString(string(currentDiffRendererConfig.Command), templateValues)
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) GetRawGitArgs() []string {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil || currentDiffRendererConfig.getType() != DiffRendererType_RawGit {
|
||||
return nil
|
||||
}
|
||||
return currentDiffRendererConfig.Args
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) CycleDiffRenderers() {
|
||||
self.diffRendererIndex = (self.diffRendererIndex + 1) % len(self.getUserConfig().Git.DiffRenderers)
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) CycleDiffRenderersBackward() {
|
||||
n := len(self.getUserConfig().Git.DiffRenderers)
|
||||
self.diffRendererIndex = (self.diffRendererIndex - 1 + n) % n
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfigManager) CurrentDiffRendererIndex() (int, int) {
|
||||
return self.diffRendererIndex, len(self.getUserConfig().Git.DiffRenderers)
|
||||
}
|
||||
|
||||
// CurrentDiffRendererName returns a name for the current diff renderer, suitable for showing
|
||||
// to the user.
|
||||
func (self *DiffRendererConfigManager) CurrentDiffRendererName(tr *i18n.TranslationSet) string {
|
||||
currentDiffRendererConfig := self.currentDiffRendererConfig()
|
||||
if currentDiffRendererConfig == nil {
|
||||
return tr.DefaultDiffRendererName
|
||||
}
|
||||
|
||||
if name := currentDiffRendererConfig.displayName(); name != "" {
|
||||
return name
|
||||
}
|
||||
|
||||
if currentDiffRendererConfig.getType() == DiffRendererType_ExtDiff && currentDiffRendererConfig.Command == "" {
|
||||
return tr.ExternalDiffDiffRendererName
|
||||
}
|
||||
|
||||
return tr.DefaultDiffRendererName
|
||||
}
|
||||
|
||||
func (self *DiffRendererConfig) displayName() string {
|
||||
if self.Name != "" {
|
||||
return self.Name
|
||||
}
|
||||
if self.getType() == DiffRendererType_RawGit && len(self.Args) > 0 {
|
||||
return self.Args[0]
|
||||
}
|
||||
return firstWord(string(self.Command))
|
||||
}
|
||||
|
||||
func firstWord(command string) string {
|
||||
fields := strings.Fields(command)
|
||||
if len(fields) == 0 {
|
||||
return ""
|
||||
}
|
||||
return fields[0]
|
||||
}
|
||||
96
pkg/config/diff_renderer_config_manager_test.go
Normal file
96
pkg/config/diff_renderer_config_manager_test.go
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCurrentDiffRendererName(t *testing.T) {
|
||||
tr := i18n.EnglishTranslationSet()
|
||||
|
||||
scenarios := []struct {
|
||||
name string
|
||||
diffRendererConfig DiffRendererConfig
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "explicit name takes precedence over the command",
|
||||
diffRendererConfig: DiffRendererConfig{Name: "delta side-by-side", Command: "delta --side-by-side"},
|
||||
expected: "delta side-by-side",
|
||||
},
|
||||
{
|
||||
name: "derived from the first word of the stdinFilter command",
|
||||
diffRendererConfig: DiffRendererConfig{Command: "delta --side-by-side"},
|
||||
expected: "delta",
|
||||
},
|
||||
{
|
||||
name: "surrounding whitespace in the command is ignored",
|
||||
diffRendererConfig: DiffRendererConfig{Command: " diff-so-fancy "},
|
||||
expected: "diff-so-fancy",
|
||||
},
|
||||
{
|
||||
name: "derived from the first word of the extDiff command",
|
||||
diffRendererConfig: DiffRendererConfig{Type: "extDiff", Command: "difft --color=always"},
|
||||
expected: "difft",
|
||||
},
|
||||
{
|
||||
name: "no name can be derived for external diff",
|
||||
diffRendererConfig: DiffRendererConfig{Type: "extDiff"},
|
||||
expected: tr.ExternalDiffDiffRendererName,
|
||||
},
|
||||
{
|
||||
name: "derived from first argument of rawGit args",
|
||||
diffRendererConfig: DiffRendererConfig{Type: "rawGit", Args: []string{"--color-words"}},
|
||||
expected: "--color-words",
|
||||
},
|
||||
{
|
||||
name: "no name can be derived for raw diff",
|
||||
diffRendererConfig: DiffRendererConfig{Type: "rawGit"},
|
||||
expected: tr.DefaultDiffRendererName,
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
userConfig := &UserConfig{}
|
||||
userConfig.Git.DiffRenderers = []DiffRendererConfig{s.diffRendererConfig}
|
||||
config := NewDiffRendererConfigManager(func() *UserConfig { return userConfig })
|
||||
|
||||
assert.Equal(t, s.expected, config.CurrentDiffRendererName(tr))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentDiffRendererNameWithoutDiffRenderers(t *testing.T) {
|
||||
config := NewDiffRendererConfigManager(func() *UserConfig { return &UserConfig{} })
|
||||
|
||||
tr := i18n.EnglishTranslationSet()
|
||||
assert.Equal(t, tr.DefaultDiffRendererName, config.CurrentDiffRendererName(tr))
|
||||
}
|
||||
|
||||
func TestCycleDiffRenderers(t *testing.T) {
|
||||
userConfig := &UserConfig{}
|
||||
userConfig.Git.DiffRenderers = []DiffRendererConfig{{Name: "a"}, {Name: "b"}, {Name: "c"}}
|
||||
config := NewDiffRendererConfigManager(func() *UserConfig { return userConfig })
|
||||
|
||||
currentIndex := func() int {
|
||||
index, _ := config.CurrentDiffRendererIndex()
|
||||
return index
|
||||
}
|
||||
|
||||
assert.Equal(t, 0, currentIndex())
|
||||
|
||||
config.CycleDiffRenderers()
|
||||
assert.Equal(t, 1, currentIndex())
|
||||
config.CycleDiffRenderers()
|
||||
assert.Equal(t, 2, currentIndex())
|
||||
config.CycleDiffRenderers()
|
||||
assert.Equal(t, 0, currentIndex(), "cycling forward past the last diff renderer wraps to the first")
|
||||
|
||||
config.CycleDiffRenderersBackward()
|
||||
assert.Equal(t, 2, currentIndex(), "cycling backward past the first diff renderer wraps to the last")
|
||||
config.CycleDiffRenderersBackward()
|
||||
assert.Equal(t, 1, currentIndex())
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type PagerConfig struct {
|
||||
getUserConfig func() *UserConfig
|
||||
pagerIndex int
|
||||
}
|
||||
|
||||
func NewPagerConfig(getUserConfig func() *UserConfig) *PagerConfig {
|
||||
return &PagerConfig{getUserConfig: getUserConfig}
|
||||
}
|
||||
|
||||
func (self *PagerConfig) currentPagerConfig() *PagingConfig {
|
||||
pagers := self.getUserConfig().Git.Pagers
|
||||
if len(pagers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Guard against the pager index being out of range, which can happen if the user
|
||||
// has removed pagers from their config file while lazygit is running.
|
||||
if self.pagerIndex >= len(pagers) {
|
||||
self.pagerIndex = 0
|
||||
}
|
||||
|
||||
return &pagers[self.pagerIndex]
|
||||
}
|
||||
|
||||
func (self *PagerConfig) GetPagerCommand(width int) string {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
if currentPagerConfig == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
templateValues := map[string]string{
|
||||
"columnWidth": strconv.Itoa(width/2 - 6),
|
||||
}
|
||||
|
||||
pagerTemplate := string(currentPagerConfig.Pager)
|
||||
return utils.ResolvePlaceholderString(pagerTemplate, templateValues)
|
||||
}
|
||||
|
||||
func (self *PagerConfig) GetColorArg() string {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
if currentPagerConfig == nil {
|
||||
return "always"
|
||||
}
|
||||
|
||||
colorArg := currentPagerConfig.ColorArg
|
||||
if colorArg == "" {
|
||||
return "always"
|
||||
}
|
||||
return colorArg
|
||||
}
|
||||
|
||||
func (self *PagerConfig) GetExternalDiffCommand(diffContext uint64) string {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
if currentPagerConfig == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
templateValues := map[string]string{
|
||||
"diffContext": strconv.Itoa(int(diffContext)),
|
||||
}
|
||||
|
||||
return utils.ResolvePlaceholderString(currentPagerConfig.ExternalDiffCommand, templateValues)
|
||||
}
|
||||
|
||||
func (self *PagerConfig) GetUseExternalDiffGitConfig() bool {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
if currentPagerConfig == nil {
|
||||
return false
|
||||
}
|
||||
return currentPagerConfig.UseExternalDiffGitConfig
|
||||
}
|
||||
|
||||
func (self *PagerConfig) CyclePagers() {
|
||||
self.pagerIndex = (self.pagerIndex + 1) % len(self.getUserConfig().Git.Pagers)
|
||||
}
|
||||
|
||||
func (self *PagerConfig) CyclePagersBackward() {
|
||||
n := len(self.getUserConfig().Git.Pagers)
|
||||
self.pagerIndex = (self.pagerIndex - 1 + n) % n
|
||||
}
|
||||
|
||||
func (self *PagerConfig) CurrentPagerIndex() (int, int) {
|
||||
return self.pagerIndex, len(self.getUserConfig().Git.Pagers)
|
||||
}
|
||||
|
||||
// CurrentPagerName returns a name for the current pager, suitable for showing
|
||||
// to the user. It returns an empty string if no name can be derived; callers
|
||||
// should substitute a localized fallback in that case.
|
||||
func (self *PagerConfig) CurrentPagerName() string {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
if currentPagerConfig == nil {
|
||||
return ""
|
||||
}
|
||||
return currentPagerConfig.displayName()
|
||||
}
|
||||
|
||||
// CurrentPagerUsesGitConfigDiff reports whether the current pager defers to
|
||||
// git's own external diff config. Such an entry has no name we can derive (the
|
||||
// actual command may even vary per file via .gitattributes), so callers show a
|
||||
// generic label rather than treating it like the default no-pager entry.
|
||||
func (self *PagerConfig) CurrentPagerUsesGitConfigDiff() bool {
|
||||
currentPagerConfig := self.currentPagerConfig()
|
||||
return currentPagerConfig != nil && currentPagerConfig.UseExternalDiffGitConfig
|
||||
}
|
||||
|
||||
func (self *PagingConfig) displayName() string {
|
||||
if self.Name != "" {
|
||||
return self.Name
|
||||
}
|
||||
if word := firstWord(string(self.Pager)); word != "" {
|
||||
return word
|
||||
}
|
||||
return firstWord(self.ExternalDiffCommand)
|
||||
}
|
||||
|
||||
func firstWord(command string) string {
|
||||
fields := strings.Fields(command)
|
||||
if len(fields) == 0 {
|
||||
return ""
|
||||
}
|
||||
return fields[0]
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCurrentPagerName(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
pager PagingConfig
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "explicit name takes precedence over the command",
|
||||
pager: PagingConfig{Name: "delta side-by-side", Pager: "delta --side-by-side"},
|
||||
expected: "delta side-by-side",
|
||||
},
|
||||
{
|
||||
name: "derived from the first word of the pager command",
|
||||
pager: PagingConfig{Pager: "delta --side-by-side"},
|
||||
expected: "delta",
|
||||
},
|
||||
{
|
||||
name: "surrounding whitespace in the command is ignored",
|
||||
pager: PagingConfig{Pager: " diff-so-fancy "},
|
||||
expected: "diff-so-fancy",
|
||||
},
|
||||
{
|
||||
name: "falls back to the external diff command when there is no pager",
|
||||
pager: PagingConfig{ExternalDiffCommand: "difft --color=always"},
|
||||
expected: "difft",
|
||||
},
|
||||
{
|
||||
name: "no name can be derived",
|
||||
pager: PagingConfig{UseExternalDiffGitConfig: true},
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
userConfig := &UserConfig{}
|
||||
userConfig.Git.Pagers = []PagingConfig{s.pager}
|
||||
config := NewPagerConfig(func() *UserConfig { return userConfig })
|
||||
|
||||
assert.Equal(t, s.expected, config.CurrentPagerName())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPagerNameWithoutPagers(t *testing.T) {
|
||||
config := NewPagerConfig(func() *UserConfig { return &UserConfig{} })
|
||||
|
||||
assert.Equal(t, "", config.CurrentPagerName())
|
||||
}
|
||||
|
||||
func TestCyclePagers(t *testing.T) {
|
||||
userConfig := &UserConfig{}
|
||||
userConfig.Git.Pagers = []PagingConfig{{Name: "a"}, {Name: "b"}, {Name: "c"}}
|
||||
config := NewPagerConfig(func() *UserConfig { return userConfig })
|
||||
|
||||
currentIndex := func() int {
|
||||
index, _ := config.CurrentPagerIndex()
|
||||
return index
|
||||
}
|
||||
|
||||
assert.Equal(t, 0, currentIndex())
|
||||
|
||||
config.CyclePagers()
|
||||
assert.Equal(t, 1, currentIndex())
|
||||
config.CyclePagers()
|
||||
assert.Equal(t, 2, currentIndex())
|
||||
config.CyclePagers()
|
||||
assert.Equal(t, 0, currentIndex(), "cycling forward past the last pager wraps to the first")
|
||||
|
||||
config.CyclePagersBackward()
|
||||
assert.Equal(t, 2, currentIndex(), "cycling backward past the first pager wraps to the last")
|
||||
config.CyclePagersBackward()
|
||||
assert.Equal(t, 1, currentIndex())
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ type GuiConfig struct {
|
|||
// One of: 'margin' (default) | 'jump'
|
||||
ScrollOffBehavior string `yaml:"scrollOffBehavior"`
|
||||
// The number of spaces per tab; used for everything that's shown in the main view, but probably mostly relevant for diffs.
|
||||
// Note that when using a pager, the pager has its own tab width setting, so you need to pass it separately in the pager command.
|
||||
// Note that when using a diff renderer, the renderer has its own tab width setting, so you need to pass it separately in the renderer command.
|
||||
TabWidth int `yaml:"tabWidth" jsonschema:"minimum=1"`
|
||||
// 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.
|
||||
|
|
@ -269,37 +269,39 @@ type SpinnerConfig struct {
|
|||
}
|
||||
|
||||
type GitConfig struct {
|
||||
// Array of pagers. Each entry has the following format:
|
||||
// [dev] The following documentation is duplicated from the PagingConfig struct below.
|
||||
// Array of diff renderers. Each entry has the following format:
|
||||
// [dev] The following documentation is duplicated from the DiffRendererConfig struct below.
|
||||
//
|
||||
// # A name for the pager, shown in the notification when cycling pagers.
|
||||
// # If not set, the name is derived from the first word of the pager
|
||||
// # command (or of the external diff command).
|
||||
// # The type of diff renderer. One of: 'stdinFilter' (default) | 'extDiff'
|
||||
// # | 'rawGit'
|
||||
// type: "stdinFilter"
|
||||
//
|
||||
// # A name for the diff renderer, shown in the notification when cycling
|
||||
// # renderers. If not set, the name is derived from the first word of the
|
||||
// # renderer command.
|
||||
// name: ""
|
||||
//
|
||||
// # 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'
|
||||
// # Value of the --color arg in the git diff command. Only used for type
|
||||
// # 'stdinFilter'. Some renderers want this to be set to 'always' and some
|
||||
// # want it set to 'never'.
|
||||
// colorArg: "always"
|
||||
//
|
||||
// # The command to use for rendering diffs. This is either a stdinFilter or
|
||||
// # an external diff command, depending on the type field; not applicable if
|
||||
// # the type is 'rawGit'.
|
||||
// # e.g.
|
||||
// # diff-so-fancy
|
||||
// # delta --dark --paging=never
|
||||
// # ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
// pager: ""
|
||||
// # ydiff -p cat
|
||||
// # difft --color=always
|
||||
// command: ""
|
||||
//
|
||||
// # e.g. 'difft --color=always'
|
||||
// externalDiffCommand: ""
|
||||
// # Extra arguments (array of strings) passed to the git command. Only
|
||||
// # applicable if the type is 'rawGit'.
|
||||
// args: []
|
||||
//
|
||||
// # If true, Lazygit will use git's `diff.external` config for paging.
|
||||
// # The advantage over `externalDiffCommand` is that this can be
|
||||
// # configured per file type in .gitattributes; see
|
||||
// # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
// useExternalDiffGitConfig: false
|
||||
//
|
||||
// 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually exclusive; set at most one per entry.
|
||||
//
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md for more information.
|
||||
Pagers []PagingConfig `yaml:"pagers"`
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_DiffRenderers.md for more information.
|
||||
DiffRenderers []DiffRendererConfig `yaml:"diffRenderers"`
|
||||
// Config relating to committing
|
||||
Commit CommitConfig `yaml:"commit"`
|
||||
// Config relating to merging
|
||||
|
|
@ -358,31 +360,34 @@ type GitConfig struct {
|
|||
TruncateCopiedCommitHashesTo int `yaml:"truncateCopiedCommitHashesTo"`
|
||||
}
|
||||
|
||||
type PagerType string
|
||||
type DiffRendererCommandType string
|
||||
|
||||
func (PagerType) JSONSchemaExtend(schema *jsonschema.Schema) {
|
||||
func (DiffRendererCommandType) JSONSchemaExtend(schema *jsonschema.Schema) {
|
||||
schema.Examples = []any{
|
||||
"delta --dark --paging=never",
|
||||
"diff-so-fancy",
|
||||
"ydiff -p cat -s --wrap --width={{columnWidth}}",
|
||||
"ydiff -p cat",
|
||||
"difft --color=always",
|
||||
}
|
||||
}
|
||||
|
||||
// [dev] This documentation is duplicated in the GitConfig struct. If you make changes here, make them there too.
|
||||
type PagingConfig struct {
|
||||
// A name for the pager, shown in the notification when cycling pagers. If not set, the name is derived from the first word of the pager command (or of the external diff command).
|
||||
type DiffRendererConfig struct {
|
||||
// The type of diff renderer. One of: 'stdinFilter' (default) | 'extDiff' | 'rawGit'
|
||||
Type string `yaml:"type" jsonschema:"enum=stdinFilter,enum=extDiff,enum=rawGit"`
|
||||
// A name for the diff renderer, shown in the notification when cycling renderers. If not set, the name is derived from the first word of the renderer command.
|
||||
Name string `yaml:"name"`
|
||||
// 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'
|
||||
// Value of the --color arg in the git diff command. Only used for type 'stdinFilter'. Some renderers want this to be set to 'always' and some want it set to 'never'.
|
||||
ColorArg string `yaml:"colorArg" jsonschema:"enum=always,enum=never"`
|
||||
// The command to use for rendering diffs. This is either a stdinFilter or an external diff command, depending on the type field; not applicable if the type is 'rawGit'.
|
||||
// e.g.
|
||||
// diff-so-fancy
|
||||
// delta --dark --paging=never
|
||||
// ydiff -p cat -s --wrap --width={{columnWidth}}
|
||||
Pager PagerType `yaml:"pager"`
|
||||
// e.g. 'difft --color=always'
|
||||
ExternalDiffCommand string `yaml:"externalDiffCommand"`
|
||||
// If true, Lazygit will use git's `diff.external` config for paging. The advantage over `externalDiffCommand` is that this can be configured per file type in .gitattributes; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
UseExternalDiffGitConfig bool `yaml:"useExternalDiffGitConfig"`
|
||||
// ydiff -p cat
|
||||
// difft --color=always
|
||||
Command DiffRendererCommandType `yaml:"command"`
|
||||
// Extra arguments (array of strings) passed to the git command. Only applicable if the type is 'rawGit'.
|
||||
Args []string `yaml:"args"`
|
||||
}
|
||||
|
||||
type CommitConfig struct {
|
||||
|
|
@ -524,23 +529,23 @@ type KeybindingUniversalConfig struct {
|
|||
// Deprecated: add the key to `scrollUpMain` instead.
|
||||
ScrollUpMainAlt2 Keybinding `yaml:"scrollUpMain-alt2"`
|
||||
// Deprecated: add the key to `scrollDownMain` instead.
|
||||
ScrollDownMainAlt2 Keybinding `yaml:"scrollDownMain-alt2"`
|
||||
ExecuteShellCommand Keybinding `yaml:"executeShellCommand"`
|
||||
CreateRebaseOptionsMenu Keybinding `yaml:"createRebaseOptionsMenu"`
|
||||
Push Keybinding `yaml:"pushFiles"` // 'Files' appended for legacy reasons
|
||||
Pull Keybinding `yaml:"pullFiles"` // 'Files' appended for legacy reasons
|
||||
Refresh Keybinding `yaml:"refresh"`
|
||||
CreatePatchOptionsMenu Keybinding `yaml:"createPatchOptionsMenu"`
|
||||
NextTab Keybinding `yaml:"nextTab"`
|
||||
PrevTab Keybinding `yaml:"prevTab"`
|
||||
NextScreenMode Keybinding `yaml:"nextScreenMode"`
|
||||
PrevScreenMode Keybinding `yaml:"prevScreenMode"`
|
||||
CyclePagers Keybinding `yaml:"cyclePagers"`
|
||||
CyclePagersReverse Keybinding `yaml:"cyclePagersReverse"`
|
||||
Undo Keybinding `yaml:"undo"`
|
||||
Redo Keybinding `yaml:"redo"`
|
||||
FilteringMenu Keybinding `yaml:"filteringMenu"`
|
||||
DiffingMenu Keybinding `yaml:"diffingMenu"`
|
||||
ScrollDownMainAlt2 Keybinding `yaml:"scrollDownMain-alt2"`
|
||||
ExecuteShellCommand Keybinding `yaml:"executeShellCommand"`
|
||||
CreateRebaseOptionsMenu Keybinding `yaml:"createRebaseOptionsMenu"`
|
||||
Push Keybinding `yaml:"pushFiles"` // 'Files' appended for legacy reasons
|
||||
Pull Keybinding `yaml:"pullFiles"` // 'Files' appended for legacy reasons
|
||||
Refresh Keybinding `yaml:"refresh"`
|
||||
CreatePatchOptionsMenu Keybinding `yaml:"createPatchOptionsMenu"`
|
||||
NextTab Keybinding `yaml:"nextTab"`
|
||||
PrevTab Keybinding `yaml:"prevTab"`
|
||||
NextScreenMode Keybinding `yaml:"nextScreenMode"`
|
||||
PrevScreenMode Keybinding `yaml:"prevScreenMode"`
|
||||
CycleDiffRenderers Keybinding `yaml:"cycleDiffRenderers"`
|
||||
CycleDiffRenderersReverse Keybinding `yaml:"cycleDiffRenderersReverse"`
|
||||
Undo Keybinding `yaml:"undo"`
|
||||
Redo Keybinding `yaml:"redo"`
|
||||
FilteringMenu Keybinding `yaml:"filteringMenu"`
|
||||
DiffingMenu Keybinding `yaml:"diffingMenu"`
|
||||
// Deprecated: add the key to `diffingMenu` instead.
|
||||
DiffingMenuAlt Keybinding `yaml:"diffingMenu-alt"`
|
||||
CopyToClipboard Keybinding `yaml:"copyToClipboard"`
|
||||
|
|
@ -1055,8 +1060,8 @@ func GetDefaultConfigForPlatform(platform string) *UserConfig {
|
|||
PrevTab: Keybinding{"["},
|
||||
NextScreenMode: Keybinding{"+"},
|
||||
PrevScreenMode: Keybinding{"_"},
|
||||
CyclePagers: Keybinding{"|"},
|
||||
CyclePagersReverse: Keybinding{"\\"},
|
||||
CycleDiffRenderers: Keybinding{"|"},
|
||||
CycleDiffRenderersReverse: Keybinding{"\\"},
|
||||
Undo: Keybinding{"z"},
|
||||
Redo: Keybinding{"Z"},
|
||||
FilteringMenu: Keybinding{"<ctrl+s>"},
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func (config *UserConfig) Validate() error {
|
|||
[]string{"always", "never", "when-maximised"}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validatePagers(config.Git.Pagers); err != nil {
|
||||
if err := validateDiffRenderers(config.Git.DiffRenderers); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateKeybindings(config.Keybinding); err != nil {
|
||||
|
|
@ -110,25 +110,26 @@ func validateSpinner(spinner SpinnerConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// validatePagers rejects pager entries that combine more than one diff
|
||||
// mechanism. A pager (GIT_PAGER) formats the diff that git produces, whereas
|
||||
// externalDiffCommand and useExternalDiffGitConfig change how git produces the
|
||||
// diff in the first place; piping one through the other almost always yields
|
||||
// garbled output, so we treat the three as mutually exclusive.
|
||||
func validatePagers(pagers []PagingConfig) error {
|
||||
for i, pager := range pagers {
|
||||
count := 0
|
||||
if pager.Pager != "" {
|
||||
count++
|
||||
}
|
||||
if pager.ExternalDiffCommand != "" {
|
||||
count++
|
||||
}
|
||||
if pager.UseExternalDiffGitConfig {
|
||||
count++
|
||||
}
|
||||
if count > 1 {
|
||||
return fmt.Errorf("git.pagers[%d]: at most one of 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' may be set; they are mutually exclusive", i)
|
||||
func validateDiffRenderers(diffRenderers []DiffRendererConfig) error {
|
||||
for _, diffRenderer := range diffRenderers {
|
||||
switch diffRenderer.Type {
|
||||
case "stdinFilter", "":
|
||||
if diffRenderer.Command == "" {
|
||||
return errors.New("git.diffRenderers: 'command' must be specified for diff renderer type 'stdinFilter'.")
|
||||
}
|
||||
if len(diffRenderer.Args) > 0 {
|
||||
return errors.New("git.diffRenderers: 'args' cannot be used with diff renderer type 'stdinFilter'.")
|
||||
}
|
||||
case "extDiff":
|
||||
if len(diffRenderer.Args) > 0 {
|
||||
return errors.New("git.diffRenderers: 'args' cannot be used with diff renderer type 'extDiff'.")
|
||||
}
|
||||
case "rawGit":
|
||||
if diffRenderer.Command != "" {
|
||||
return errors.New("git.diffRenderers: 'command' cannot be used with diff renderer type 'rawGit'.")
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("git.diffRenderers: unknown type '%s'. Allowed values: stdinFilter, extDiff, rawGit", diffRenderer.Type)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -361,26 +361,30 @@ func TestUserConfigValidate_sidePanels(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUserConfigValidate_pagers(t *testing.T) {
|
||||
func TestUserConfigValidate_diffRenderers(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
pager PagingConfig
|
||||
valid bool
|
||||
name string
|
||||
diffRenderer DiffRendererConfig
|
||||
valid bool
|
||||
}{
|
||||
{name: "empty", pager: PagingConfig{}, valid: true},
|
||||
{name: "pager only", pager: PagingConfig{Pager: "delta"}, valid: true},
|
||||
{name: "external diff command only", pager: PagingConfig{ExternalDiffCommand: "difft"}, valid: true},
|
||||
{name: "git config external diff only", pager: PagingConfig{UseExternalDiffGitConfig: true}, valid: true},
|
||||
{name: "pager and external diff command", pager: PagingConfig{Pager: "delta", ExternalDiffCommand: "difft"}, valid: false},
|
||||
{name: "pager and git config external diff", pager: PagingConfig{Pager: "delta", UseExternalDiffGitConfig: true}, valid: false},
|
||||
{name: "both external diff mechanisms", pager: PagingConfig{ExternalDiffCommand: "difft", UseExternalDiffGitConfig: true}, valid: false},
|
||||
{name: "all three", pager: PagingConfig{Pager: "delta", ExternalDiffCommand: "difft", UseExternalDiffGitConfig: true}, valid: false},
|
||||
{name: "stdinFilter with type default", diffRenderer: DiffRendererConfig{Command: "delta"}, valid: true},
|
||||
{name: "stdinFilter with explicit type", diffRenderer: DiffRendererConfig{Type: "stdinFilter", Command: "delta"}, valid: true},
|
||||
{name: "stdinFilter with explicit type", diffRenderer: DiffRendererConfig{Type: "stdinFilter"}, valid: false},
|
||||
{name: "stdinFilter with type default without command", diffRenderer: DiffRendererConfig{}, valid: false},
|
||||
{name: "stdinFilter with args", diffRenderer: DiffRendererConfig{Type: "stdinFilter", Command: "delta", Args: []string{"-x"}}, valid: false},
|
||||
{name: "external diff", diffRenderer: DiffRendererConfig{Type: "extDiff", Command: "difft"}, valid: true},
|
||||
{name: "external diff without command", diffRenderer: DiffRendererConfig{Type: "extDiff"}, valid: true},
|
||||
{name: "external diff with args", diffRenderer: DiffRendererConfig{Type: "extDiff", Command: "difft", Args: []string{"-x"}}, valid: false},
|
||||
{name: "raw git", diffRenderer: DiffRendererConfig{Type: "rawGit"}, valid: true},
|
||||
{name: "raw git with args", diffRenderer: DiffRendererConfig{Type: "rawGit", Args: []string{"-x"}}, valid: true},
|
||||
{name: "raw git with command", diffRenderer: DiffRendererConfig{Type: "rawGit", Command: "delta"}, valid: false},
|
||||
{name: "unknown type", diffRenderer: DiffRendererConfig{Type: "unknown"}, valid: false},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
config := GetDefaultConfig()
|
||||
config.Git.Pagers = []PagingConfig{s.pager}
|
||||
config.Git.DiffRenderers = []DiffRendererConfig{s.diffRenderer}
|
||||
err := config.Validate()
|
||||
|
||||
if s.valid {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
package constants
|
||||
|
||||
type Docs struct {
|
||||
CustomPagers string
|
||||
CustomCommands string
|
||||
CustomKeybindings string
|
||||
Keybindings string
|
||||
Undoing string
|
||||
Config string
|
||||
Tutorial string
|
||||
CustomPatchDemo string
|
||||
CustomDiffRenderers string
|
||||
CustomCommands string
|
||||
CustomKeybindings string
|
||||
Keybindings string
|
||||
Undoing string
|
||||
Config string
|
||||
Tutorial string
|
||||
CustomPatchDemo string
|
||||
}
|
||||
|
||||
var Links = struct {
|
||||
|
|
@ -25,13 +25,13 @@ var Links = struct {
|
|||
Discussions: "https://github.com/jesseduffield/lazygit/discussions",
|
||||
Releases: "https://github.com/jesseduffield/lazygit/releases",
|
||||
Docs: Docs{
|
||||
CustomPagers: "https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md",
|
||||
CustomKeybindings: "https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md",
|
||||
CustomCommands: "https://github.com/jesseduffield/lazygit/wiki/Custom-Commands-Compendium",
|
||||
Keybindings: "https://github.com/jesseduffield/lazygit/blob/%s/docs/keybindings",
|
||||
Undoing: "https://github.com/jesseduffield/lazygit/blob/master/docs/Undoing.md",
|
||||
Config: "https://github.com/jesseduffield/lazygit/blob/%s/docs/Config.md",
|
||||
Tutorial: "https://youtu.be/VDXvbHZYeKY",
|
||||
CustomPatchDemo: "https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches",
|
||||
CustomDiffRenderers: "https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_DiffRenderers.md",
|
||||
CustomKeybindings: "https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md",
|
||||
CustomCommands: "https://github.com/jesseduffield/lazygit/wiki/Custom-Commands-Compendium",
|
||||
Keybindings: "https://github.com/jesseduffield/lazygit/blob/%s/docs/keybindings",
|
||||
Undoing: "https://github.com/jesseduffield/lazygit/blob/master/docs/Undoing.md",
|
||||
Config: "https://github.com/jesseduffield/lazygit/blob/%s/docs/Config.md",
|
||||
Tutorial: "https://youtu.be/VDXvbHZYeKY",
|
||||
CustomPatchDemo: "https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches",
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ func (gui *Gui) getRandomTip() string {
|
|||
// links
|
||||
fmt.Sprintf(
|
||||
"If you want a git diff with syntax colouring, check out lazygit's integration with delta:\n%s",
|
||||
constants.Links.Docs.CustomPagers,
|
||||
constants.Links.Docs.CustomDiffRenderers,
|
||||
),
|
||||
fmt.Sprintf(
|
||||
"You can build your own custom menus and commands to run from within lazygit. For examples see:\n%s",
|
||||
|
|
|
|||
|
|
@ -62,18 +62,18 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type
|
|||
Description: self.c.Tr.PrevScreenMode,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.CyclePagers),
|
||||
Handler: opts.Guards.NoPopupPanel(self.cyclePagers),
|
||||
GetDisabledReason: self.canCyclePagers,
|
||||
Description: self.c.Tr.CyclePagers,
|
||||
Tooltip: self.c.Tr.CyclePagersTooltip,
|
||||
Keys: opts.GetKeys(opts.Config.Universal.CycleDiffRenderers),
|
||||
Handler: opts.Guards.NoPopupPanel(self.cycleDiffRenderers),
|
||||
GetDisabledReason: self.canCycleDiffRenderers,
|
||||
Description: self.c.Tr.CycleDiffRenderers,
|
||||
Tooltip: self.c.Tr.CycleDiffRenderersTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.CyclePagersReverse),
|
||||
Handler: opts.Guards.NoPopupPanel(self.cyclePagersBackward),
|
||||
GetDisabledReason: self.canCyclePagers,
|
||||
Description: self.c.Tr.CyclePagersReverse,
|
||||
Tooltip: self.c.Tr.CyclePagersReverseTooltip,
|
||||
Keys: opts.GetKeys(opts.Config.Universal.CycleDiffRenderersReverse),
|
||||
Handler: opts.Guards.NoPopupPanel(self.cycleDiffRenderersBackward),
|
||||
GetDisabledReason: self.canCycleDiffRenderers,
|
||||
Description: self.c.Tr.CycleDiffRenderersReverse,
|
||||
Tooltip: self.c.Tr.CycleDiffRenderersReverseTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Return),
|
||||
|
|
@ -170,21 +170,21 @@ func (self *GlobalController) prevScreenMode() error {
|
|||
return (&ScreenModeActions{c: self.c}).Prev()
|
||||
}
|
||||
|
||||
func (self *GlobalController) cyclePagers() error {
|
||||
self.c.State().GetPagerConfig().CyclePagers()
|
||||
self.onPagerChanged()
|
||||
func (self *GlobalController) cycleDiffRenderers() error {
|
||||
self.c.State().GetDiffRendererConfigManager().CycleDiffRenderers()
|
||||
self.onDiffRenderersChanged()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *GlobalController) cyclePagersBackward() error {
|
||||
self.c.State().GetPagerConfig().CyclePagersBackward()
|
||||
self.onPagerChanged()
|
||||
func (self *GlobalController) cycleDiffRenderersBackward() error {
|
||||
self.c.State().GetDiffRendererConfigManager().CycleDiffRenderersBackward()
|
||||
self.onDiffRenderersChanged()
|
||||
return nil
|
||||
}
|
||||
|
||||
// onPagerChanged re-renders the main view so the newly selected pager takes
|
||||
// effect, and shows a toast naming it.
|
||||
func (self *GlobalController) onPagerChanged() {
|
||||
// onDiffRenderersChanged re-renders the main view so the newly selected diff renderer
|
||||
// takes effect, and shows a toast naming it.
|
||||
func (self *GlobalController) onDiffRenderersChanged() {
|
||||
currentSide := self.c.Context().CurrentSide()
|
||||
currentKey := self.c.Context().Current().GetKey()
|
||||
if currentSide.GetKey() == currentKey ||
|
||||
|
|
@ -193,28 +193,21 @@ func (self *GlobalController) onPagerChanged() {
|
|||
currentSide.HandleRenderToMain()
|
||||
}
|
||||
|
||||
pagerConfig := self.c.State().GetPagerConfig()
|
||||
current, total := pagerConfig.CurrentPagerIndex()
|
||||
name := pagerConfig.CurrentPagerName()
|
||||
if name == "" {
|
||||
if pagerConfig.CurrentPagerUsesGitConfigDiff() {
|
||||
name = self.c.Tr.ExternalDiffPagerName
|
||||
} else {
|
||||
name = self.c.Tr.DefaultPagerName
|
||||
}
|
||||
}
|
||||
self.c.Toast(utils.ResolvePlaceholderString(self.c.Tr.SelectedPager, map[string]string{
|
||||
diffRendererConfigManager := self.c.State().GetDiffRendererConfigManager()
|
||||
current, total := diffRendererConfigManager.CurrentDiffRendererIndex()
|
||||
name := diffRendererConfigManager.CurrentDiffRendererName(self.c.Tr)
|
||||
self.c.Toast(utils.ResolvePlaceholderString(self.c.Tr.SelectedDiffRenderers, map[string]string{
|
||||
"name": name,
|
||||
"current": strconv.Itoa(current + 1),
|
||||
"total": strconv.Itoa(total),
|
||||
}))
|
||||
}
|
||||
|
||||
func (self *GlobalController) canCyclePagers() *types.DisabledReason {
|
||||
_, total := self.c.State().GetPagerConfig().CurrentPagerIndex()
|
||||
func (self *GlobalController) canCycleDiffRenderers() *types.DisabledReason {
|
||||
_, total := self.c.State().GetDiffRendererConfigManager().CurrentDiffRendererIndex()
|
||||
if total <= 1 {
|
||||
return &types.DisabledReason{
|
||||
Text: self.c.Tr.CyclePagersDisabledReason,
|
||||
Text: self.c.Tr.CycleDiffRenderersDisabledReason,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -42,9 +42,10 @@ func (self *ScreenModeActions) rerenderViewsWithScreenModeDependentContent() {
|
|||
}
|
||||
}
|
||||
|
||||
// Rerender the main view; for views that display a diff this is necessary in case a custom
|
||||
// pager depends on the width of the view. For other views it isn't needed, but we don't bother
|
||||
// making a distinction here, as rerendering the main view unnecessarily is not a big deal.
|
||||
// Rerender the main view; for views that display a diff this is necessary in case a custom diff
|
||||
// renderer depends on the width of the view. For other views it isn't needed, but we don't
|
||||
// bother making a distinction here, as rerendering the main view unnecessarily is not a big
|
||||
// deal.
|
||||
self.c.Context().CurrentSide().HandleRenderToMain()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ type Gui struct {
|
|||
// this is the state of the GUI for the current repo
|
||||
State *GuiRepoState
|
||||
|
||||
pagerConfig *config.PagerConfig
|
||||
diffRendererConfig *config.DiffRendererConfigManager
|
||||
|
||||
CustomCommandsClient *custom_commands.Client
|
||||
|
||||
|
|
@ -178,8 +178,8 @@ func (self *StateAccessor) GetRepoGeneration() int {
|
|||
return int(self.gui.repoGeneration.Load())
|
||||
}
|
||||
|
||||
func (self *StateAccessor) GetPagerConfig() *config.PagerConfig {
|
||||
return self.gui.pagerConfig
|
||||
func (self *StateAccessor) GetDiffRendererConfigManager() *config.DiffRendererConfigManager {
|
||||
return self.gui.diffRendererConfig
|
||||
}
|
||||
|
||||
func (self *StateAccessor) GetShowExtrasWindow() bool {
|
||||
|
|
@ -346,7 +346,7 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
|
|||
gui.gitVersion,
|
||||
gui.os,
|
||||
git_config.NewStdCachedGitConfig(gui.Log),
|
||||
gui.pagerConfig,
|
||||
gui.diffRendererConfig,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -859,7 +859,7 @@ func NewGui(
|
|||
gui.BackgroundRoutineMgr = &BackgroundRoutineMgr{gui: gui}
|
||||
gui.stateAccessor = &StateAccessor{gui: gui}
|
||||
|
||||
gui.pagerConfig = config.NewPagerConfig(func() *config.UserConfig { return gui.UserConfig() })
|
||||
gui.diffRendererConfig = config.NewDiffRendererConfigManager(func() *config.UserConfig { return gui.UserConfig() })
|
||||
|
||||
return gui, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func NewState(diff string, selectedLineIdx int, view *gocui.View, oldState *Stat
|
|||
// if we have clicked from the outside to focus the main view we'll pass in a non-negative line index so that we can instantly select that line
|
||||
if selectedLineIdx >= 0 {
|
||||
// Clamp to the number of wrapped view lines; index might be out of
|
||||
// bounds if a custom pager is being used which produces more lines
|
||||
// bounds if a custom diff renderer is being used which produces more lines
|
||||
selectedLineIdx = min(selectedLineIdx, len(viewLineIndices)-1)
|
||||
|
||||
selectMode = RANGE
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/tasks"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
|
|
@ -51,39 +52,32 @@ func (p ptyCmd) String() string { return p.cmd.String() }
|
|||
func (p ptyCmd) GetProcess() *os.Process { return p.process }
|
||||
|
||||
// Some commands need to output for a terminal to active certain behaviour.
|
||||
// For example, git won't invoke the GIT_PAGER env var unless it thinks it's
|
||||
// For example, git won't invoke the GIT_PAGER env var unless it thinks it's
|
||||
// talking to a terminal. We typically write cmd outputs straight to a view,
|
||||
// which is just an io.Reader. the pty package lets us wrap a command in a
|
||||
// pseudo-terminal meaning we'll get the behaviour we want from the underlying
|
||||
// command.
|
||||
func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error {
|
||||
width := view.InnerWidth()
|
||||
diffContext := gui.UserConfig().Git.DiffContextSize
|
||||
|
||||
// LAZYGIT_COLUMNS is documented in docs/Custom_Pagers.md for pager
|
||||
// scripts that can't query the terminal width directly. We set it on
|
||||
// every platform so those scripts remain portable.
|
||||
// Set LAZYGIT_COLUMNS for diff renderer scripts that can't query the terminal width directly.
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("LAZYGIT_COLUMNS=%d", width))
|
||||
|
||||
pager := gui.stateAccessor.GetPagerConfig().GetPagerCommand(width)
|
||||
externalDiffCommand := gui.stateAccessor.GetPagerConfig().GetExternalDiffCommand(diffContext)
|
||||
useExtDiffGitConfig := gui.stateAccessor.GetPagerConfig().GetUseExternalDiffGitConfig()
|
||||
|
||||
if pager == "" && externalDiffCommand == "" && !useExtDiffGitConfig {
|
||||
// If we're not using a custom pager nor external diff command, then we don't need to use a pty
|
||||
if gui.stateAccessor.GetDiffRendererConfigManager().GetDiffRendererType() == config.DiffRendererType_RawGit {
|
||||
// If we're not using a custom diff renderer, then we don't need to use a pty
|
||||
return gui.newCmdTask(view, cmd, prefix)
|
||||
}
|
||||
|
||||
// Run the pty after layout so that it gets the correct size
|
||||
gui.afterLayout(func() error {
|
||||
// Need to get the width and the pager again because the layout might have
|
||||
// Need to get the width and the pager command again because the layout might have
|
||||
// changed the size of the view
|
||||
width = view.InnerWidth()
|
||||
pager := gui.stateAccessor.GetPagerConfig().GetPagerCommand(width)
|
||||
pager := gui.stateAccessor.GetDiffRendererConfigManager().GetStdinFilterCommand(width)
|
||||
|
||||
cmdStr := strings.Join(cmd.Args, " ")
|
||||
|
||||
// This communicates to pagers that we're in a very simple
|
||||
// This communicates to diff renderers that we're in a very simple
|
||||
// terminal that they should not expect to have much capabilities.
|
||||
// Moving the cursor, clearing the screen, or querying for colors are among such "advanced" capabilities.
|
||||
// Context: https://github.com/jesseduffield/lazygit/issues/3419
|
||||
|
|
@ -102,7 +96,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
var p oscommands.Pty
|
||||
var fallbackPipe io.ReadCloser
|
||||
start := func() (tasks.Cmd, io.Reader) {
|
||||
// The pty (and pager) wrap to this width; apply it here, on the
|
||||
// The pty (and diff renderer) wrap to this width; apply it here, on the
|
||||
// task's goroutine once the previous task has stopped, so it doesn't
|
||||
// race that task's writes (see View.SetContentWidth).
|
||||
view.SetContentWidth(width)
|
||||
|
|
@ -110,7 +104,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
sp, err := oscommands.StartPty(cmd, cols, rows)
|
||||
if err != nil {
|
||||
gui.c.Log.Error(err)
|
||||
// Fall back to running the command without a pty: the pager is
|
||||
// Fall back to running the command without a pty: the diff renderer is
|
||||
// lost, but the command's output still renders.
|
||||
execCmd, pipe := startCmdWithPipe(cmd, gui.c.Log)
|
||||
fallbackPipe = pipe
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ type HasUrn interface {
|
|||
type IStateAccessor interface {
|
||||
GetRepoPathStack() *utils.StringStack
|
||||
GetRepoState() IRepoStateAccessor
|
||||
GetPagerConfig() *config.PagerConfig
|
||||
GetDiffRendererConfigManager() *config.DiffRendererConfigManager
|
||||
// tells us whether we're currently updating lazygit
|
||||
GetUpdating() bool
|
||||
SetUpdating(bool)
|
||||
|
|
|
|||
|
|
@ -612,14 +612,14 @@ type TranslationSet struct {
|
|||
ViewResetToUpstreamOptions string
|
||||
NextScreenMode string
|
||||
PrevScreenMode string
|
||||
CyclePagers string
|
||||
CyclePagersTooltip string
|
||||
CyclePagersReverse string
|
||||
CyclePagersReverseTooltip string
|
||||
CyclePagersDisabledReason string
|
||||
SelectedPager string
|
||||
DefaultPagerName string
|
||||
ExternalDiffPagerName string
|
||||
CycleDiffRenderers string
|
||||
CycleDiffRenderersTooltip string
|
||||
CycleDiffRenderersReverse string
|
||||
CycleDiffRenderersReverseTooltip string
|
||||
CycleDiffRenderersDisabledReason string
|
||||
SelectedDiffRenderers string
|
||||
DefaultDiffRendererName string
|
||||
ExternalDiffDiffRendererName string
|
||||
StartSearch string
|
||||
StartFilter string
|
||||
SelectRemoteRepository string
|
||||
|
|
@ -1767,14 +1767,14 @@ func EnglishTranslationSet() *TranslationSet {
|
|||
ViewResetToUpstreamOptions: "View upstream reset options",
|
||||
NextScreenMode: "Next screen mode (normal/half/fullscreen)",
|
||||
PrevScreenMode: "Prev screen mode",
|
||||
CyclePagers: "Cycle pagers",
|
||||
CyclePagersTooltip: "Choose the next pager in the list of configured pagers.",
|
||||
CyclePagersReverse: "Cycle pagers (reverse)",
|
||||
CyclePagersReverseTooltip: "Choose the previous pager in the list of configured pagers.",
|
||||
CyclePagersDisabledReason: "No other pagers configured",
|
||||
SelectedPager: "Pager: {{.name}} ({{.current}} of {{.total}})",
|
||||
DefaultPagerName: "(default)",
|
||||
ExternalDiffPagerName: "(external diff)",
|
||||
CycleDiffRenderers: "Cycle diff renderers",
|
||||
CycleDiffRenderersTooltip: "Choose the next renderer in the list of configured diff renderers.",
|
||||
CycleDiffRenderersReverse: "Cycle diff renderers (reverse)",
|
||||
CycleDiffRenderersReverseTooltip: "Choose the previous renderer in the list of configured diff renderers.",
|
||||
CycleDiffRenderersDisabledReason: "No other diff renderers configured",
|
||||
SelectedDiffRenderers: "Diff renderer: {{.name}} ({{.current}} of {{.total}})",
|
||||
DefaultDiffRendererName: "(default)",
|
||||
ExternalDiffDiffRendererName: "(external diff)",
|
||||
StartSearch: "Search the current view by text",
|
||||
StartFilter: "Filter the current view by text",
|
||||
SelectRemoteRepository: "Select base repository for pull requests",
|
||||
|
|
@ -2319,7 +2319,7 @@ keybinding:
|
|||
suspendApp: <disabled>
|
||||
redo: <ctrl+z>
|
||||
|
||||
- The 'git.paging.useConfig' option has been removed. If you were relying on it to configure your pager, you'll have to explicitly set the pager again using the 'git.paging.pager' option.
|
||||
- The 'git.paging.useConfig' option has been removed. If you were relying on it to configure your pager, you'll have to explicitly set the command again using the 'git.diffRenderers.*.command' option.
|
||||
`,
|
||||
"0.62.0": `- The default keybinding for submitting a commit from the commit description editor has changed from alt-enter to command-enter on Mac, or ctrl-enter on Linux and Windows; these are the same bindings that are used in many multi-line edit field situations, e.g. in GitHub comments. Unfortunately these are not supported by all terminals; see https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md#terminal-compatibility for more on that. If you want to revert this change, you can do so by adding the following to your config:
|
||||
|
||||
|
|
|
|||
50
pkg/integration/tests/diff/cycle_diff_renderers.go
Normal file
50
pkg/integration/tests/diff/cycle_diff_renderers.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var CycleDiffRenderers = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Cycle forwards and backwards through configured diff renderers",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.DiffRenderers = []config.DiffRendererConfig{
|
||||
// an explicit name overrides the derived one
|
||||
{Name: "custom name", Command: "cat"},
|
||||
// no name, so it's derived from the first word of the command
|
||||
{Command: "cat -n"},
|
||||
// rawGit derives it from the first argument if any
|
||||
{Type: "rawGit", Args: []string{"--color-words"}},
|
||||
// neither name nor command, so it falls back to the default label
|
||||
{Type: "rawGit"},
|
||||
}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateNCommits(1)
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Press(keys.Universal.CycleDiffRenderers)
|
||||
t.ExpectToast(Equals("Diff renderer: cat (2 of 4)"))
|
||||
|
||||
t.Views().Commits().Press(keys.Universal.CycleDiffRenderers)
|
||||
t.ExpectToast(Equals("Diff renderer: --color-words (3 of 4)"))
|
||||
|
||||
t.Views().Commits().Press(keys.Universal.CycleDiffRenderers)
|
||||
t.ExpectToast(Equals("Diff renderer: (default) (4 of 4)"))
|
||||
|
||||
// cycling forward past the last diff renderer wraps around to the first
|
||||
t.Views().Commits().Press(keys.Universal.CycleDiffRenderers)
|
||||
t.ExpectToast(Equals("Diff renderer: custom name (1 of 4)"))
|
||||
|
||||
// cycling backward past the first diff renderer wraps around to the last
|
||||
t.Views().Commits().Press(keys.Universal.CycleDiffRenderersReverse)
|
||||
t.ExpectToast(Equals("Diff renderer: (default) (4 of 4)"))
|
||||
|
||||
t.Views().Commits().Press(keys.Universal.CycleDiffRenderersReverse)
|
||||
t.ExpectToast(Equals("Diff renderer: --color-words (3 of 4)"))
|
||||
},
|
||||
})
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var CyclePagers = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Cycle forwards and backwards through configured pagers",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.Pagers = []config.PagingConfig{
|
||||
// an explicit name overrides the derived one
|
||||
{Name: "custom name", Pager: "cat"},
|
||||
// no name, so it's derived from the first word of the command
|
||||
{Pager: "cat -n"},
|
||||
// neither name nor command, so it falls back to the default label
|
||||
{},
|
||||
}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateNCommits(1)
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Press(keys.Universal.CyclePagers)
|
||||
t.ExpectToast(Equals("Pager: cat (2 of 3)"))
|
||||
|
||||
t.Views().Commits().Press(keys.Universal.CyclePagers)
|
||||
t.ExpectToast(Equals("Pager: (default) (3 of 3)"))
|
||||
|
||||
// cycling forward past the last pager wraps around to the first
|
||||
t.Views().Commits().Press(keys.Universal.CyclePagers)
|
||||
t.ExpectToast(Equals("Pager: custom name (1 of 3)"))
|
||||
|
||||
// cycling backward past the first pager wraps around to the last
|
||||
t.Views().Commits().Press(keys.Universal.CyclePagersReverse)
|
||||
t.ExpectToast(Equals("Pager: (default) (3 of 3)"))
|
||||
|
||||
t.Views().Commits().Press(keys.Universal.CyclePagersReverse)
|
||||
t.ExpectToast(Equals("Pager: cat (2 of 3)"))
|
||||
},
|
||||
})
|
||||
|
|
@ -218,7 +218,7 @@ var tests = []*components.IntegrationTest{
|
|||
demo.Undo,
|
||||
demo.WorktreeCreateFromBranches,
|
||||
diff.CopyToClipboard,
|
||||
diff.CyclePagers,
|
||||
diff.CycleDiffRenderers,
|
||||
diff.Diff,
|
||||
diff.DiffAndApplyPatch,
|
||||
diff.DiffCommits,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,23 @@ func RemoveKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Adds a string field to the given object. Caution: doesn't check for duplicate
|
||||
// keys, that's the caller's responsibility
|
||||
func AddStringKey(mappingNode *yaml.Node, key string, value string) {
|
||||
keyNode := &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: key,
|
||||
}
|
||||
valueNode := &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: value,
|
||||
}
|
||||
|
||||
mappingNode.Content = append(mappingNode.Content, keyNode, valueNode)
|
||||
}
|
||||
|
||||
// Walks a yaml document from the root node to the specified path, and then applies the transformation to that node.
|
||||
// If the requested path is not defined in the document, no changes are made to the document.
|
||||
func TransformNode(rootNode *yaml.Node, path []string, transform func(node *yaml.Node) error) error {
|
||||
|
|
|
|||
|
|
@ -314,14 +314,58 @@
|
|||
"type": "object",
|
||||
"description": "Custom icons for filenames and file extensions\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-files-icon--color"
|
||||
},
|
||||
"GitConfig": {
|
||||
"DiffRendererConfig": {
|
||||
"properties": {
|
||||
"pagers": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"stdinFilter",
|
||||
"extDiff",
|
||||
"rawGit"
|
||||
],
|
||||
"description": "The type of diff renderer. One of: 'stdinFilter' (default) | 'extDiff' | 'rawGit'"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A name for the diff renderer, shown in the notification when cycling renderers. If not set, the name is derived from the first word of the renderer command."
|
||||
},
|
||||
"colorArg": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"always",
|
||||
"never"
|
||||
],
|
||||
"description": "Value of the --color arg in the git diff command. Only used for type 'stdinFilter'. Some renderers want this to be set to 'always' and some want it set to 'never'."
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The command to use for rendering diffs. This is either a stdinFilter or an external diff command, depending on the type field; not applicable if the type is 'rawGit'.\ne.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat\ndifft --color=always",
|
||||
"examples": [
|
||||
"delta --dark --paging=never",
|
||||
"diff-so-fancy",
|
||||
"ydiff -p cat",
|
||||
"difft --color=always"
|
||||
]
|
||||
},
|
||||
"args": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/PagingConfig"
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Array of pagers. Each entry has the following format:\n\n # A name for the pager, shown in the notification when cycling pagers.\n # If not set, the name is derived from the first word of the pager\n # command (or of the external diff command).\n name: \"\"\n\n # Value of the --color arg in the git diff command. Some pagers want\n # this to be set to 'always' and some want it set to 'never'\n colorArg: \"always\"\n\n # e.g.\n # diff-so-fancy\n # delta --dark --paging=never\n # ydiff -p cat -s --wrap --width={{columnWidth}}\n pager: \"\"\n\n # e.g. 'difft --color=always'\n externalDiffCommand: \"\"\n\n # If true, Lazygit will use git's `diff.external` config for paging.\n # The advantage over `externalDiffCommand` is that this can be\n # configured per file type in .gitattributes; see\n # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.\n useExternalDiffGitConfig: false\n\n'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually exclusive; set at most one per entry.\n\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md for more information."
|
||||
"description": "Extra arguments (array of strings) passed to the git command. Only applicable if the type is 'rawGit'."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"GitConfig": {
|
||||
"properties": {
|
||||
"diffRenderers": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/DiffRendererConfig"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Array of diff renderers. Each entry has the following format:\n\n # The type of diff renderer. One of: 'stdinFilter' (default) | 'extDiff'\n # | 'rawGit'\n type: \"stdinFilter\"\n\n # A name for the diff renderer, shown in the notification when cycling\n # renderers. If not set, the name is derived from the first word of the\n # renderer command.\n name: \"\"\n\n # Value of the --color arg in the git diff command. Only used for type\n # 'stdinFilter'. Some renderers want this to be set to 'always' and some\n # want it set to 'never'.\n colorArg: \"always\"\n\n # The command to use for rendering diffs. This is either a stdinFilter or\n # an external diff command, depending on the type field; not applicable if\n # the type is 'rawGit'.\n # e.g.\n # diff-so-fancy\n # delta --dark --paging=never\n # ydiff -p cat\n # difft --color=always\n command: \"\"\n\n # Extra arguments (array of strings) passed to the git command. Only\n # applicable if the type is 'rawGit'.\n args: []\n\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_DiffRenderers.md for more information."
|
||||
},
|
||||
"commit": {
|
||||
"$ref": "#/$defs/CommitConfig",
|
||||
|
|
@ -535,7 +579,7 @@
|
|||
"tabWidth": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "The number of spaces per tab; used for everything that's shown in the main view, but probably mostly relevant for diffs.\nNote that when using a pager, the pager has its own tab width setting, so you need to pass it separately in the pager command.",
|
||||
"description": "The number of spaces per tab; used for everything that's shown in the main view, but probably mostly relevant for diffs.\nNote that when using a diff renderer, the renderer has its own tab width setting, so you need to pass it separately in the renderer command.",
|
||||
"default": 4
|
||||
},
|
||||
"mouseEvents": {
|
||||
|
|
@ -3163,7 +3207,7 @@
|
|||
],
|
||||
"default": "_"
|
||||
},
|
||||
"cyclePagers": {
|
||||
"cycleDiffRenderers": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
|
|
@ -3177,7 +3221,7 @@
|
|||
],
|
||||
"default": "|"
|
||||
},
|
||||
"cyclePagersReverse": {
|
||||
"cycleDiffRenderersReverse": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
|
|
@ -3544,41 +3588,6 @@
|
|||
"type": "object",
|
||||
"description": "Config relating to things outside of Lazygit like how files are opened, copying to clipboard, etc"
|
||||
},
|
||||
"PagingConfig": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "A name for the pager, shown in the notification when cycling pagers. If not set, the name is derived from the first word of the pager command (or of the external diff command)."
|
||||
},
|
||||
"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'"
|
||||
},
|
||||
"pager": {
|
||||
"type": "string",
|
||||
"description": "e.g.\ndiff-so-fancy\ndelta --dark --paging=never\nydiff -p cat -s --wrap --width={{columnWidth}}",
|
||||
"examples": [
|
||||
"delta --dark --paging=never",
|
||||
"diff-so-fancy",
|
||||
"ydiff -p cat -s --wrap --width={{columnWidth}}"
|
||||
]
|
||||
},
|
||||
"externalDiffCommand": {
|
||||
"type": "string",
|
||||
"description": "e.g. 'difft --color=always'"
|
||||
},
|
||||
"useExternalDiffGitConfig": {
|
||||
"type": "boolean",
|
||||
"description": "If true, Lazygit will use git's `diff.external` config for paging. The advantage over `externalDiffCommand` is that this can be configured per file type in .gitattributes; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"RefresherConfig": {
|
||||
"properties": {
|
||||
"refreshInterval": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue