mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-13 00:07:59 +02:00
Add range selection ability on list contexts (#3207)
- **PR Description** Issue: https://github.com/jesseduffield/lazygit/issues/3196 This PR adds the ability to select a range of items in list contexts. It does this in two ways: * Sticky range select: like what we already have in the staging view, you press 'v' to toggle range select and then use up/down keys to extend the range * Non-sticky range select: rather than explicitly toggling this on/off, you use shift+up/down to extend the range The PR adds the ability to range select in all list contexts, but it's up to individual actions to opt-in to supporting a range. This PR only supports it for copying a range of commits for cherry-picking. We can add more support iteratively so that we're not merging a single giant PR. For all actions requiring selection of a single-item, an error will be shown if a range is selected. Other use cases we want to support in the near future: * marking commits as pick/drop/fixup/squash/etc when mid-rebase * fixup/squash/drop when outside rebase * moving commits up/down (in or out of rebase) * staging/unstaging multiple files * discarding multiple files ## Updated keybindings Because the 'v' binding is now globally dedicated to toggling range select, I've changed the cherry-pick copy/paste keys from 'c' and 'v' to 'shift+C' and 'shift+V' respectively. I've also nullified the 'v' keybinding on the 'view divergence from upstream' option in the upstream options menu (conveniently it was the first option in the menu so you can press enter on it). ## Standardised range select display As a bonus, this PR standardises how we display a range select. We already had range select support in the patch explorer view and merge conflicts view, but they were directly rendering the highlighted selection (i.e. blue background colour) in the content written to the view, rather than tell the view which lines were selected and have the view highlight them itself. A convenient benefit here is that now the entire line is highlighted, including trailing space, rather than just the content of the line. Another convenient benefit is that our integration tests can now easily ask the view which lines are selected, rather than depending on the specific context, because the view keeps track of it. I've removed the selectedRangeBgColor config option because selectedLineBgColor should be fine. I don't see the need for two options, but tell me if you think otherwise. Also, another thing we're standardising on: hitting escape will cancel the range select, which in the staging/patch-building views means if you're selecting a range, you'll need to hit escape twice to exit out of the view. For consistency, we're also applying this logic if you have a hunk selected. I personally would much prefer this and have several times accidentally exited out of the view when trying to cancel a range select by pressing escape. In lazygit in general, 'escape' means 'exit out of the innermost mode' and I would consider range select to be a kind of mode. ## Sticky vs non-sticky range interaction Here's the state machine that explains how the sticky and non-sticky range select modes interact. Although users will typically pick one or the other, it's important to be clear on what the logic is if you swap between them: ``` (no range, press 'v') -> sticky range (no range, press arrow) -> no range (no range, press shift+arrow) -> nonsticky range (sticky range, press 'v') -> no range (sticky range, press arrow) -> sticky range (sticky range, press shift+arrow) -> nonsticky range (nonsticky range, press 'v') -> no range (nonsticky range, press arrow) -> no range (nonsticky range, press shift+arrow) -> nonsticky range ``` Also if you press escape in either range mode, it cancels the range select. ## Some implementation details * when the action involves toggling e.g. toggling cherry-pick copy or toggling staged, we decide what to do based on the selection: for example with staging: if there are any unstaged changes in the selection, we'll stage everything, otherwise we unstage everything. This is the logic we already had when staging individual directories. * we retain range selection if a view loses focus * where we previously set SetSelectedLineIdx all over the place (e.g. setting selected line idx to 0 when checking out a branch) we're now using SetSelection which also resets the range select. There are only a couple of places where we would still want to use SetSelectedLineIdx (e.g. when the user moves up/down a page, because they would want to retain range select in that case) - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [x] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [x] Docs (specifically `docs/Config.md`) have been updated if necessary * [ ] You've read through your own file changes for silly mistakes etc <!-- Be sure to name your PR with an imperative e.g. 'Add worktrees view' see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for examples -->
This commit is contained in:
commit
74e07080d0
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@ -13,9 +13,6 @@
|
|||||||
],
|
],
|
||||||
"hideSystemGoroutines": true,
|
"hideSystemGoroutines": true,
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"presentation": {
|
|
||||||
"hidden": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Tail Lazygit logs",
|
"name": "Tail Lazygit logs",
|
||||||
@ -28,9 +25,6 @@
|
|||||||
"--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"
|
"--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"
|
||||||
],
|
],
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"presentation": {
|
|
||||||
"hidden": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Attach to a running Lazygit",
|
"name": "Attach to a running Lazygit",
|
||||||
|
@ -122,7 +122,7 @@ You can also perform any these actions as a once-off (e.g. pressing `s` on a com
|
|||||||
|
|
||||||
### Cherry-pick
|
### Cherry-pick
|
||||||
|
|
||||||
Press `c` on a commit to copy it and press `v` to paste (cherry-pick) it.
|
Press `shift+c` on a commit to copy it and press `shift+v` to paste (cherry-pick) it.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -57,8 +57,6 @@ gui:
|
|||||||
- blue
|
- blue
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- blue # set to `default` to have no background colour
|
- blue # set to `default` to have no background colour
|
||||||
selectedRangeBgColor:
|
|
||||||
- blue
|
|
||||||
cherryPickedCommitBgColor:
|
cherryPickedCommitBgColor:
|
||||||
- cyan
|
- cyan
|
||||||
cherryPickedCommitFgColor:
|
cherryPickedCommitFgColor:
|
||||||
@ -201,6 +199,9 @@ keybinding:
|
|||||||
toggleWhitespaceInDiffView: '<c-w>'
|
toggleWhitespaceInDiffView: '<c-w>'
|
||||||
increaseContextInDiffView: '}'
|
increaseContextInDiffView: '}'
|
||||||
decreaseContextInDiffView: '{'
|
decreaseContextInDiffView: '{'
|
||||||
|
toggleRangeSelect: 'v'
|
||||||
|
rangeSelectUp: '<s-up>'
|
||||||
|
rangeSelectDown: '<s-down>'
|
||||||
status:
|
status:
|
||||||
checkForUpdate: 'u'
|
checkForUpdate: 'u'
|
||||||
recentRepos: '<enter>'
|
recentRepos: '<enter>'
|
||||||
@ -248,9 +249,8 @@ keybinding:
|
|||||||
amendToCommit: 'A'
|
amendToCommit: 'A'
|
||||||
pickCommit: 'p' # pick commit (when mid-rebase)
|
pickCommit: 'p' # pick commit (when mid-rebase)
|
||||||
revertCommit: 't'
|
revertCommit: 't'
|
||||||
cherryPickCopy: 'c'
|
cherryPickCopy: 'C'
|
||||||
cherryPickCopyRange: 'C'
|
pasteCommits: 'V'
|
||||||
pasteCommits: 'v'
|
|
||||||
tagCommit: 'T'
|
tagCommit: 'T'
|
||||||
checkoutCommit: '<space>'
|
checkoutCommit: '<space>'
|
||||||
resetCherryPick: '<c-R>'
|
resetCherryPick: '<c-R>'
|
||||||
@ -263,8 +263,6 @@ keybinding:
|
|||||||
commitFiles:
|
commitFiles:
|
||||||
checkoutCommitFile: 'c'
|
checkoutCommitFile: 'c'
|
||||||
main:
|
main:
|
||||||
toggleDragSelect: 'v'
|
|
||||||
toggleDragSelect-alt: 'V'
|
|
||||||
toggleSelectHunk: 'a'
|
toggleSelectHunk: 'a'
|
||||||
pickBothHunks: 'b'
|
pickBothHunks: 'b'
|
||||||
submodules:
|
submodules:
|
||||||
@ -389,15 +387,13 @@ The available attributes are:
|
|||||||
|
|
||||||
## Highlighting the selected line
|
## Highlighting the selected line
|
||||||
|
|
||||||
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` and `selectedRangeBgColor` keys to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
|
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` key to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
gui:
|
gui:
|
||||||
theme:
|
theme:
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- default
|
- default
|
||||||
selectedRangeBgColor:
|
|
||||||
- default
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use the reverse attribute like so:
|
You can also use the reverse attribute like so:
|
||||||
@ -407,8 +403,6 @@ gui:
|
|||||||
theme:
|
theme:
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- reverse
|
- reverse
|
||||||
selectedRangeBgColor:
|
|
||||||
- reverse
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Custom Author Color
|
## Custom Author Color
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
* [Configuration](./Config.md).
|
* [Configuration](./Config.md).
|
||||||
* [Custom Commands](./Custom_Command_Keybindings.md)
|
* [Custom Commands](./Custom_Command_Keybindings.md)
|
||||||
* [Custom Pagers](./Custom_Pagers.md)
|
* [Custom Pagers](./Custom_Pagers.md)
|
||||||
|
* [Dev docs](./dev)
|
||||||
* [Keybindings](./keybindings)
|
* [Keybindings](./keybindings)
|
||||||
* [Undo/Redo](./Undoing.md)
|
* [Undo/Redo](./Undoing.md)
|
||||||
|
* [Range Select](./Range_Select.md)
|
||||||
* [Searching/Filtering](./Searching.md)
|
* [Searching/Filtering](./Searching.md)
|
||||||
* [Stacked Branches](./Stacked_Branches.md)
|
* [Stacked Branches](./Stacked_Branches.md)
|
||||||
* [Dev docs](./dev)
|
|
||||||
|
14
docs/Range_Select.md
Normal file
14
docs/Range_Select.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Range Select
|
||||||
|
|
||||||
|
Some actions can be performed on a range of contiguous items. For example:
|
||||||
|
* staging multiple files at once
|
||||||
|
* squashing multiple commits at once
|
||||||
|
* copying (for cherry-pick) multiple commits at once
|
||||||
|
|
||||||
|
There are two ways to select a range of items:
|
||||||
|
1. Sticky range select: Press 'v' to toggle range select, then expand the selection using the up/down arrow key. To reset the selection, press 'v' again.
|
||||||
|
2. Non-sticky range select: Press shift+up or shift+down to expand the selection. To reset the selection, press up/down without shift.
|
||||||
|
|
||||||
|
The sticky option will be more familiar to vim users, and the second option will feel more natural to users who aren't used to doing things in a modal way.
|
||||||
|
|
||||||
|
In order to perform an action on a range of items, simply press the normal key for that action. If the action only works on individual items, it will raise an error. This is a new feature and the plan is to incrementally support range select for more and more actions. If there is an action you would like to support range select which currently does not, please raise an issue in the repo.
|
@ -58,6 +58,7 @@
|
|||||||
* `pkg/gui/gui_common.go`: defines gui-specific methods that all controllers and helpers have access to
|
* `pkg/gui/gui_common.go`: defines gui-specific methods that all controllers and helpers have access to
|
||||||
* `pkg/i18n/english.go`: defines the set of i18n strings and their English values
|
* `pkg/i18n/english.go`: defines the set of i18n strings and their English values
|
||||||
* `pkg/gui/controllers/helpers/refresh_helper.go`: manages refreshing of models. The refresh helper is typically invoked at the end of an action to re-load affected models from git (e.g. re-load branches after doing a git pull)
|
* `pkg/gui/controllers/helpers/refresh_helper.go`: manages refreshing of models. The refresh helper is typically invoked at the end of an action to re-load affected models from git (e.g. re-load branches after doing a git pull)
|
||||||
|
* `pkg/gui/controllers/quit_actions.go`: contains code that runs when you hit 'escape' on a view (assuming the view doesn't define its own escape handler)
|
||||||
* `vendor/github.com/jesseduffield/gocui/gui.go`: defines the gocui gui struct
|
* `vendor/github.com/jesseduffield/gocui/gui.go`: defines the gocui gui struct
|
||||||
* `vendor/github.com/jesseduffield/gocui/view.go`: defines the gocui view struct
|
* `vendor/github.com/jesseduffield/gocui/view.go`: defines the gocui view struct
|
||||||
|
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: Next page
|
<kbd>.</kbd>: Next page
|
||||||
<kbd><</kbd>: Scroll to top
|
<kbd><</kbd>: Scroll to top
|
||||||
<kbd>></kbd>: Scroll to bottom
|
<kbd>></kbd>: Scroll to bottom
|
||||||
|
<kbd>v</kbd>: Toggle range select
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: Search the current view by text
|
<kbd>/</kbd>: Search the current view by text
|
||||||
<kbd>H</kbd>: Scroll left
|
<kbd>H</kbd>: Scroll left
|
||||||
<kbd>L</kbd>: Scroll right
|
<kbd>L</kbd>: Scroll right
|
||||||
@ -85,7 +88,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
||||||
<kbd><c-j></kbd>: Move commit down one
|
<kbd><c-j></kbd>: Move commit down one
|
||||||
<kbd><c-k></kbd>: Move commit up one
|
<kbd><c-k></kbd>: Move commit up one
|
||||||
<kbd>v</kbd>: Paste commits (cherry-pick)
|
<kbd>V</kbd>: Paste commits (cherry-pick)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: Amend commit with staged changes
|
<kbd>A</kbd>: Amend commit with staged changes
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -98,8 +101,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
<kbd>C</kbd>: Copy commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
<kbd>/</kbd>: Search the current view by text
|
<kbd>/</kbd>: Search the current view by text
|
||||||
@ -196,8 +198,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<pre>
|
<pre>
|
||||||
<kbd><left></kbd>: Select previous hunk
|
<kbd><left></kbd>: Select previous hunk
|
||||||
<kbd><right></kbd>: Select next hunk
|
<kbd><right></kbd>: Select next hunk
|
||||||
<kbd>v</kbd>: Toggle drag select
|
<kbd>v</kbd>: Toggle range select
|
||||||
<kbd>V</kbd>: Toggle drag select
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Open file
|
<kbd>o</kbd>: Open file
|
||||||
@ -212,8 +213,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<pre>
|
<pre>
|
||||||
<kbd><left></kbd>: Select previous hunk
|
<kbd><left></kbd>: Select previous hunk
|
||||||
<kbd><right></kbd>: Select next hunk
|
<kbd><right></kbd>: Select next hunk
|
||||||
<kbd>v</kbd>: Toggle drag select
|
<kbd>v</kbd>: Toggle range select
|
||||||
<kbd>V</kbd>: Toggle drag select
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Open file
|
<kbd>o</kbd>: Open file
|
||||||
@ -247,8 +247,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
<kbd>C</kbd>: Copy commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View commits
|
<kbd><enter></kbd>: View commits
|
||||||
@ -315,8 +314,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
<kbd>C</kbd>: Copy commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: 次のページ
|
<kbd>.</kbd>: 次のページ
|
||||||
<kbd><</kbd>: 最上部までスクロール
|
<kbd><</kbd>: 最上部までスクロール
|
||||||
<kbd>></kbd>: 最下部までスクロール
|
<kbd>></kbd>: 最下部までスクロール
|
||||||
|
<kbd>v</kbd>: 範囲選択を切り替え
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: 検索を開始
|
<kbd>/</kbd>: 検索を開始
|
||||||
<kbd>H</kbd>: 左スクロール
|
<kbd>H</kbd>: 左スクロール
|
||||||
<kbd>L</kbd>: 右スクロール
|
<kbd>L</kbd>: 右スクロール
|
||||||
@ -67,8 +70,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
<kbd>o</kbd>: ブラウザでコミットを開く
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
<kbd>n</kbd>: コミットにブランチを作成
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
<kbd>C</kbd>: コミットをコピー (cherry-pick)
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
@ -104,7 +106,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
||||||
<kbd><c-j></kbd>: コミットを1つ下に移動
|
<kbd><c-j></kbd>: コミットを1つ下に移動
|
||||||
<kbd><c-k></kbd>: コミットを1つ上に移動
|
<kbd><c-k></kbd>: コミットを1つ上に移動
|
||||||
<kbd>v</kbd>: コミットを貼り付け (cherry-pick)
|
<kbd>V</kbd>: コミットを貼り付け (cherry-pick)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: ステージされた変更でamendコミット
|
<kbd>A</kbd>: ステージされた変更でamendコミット
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -117,8 +119,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
<kbd>o</kbd>: ブラウザでコミットを開く
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
<kbd>n</kbd>: コミットにブランチを作成
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
<kbd>C</kbd>: コミットをコピー (cherry-pick)
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
<kbd>/</kbd>: 検索を開始
|
<kbd>/</kbd>: 検索を開始
|
||||||
@ -270,7 +271,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 前のhunkを選択
|
<kbd><left></kbd>: 前のhunkを選択
|
||||||
<kbd><right></kbd>: 次のhunkを選択
|
<kbd><right></kbd>: 次のhunkを選択
|
||||||
<kbd>v</kbd>: 範囲選択を切り替え
|
<kbd>v</kbd>: 範囲選択を切り替え
|
||||||
<kbd>V</kbd>: 範囲選択を切り替え
|
|
||||||
<kbd>a</kbd>: Hunk選択を切り替え
|
<kbd>a</kbd>: Hunk選択を切り替え
|
||||||
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
||||||
<kbd>o</kbd>: ファイルを開く
|
<kbd>o</kbd>: ファイルを開く
|
||||||
@ -286,7 +286,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 前のhunkを選択
|
<kbd><left></kbd>: 前のhunkを選択
|
||||||
<kbd><right></kbd>: 次のhunkを選択
|
<kbd><right></kbd>: 次のhunkを選択
|
||||||
<kbd>v</kbd>: 範囲選択を切り替え
|
<kbd>v</kbd>: 範囲選択を切り替え
|
||||||
<kbd>V</kbd>: 範囲選択を切り替え
|
|
||||||
<kbd>a</kbd>: Hunk選択を切り替え
|
<kbd>a</kbd>: Hunk選択を切り替え
|
||||||
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
||||||
<kbd>o</kbd>: ファイルを開く
|
<kbd>o</kbd>: ファイルを開く
|
||||||
@ -347,8 +346,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
<kbd>o</kbd>: ブラウザでコミットを開く
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
<kbd>n</kbd>: コミットにブランチを作成
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
<kbd>C</kbd>: コミットをコピー (cherry-pick)
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: コミットを閲覧
|
<kbd><enter></kbd>: コミットを閲覧
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: 다음 페이지
|
<kbd>.</kbd>: 다음 페이지
|
||||||
<kbd><</kbd>: 맨 위로 스크롤
|
<kbd><</kbd>: 맨 위로 스크롤
|
||||||
<kbd>></kbd>: 맨 아래로 스크롤
|
<kbd>></kbd>: 맨 아래로 스크롤
|
||||||
|
<kbd>v</kbd>: 드래그 선택 전환
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: 검색 시작
|
<kbd>/</kbd>: 검색 시작
|
||||||
<kbd>H</kbd>: 우 스크롤
|
<kbd>H</kbd>: 우 스크롤
|
||||||
<kbd>L</kbd>: 좌 스크롤
|
<kbd>L</kbd>: 좌 스크롤
|
||||||
@ -54,8 +57,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
<kbd>C</kbd>: 커밋을 복사 (cherry-pick)
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 커밋 보기
|
<kbd><enter></kbd>: 커밋 보기
|
||||||
@ -85,8 +87,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
<kbd>C</kbd>: 커밋을 복사 (cherry-pick)
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
@ -141,7 +142,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 이전 hunk를 선택
|
<kbd><left></kbd>: 이전 hunk를 선택
|
||||||
<kbd><right></kbd>: 다음 hunk를 선택
|
<kbd><right></kbd>: 다음 hunk를 선택
|
||||||
<kbd>v</kbd>: 드래그 선택 전환
|
<kbd>v</kbd>: 드래그 선택 전환
|
||||||
<kbd>V</kbd>: 드래그 선택 전환
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
||||||
<kbd>o</kbd>: 파일 닫기
|
<kbd>o</kbd>: 파일 닫기
|
||||||
@ -157,7 +157,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 이전 hunk를 선택
|
<kbd><left></kbd>: 이전 hunk를 선택
|
||||||
<kbd><right></kbd>: 다음 hunk를 선택
|
<kbd><right></kbd>: 다음 hunk를 선택
|
||||||
<kbd>v</kbd>: 드래그 선택 전환
|
<kbd>v</kbd>: 드래그 선택 전환
|
||||||
<kbd>V</kbd>: 드래그 선택 전환
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
||||||
<kbd>o</kbd>: 파일 닫기
|
<kbd>o</kbd>: 파일 닫기
|
||||||
@ -269,7 +268,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
||||||
<kbd><c-j></kbd>: 커밋을 1개 아래로 이동
|
<kbd><c-j></kbd>: 커밋을 1개 아래로 이동
|
||||||
<kbd><c-k></kbd>: 커밋을 1개 위로 이동
|
<kbd><c-k></kbd>: 커밋을 1개 위로 이동
|
||||||
<kbd>v</kbd>: 커밋을 붙여넣기 (cherry-pick)
|
<kbd>V</kbd>: 커밋을 붙여넣기 (cherry-pick)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: Amend commit with staged changes
|
<kbd>A</kbd>: Amend commit with staged changes
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -282,8 +281,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
||||||
<kbd>g</kbd>: View reset options
|
<kbd>g</kbd>: View reset options
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
<kbd>C</kbd>: 커밋을 복사 (cherry-pick)
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View selected item's files
|
<kbd><enter></kbd>: View selected item's files
|
||||||
<kbd>/</kbd>: 검색 시작
|
<kbd>/</kbd>: 검색 시작
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: Volgende pagina
|
<kbd>.</kbd>: Volgende pagina
|
||||||
<kbd><</kbd>: Scroll naar boven
|
<kbd><</kbd>: Scroll naar boven
|
||||||
<kbd>></kbd>: Scroll naar beneden
|
<kbd>></kbd>: Scroll naar beneden
|
||||||
|
<kbd>v</kbd>: Toggle drag selecteer
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: Start met zoeken
|
<kbd>/</kbd>: Start met zoeken
|
||||||
<kbd>H</kbd>: Scroll left
|
<kbd>H</kbd>: Scroll left
|
||||||
<kbd>L</kbd>: Scroll right
|
<kbd>L</kbd>: Scroll right
|
||||||
@ -148,7 +151,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: Squash bovenstaande commits
|
<kbd>S</kbd>: Squash bovenstaande commits
|
||||||
<kbd><c-j></kbd>: Verplaats commit 1 naar beneden
|
<kbd><c-j></kbd>: Verplaats commit 1 naar beneden
|
||||||
<kbd><c-k></kbd>: Verplaats commit 1 naar boven
|
<kbd><c-k></kbd>: Verplaats commit 1 naar boven
|
||||||
<kbd>v</kbd>: Plak commits (cherry-pick)
|
<kbd>V</kbd>: Plak commits (cherry-pick)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: Wijzig commit met staged veranderingen
|
<kbd>A</kbd>: Wijzig commit met staged veranderingen
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -161,8 +164,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
<kbd>g</kbd>: Bekijk reset opties
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
<kbd>C</kbd>: Kopieer commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
||||||
<kbd>/</kbd>: Start met zoeken
|
<kbd>/</kbd>: Start met zoeken
|
||||||
@ -205,7 +207,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: Selecteer de vorige hunk
|
<kbd><left></kbd>: Selecteer de vorige hunk
|
||||||
<kbd><right></kbd>: Selecteer de volgende hunk
|
<kbd><right></kbd>: Selecteer de volgende hunk
|
||||||
<kbd>v</kbd>: Toggle drag selecteer
|
<kbd>v</kbd>: Toggle drag selecteer
|
||||||
<kbd>V</kbd>: Toggle drag selecteer
|
|
||||||
<kbd>a</kbd>: Toggle selecteer hunk
|
<kbd>a</kbd>: Toggle selecteer hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Open bestand
|
<kbd>o</kbd>: Open bestand
|
||||||
@ -225,8 +226,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
<kbd>g</kbd>: Bekijk reset opties
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
<kbd>C</kbd>: Kopieer commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Bekijk commits
|
<kbd><enter></kbd>: Bekijk commits
|
||||||
@ -266,7 +266,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: Selecteer de vorige hunk
|
<kbd><left></kbd>: Selecteer de vorige hunk
|
||||||
<kbd><right></kbd>: Selecteer de volgende hunk
|
<kbd><right></kbd>: Selecteer de volgende hunk
|
||||||
<kbd>v</kbd>: Toggle drag selecteer
|
<kbd>v</kbd>: Toggle drag selecteer
|
||||||
<kbd>V</kbd>: Toggle drag selecteer
|
|
||||||
<kbd>a</kbd>: Toggle selecteer hunk
|
<kbd>a</kbd>: Toggle selecteer hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Open bestand
|
<kbd>o</kbd>: Open bestand
|
||||||
@ -315,8 +314,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
<kbd>g</kbd>: Bekijk reset opties
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
<kbd>C</kbd>: Kopieer commit (cherry-pick)
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: Next page
|
<kbd>.</kbd>: Next page
|
||||||
<kbd><</kbd>: Scroll to top
|
<kbd><</kbd>: Scroll to top
|
||||||
<kbd>></kbd>: Scroll to bottom
|
<kbd>></kbd>: Scroll to bottom
|
||||||
|
<kbd>v</kbd>: Toggle range select
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: Search the current view by text
|
<kbd>/</kbd>: Search the current view by text
|
||||||
<kbd>H</kbd>: Scroll left
|
<kbd>H</kbd>: Scroll left
|
||||||
<kbd>L</kbd>: Scroll right
|
<kbd>L</kbd>: Scroll right
|
||||||
@ -69,7 +72,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
|
<kbd>S</kbd>: Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
|
||||||
<kbd><c-j></kbd>: Przenieś commit 1 w dół
|
<kbd><c-j></kbd>: Przenieś commit 1 w dół
|
||||||
<kbd><c-k></kbd>: Przenieś commit 1 w górę
|
<kbd><c-k></kbd>: Przenieś commit 1 w górę
|
||||||
<kbd>v</kbd>: Wklej commity (przebieranie)
|
<kbd>V</kbd>: Wklej commity (przebieranie)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: Popraw commit zmianami z poczekalni
|
<kbd>A</kbd>: Popraw commit zmianami z poczekalni
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -82,8 +85,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
<kbd>g</kbd>: Wyświetl opcje resetu
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
<kbd>C</kbd>: Kopiuj commit (przebieranie)
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Przeglądaj pliki commita
|
<kbd><enter></kbd>: Przeglądaj pliki commita
|
||||||
<kbd>/</kbd>: Search the current view by text
|
<kbd>/</kbd>: Search the current view by text
|
||||||
@ -127,8 +129,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<pre>
|
<pre>
|
||||||
<kbd><left></kbd>: Poprzedni kawałek
|
<kbd><left></kbd>: Poprzedni kawałek
|
||||||
<kbd><right></kbd>: Następny kawałek
|
<kbd><right></kbd>: Następny kawałek
|
||||||
<kbd>v</kbd>: Toggle drag select
|
<kbd>v</kbd>: Toggle range select
|
||||||
<kbd>V</kbd>: Toggle drag select
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Otwórz plik
|
<kbd>o</kbd>: Otwórz plik
|
||||||
@ -197,8 +198,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<pre>
|
<pre>
|
||||||
<kbd><left></kbd>: Poprzedni kawałek
|
<kbd><left></kbd>: Poprzedni kawałek
|
||||||
<kbd><right></kbd>: Następny kawałek
|
<kbd><right></kbd>: Następny kawałek
|
||||||
<kbd>v</kbd>: Toggle drag select
|
<kbd>v</kbd>: Toggle range select
|
||||||
<kbd>V</kbd>: Toggle drag select
|
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
<kbd>a</kbd>: Toggle select hunk
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
||||||
<kbd>o</kbd>: Otwórz plik
|
<kbd>o</kbd>: Otwórz plik
|
||||||
@ -224,8 +224,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
<kbd>g</kbd>: Wyświetl opcje resetu
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
<kbd>C</kbd>: Kopiuj commit (przebieranie)
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: View commits
|
<kbd><enter></kbd>: View commits
|
||||||
@ -308,8 +307,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: Open commit in browser
|
<kbd>o</kbd>: Open commit in browser
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
<kbd>n</kbd>: Create new branch off of commit
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
<kbd>g</kbd>: Wyświetl opcje resetu
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
<kbd>C</kbd>: Kopiuj commit (przebieranie)
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Przeglądaj pliki commita
|
<kbd><enter></kbd>: Przeglądaj pliki commita
|
||||||
|
@ -37,6 +37,9 @@ _Связки клавиш_
|
|||||||
<kbd>.</kbd>: Следующая страница
|
<kbd>.</kbd>: Следующая страница
|
||||||
<kbd><</kbd>: Пролистать наверх
|
<kbd><</kbd>: Пролистать наверх
|
||||||
<kbd>></kbd>: Прокрутить вниз
|
<kbd>></kbd>: Прокрутить вниз
|
||||||
|
<kbd>v</kbd>: Переключить выборку перетаскивания
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: Найти
|
<kbd>/</kbd>: Найти
|
||||||
<kbd>H</kbd>: Прокрутить влево
|
<kbd>H</kbd>: Прокрутить влево
|
||||||
<kbd>L</kbd>: Прокрутить вправо
|
<kbd>L</kbd>: Прокрутить вправо
|
||||||
@ -61,7 +64,6 @@ _Связки клавиш_
|
|||||||
<kbd><left></kbd>: Выбрать предыдущую часть
|
<kbd><left></kbd>: Выбрать предыдущую часть
|
||||||
<kbd><right></kbd>: Выбрать следующую часть
|
<kbd><right></kbd>: Выбрать следующую часть
|
||||||
<kbd>v</kbd>: Переключить выборку перетаскивания
|
<kbd>v</kbd>: Переключить выборку перетаскивания
|
||||||
<kbd>V</kbd>: Переключить выборку перетаскивания
|
|
||||||
<kbd>a</kbd>: Переключить выборку частей
|
<kbd>a</kbd>: Переключить выборку частей
|
||||||
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
||||||
<kbd>o</kbd>: Открыть файл
|
<kbd>o</kbd>: Открыть файл
|
||||||
@ -106,7 +108,6 @@ _Связки клавиш_
|
|||||||
<kbd><left></kbd>: Выбрать предыдущую часть
|
<kbd><left></kbd>: Выбрать предыдущую часть
|
||||||
<kbd><right></kbd>: Выбрать следующую часть
|
<kbd><right></kbd>: Выбрать следующую часть
|
||||||
<kbd>v</kbd>: Переключить выборку перетаскивания
|
<kbd>v</kbd>: Переключить выборку перетаскивания
|
||||||
<kbd>V</kbd>: Переключить выборку перетаскивания
|
|
||||||
<kbd>a</kbd>: Переключить выборку частей
|
<kbd>a</kbd>: Переключить выборку частей
|
||||||
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
||||||
<kbd>o</kbd>: Открыть файл
|
<kbd>o</kbd>: Открыть файл
|
||||||
@ -126,8 +127,7 @@ _Связки клавиш_
|
|||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
<kbd>o</kbd>: Открыть коммит в браузере
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
<kbd>g</kbd>: Просмотреть параметры сброса
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
<kbd>C</kbd>: Скопировать отобранные коммит (cherry-pick)
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Просмотреть коммиты
|
<kbd><enter></kbd>: Просмотреть коммиты
|
||||||
@ -152,7 +152,7 @@ _Связки клавиш_
|
|||||||
<kbd>S</kbd>: Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение)
|
<kbd>S</kbd>: Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение)
|
||||||
<kbd><c-j></kbd>: Переместить коммит вниз на один
|
<kbd><c-j></kbd>: Переместить коммит вниз на один
|
||||||
<kbd><c-k></kbd>: Переместить коммит вверх на один
|
<kbd><c-k></kbd>: Переместить коммит вверх на один
|
||||||
<kbd>v</kbd>: Вставить отобранные коммиты (cherry-pick)
|
<kbd>V</kbd>: Вставить отобранные коммиты (cherry-pick)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: Править последний коммит с проиндексированными изменениями
|
<kbd>A</kbd>: Править последний коммит с проиндексированными изменениями
|
||||||
<kbd>a</kbd>: Установить/убрать автора коммита
|
<kbd>a</kbd>: Установить/убрать автора коммита
|
||||||
@ -165,8 +165,7 @@ _Связки клавиш_
|
|||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
<kbd>o</kbd>: Открыть коммит в браузере
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
<kbd>g</kbd>: Просмотреть параметры сброса
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
<kbd>C</kbd>: Скопировать отобранные коммит (cherry-pick)
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
||||||
<kbd>/</kbd>: Найти
|
<kbd>/</kbd>: Найти
|
||||||
@ -223,8 +222,7 @@ _Связки клавиш_
|
|||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
<kbd>o</kbd>: Открыть коммит в браузере
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
<kbd>g</kbd>: Просмотреть параметры сброса
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
<kbd>C</kbd>: Скопировать отобранные коммит (cherry-pick)
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
|
||||||
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
||||||
|
@ -37,6 +37,9 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>.</kbd>: 下一页
|
<kbd>.</kbd>: 下一页
|
||||||
<kbd><</kbd>: 滚动到顶部
|
<kbd><</kbd>: 滚动到顶部
|
||||||
<kbd>></kbd>: 滚动到底部
|
<kbd>></kbd>: 滚动到底部
|
||||||
|
<kbd>v</kbd>: 切换拖动选择
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: 开始搜索
|
<kbd>/</kbd>: 开始搜索
|
||||||
<kbd>H</kbd>: 向左滚动
|
<kbd>H</kbd>: 向左滚动
|
||||||
<kbd>L</kbd>: 向右滚动
|
<kbd>L</kbd>: 向右滚动
|
||||||
@ -54,8 +57,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
<kbd>o</kbd>: 在浏览器中打开提交
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
<kbd>n</kbd>: 从提交创建新分支
|
||||||
<kbd>g</kbd>: 查看重置选项
|
<kbd>g</kbd>: 查看重置选项
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
<kbd>C</kbd>: 复制提交(拣选)
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
|
||||||
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 查看提交
|
<kbd><enter></kbd>: 查看提交
|
||||||
@ -109,8 +111,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
<kbd>o</kbd>: 在浏览器中打开提交
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
<kbd>n</kbd>: 从提交创建新分支
|
||||||
<kbd>g</kbd>: 查看重置选项
|
<kbd>g</kbd>: 查看重置选项
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
<kbd>C</kbd>: 复制提交(拣选)
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
|
||||||
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 查看提交的文件
|
<kbd><enter></kbd>: 查看提交的文件
|
||||||
@ -150,7 +151,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>S</kbd>: 压缩在所选提交之上的所有“fixup!”提交(自动压缩)
|
<kbd>S</kbd>: 压缩在所选提交之上的所有“fixup!”提交(自动压缩)
|
||||||
<kbd><c-j></kbd>: 下移提交
|
<kbd><c-j></kbd>: 下移提交
|
||||||
<kbd><c-k></kbd>: 上移提交
|
<kbd><c-k></kbd>: 上移提交
|
||||||
<kbd>v</kbd>: 粘贴提交(拣选)
|
<kbd>V</kbd>: 粘贴提交(拣选)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: 用已暂存的更改来修补提交
|
<kbd>A</kbd>: 用已暂存的更改来修补提交
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
<kbd>a</kbd>: Set/Reset commit author
|
||||||
@ -163,8 +164,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
<kbd>o</kbd>: 在浏览器中打开提交
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
<kbd>n</kbd>: 从提交创建新分支
|
||||||
<kbd>g</kbd>: 查看重置选项
|
<kbd>g</kbd>: 查看重置选项
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
<kbd>C</kbd>: 复制提交(拣选)
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 查看提交的文件
|
<kbd><enter></kbd>: 查看提交的文件
|
||||||
<kbd>/</kbd>: 开始搜索
|
<kbd>/</kbd>: 开始搜索
|
||||||
@ -229,7 +229,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 选择上一个区块
|
<kbd><left></kbd>: 选择上一个区块
|
||||||
<kbd><right></kbd>: 选择下一个区块
|
<kbd><right></kbd>: 选择下一个区块
|
||||||
<kbd>v</kbd>: 切换拖动选择
|
<kbd>v</kbd>: 切换拖动选择
|
||||||
<kbd>V</kbd>: 切换拖动选择
|
|
||||||
<kbd>a</kbd>: 切换选择区块
|
<kbd>a</kbd>: 切换选择区块
|
||||||
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
||||||
<kbd>o</kbd>: 打开文件
|
<kbd>o</kbd>: 打开文件
|
||||||
@ -274,7 +273,6 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
<kbd><left></kbd>: 选择上一个区块
|
<kbd><left></kbd>: 选择上一个区块
|
||||||
<kbd><right></kbd>: 选择下一个区块
|
<kbd><right></kbd>: 选择下一个区块
|
||||||
<kbd>v</kbd>: 切换拖动选择
|
<kbd>v</kbd>: 切换拖动选择
|
||||||
<kbd>V</kbd>: 切换拖动选择
|
|
||||||
<kbd>a</kbd>: 切换选择区块
|
<kbd>a</kbd>: 切换选择区块
|
||||||
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
||||||
<kbd>o</kbd>: 打开文件
|
<kbd>o</kbd>: 打开文件
|
||||||
|
@ -37,6 +37,9 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd>.</kbd>: 下一頁
|
<kbd>.</kbd>: 下一頁
|
||||||
<kbd><</kbd>: 捲動到頂部
|
<kbd><</kbd>: 捲動到頂部
|
||||||
<kbd>></kbd>: 捲動到底部
|
<kbd>></kbd>: 捲動到底部
|
||||||
|
<kbd>v</kbd>: 切換拖曳選擇
|
||||||
|
<kbd><s-down></kbd>: Range select down
|
||||||
|
<kbd><s-up></kbd>: Range select up
|
||||||
<kbd>/</kbd>: 開始搜尋
|
<kbd>/</kbd>: 開始搜尋
|
||||||
<kbd>H</kbd>: 向左捲動
|
<kbd>H</kbd>: 向左捲動
|
||||||
<kbd>L</kbd>: 向右捲動
|
<kbd>L</kbd>: 向右捲動
|
||||||
@ -54,8 +57,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
<kbd>n</kbd>: 從提交建立新分支
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
<kbd>g</kbd>: 檢視重設選項
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
<kbd>C</kbd>: 複製提交 (揀選)
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
|
||||||
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 檢視提交
|
<kbd><enter></kbd>: 檢視提交
|
||||||
@ -102,7 +104,6 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd><left></kbd>: 選擇上一段
|
<kbd><left></kbd>: 選擇上一段
|
||||||
<kbd><right></kbd>: 選擇下一段
|
<kbd><right></kbd>: 選擇下一段
|
||||||
<kbd>v</kbd>: 切換拖曳選擇
|
<kbd>v</kbd>: 切換拖曳選擇
|
||||||
<kbd>V</kbd>: 切換拖曳選擇
|
|
||||||
<kbd>a</kbd>: 切換選擇程式碼塊
|
<kbd>a</kbd>: 切換選擇程式碼塊
|
||||||
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
||||||
<kbd>o</kbd>: 開啟檔案
|
<kbd>o</kbd>: 開啟檔案
|
||||||
@ -124,7 +125,6 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd><left></kbd>: 選擇上一段
|
<kbd><left></kbd>: 選擇上一段
|
||||||
<kbd><right></kbd>: 選擇下一段
|
<kbd><right></kbd>: 選擇下一段
|
||||||
<kbd>v</kbd>: 切換拖曳選擇
|
<kbd>v</kbd>: 切換拖曳選擇
|
||||||
<kbd>V</kbd>: 切換拖曳選擇
|
|
||||||
<kbd>a</kbd>: 切換選擇程式碼塊
|
<kbd>a</kbd>: 切換選擇程式碼塊
|
||||||
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
||||||
<kbd>o</kbd>: 開啟檔案
|
<kbd>o</kbd>: 開啟檔案
|
||||||
@ -152,8 +152,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
<kbd>n</kbd>: 從提交建立新分支
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
<kbd>g</kbd>: 檢視重設選項
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
<kbd>C</kbd>: 複製提交 (揀選)
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
|
||||||
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 檢視所選項目的檔案
|
<kbd><enter></kbd>: 檢視所選項目的檔案
|
||||||
@ -193,7 +192,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd>S</kbd>: 壓縮上方所有的“fixup!”提交 (自動壓縮)
|
<kbd>S</kbd>: 壓縮上方所有的“fixup!”提交 (自動壓縮)
|
||||||
<kbd><c-j></kbd>: 向下移動提交
|
<kbd><c-j></kbd>: 向下移動提交
|
||||||
<kbd><c-k></kbd>: 向上移動提交
|
<kbd><c-k></kbd>: 向上移動提交
|
||||||
<kbd>v</kbd>: 貼上提交 (揀選)
|
<kbd>V</kbd>: 貼上提交 (揀選)
|
||||||
<kbd>B</kbd>: Mark commit as base commit for rebase
|
<kbd>B</kbd>: Mark commit as base commit for rebase
|
||||||
<kbd>A</kbd>: 使用已預存的更改修正提交
|
<kbd>A</kbd>: 使用已預存的更改修正提交
|
||||||
<kbd>a</kbd>: 設置/重設提交作者
|
<kbd>a</kbd>: 設置/重設提交作者
|
||||||
@ -206,8 +205,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
<kbd>n</kbd>: 從提交建立新分支
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
<kbd>g</kbd>: 檢視重設選項
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
<kbd>C</kbd>: 複製提交 (揀選)
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
|
||||||
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
<kbd><c-t></kbd>: Open external diff tool (git difftool)
|
||||||
<kbd><enter></kbd>: 檢視所選項目的檔案
|
<kbd><enter></kbd>: 檢視所選項目的檔案
|
||||||
<kbd>/</kbd>: 開始搜尋
|
<kbd>/</kbd>: 開始搜尋
|
||||||
|
6
go.mod
6
go.mod
@ -16,7 +16,7 @@ require (
|
|||||||
github.com/integrii/flaggy v1.4.0
|
github.com/integrii/flaggy v1.4.0
|
||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db
|
github.com/jesseduffield/gocui v0.3.1-0.20240118234343-2d41754af383
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
||||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||||
@ -74,8 +74,8 @@ require (
|
|||||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||||
golang.org/x/net v0.7.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.15.0 // indirect
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
golang.org/x/term v0.15.0 // indirect
|
golang.org/x/term v0.16.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
10
go.sum
10
go.sum
@ -187,8 +187,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
|
|||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db h1:ihJdYk85/XQLGiG3b6m8P2z+RUohRMtPmX74YR9IT8s=
|
github.com/jesseduffield/gocui v0.3.1-0.20240118234343-2d41754af383 h1:twcgVo+K7UTXwrsNtlCvTi8AyCp7CuBX//+j4wWkivQ=
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db/go.mod h1:9zkyjnUmdL3+sUknJrQy/3HweUu8mVln/3J2wRF/l8M=
|
github.com/jesseduffield/gocui v0.3.1-0.20240118234343-2d41754af383/go.mod h1:9zkyjnUmdL3+sUknJrQy/3HweUu8mVln/3J2wRF/l8M=
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
||||||
@ -469,13 +469,15 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
|
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||||
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -14,11 +14,6 @@ type patchPresenter struct {
|
|||||||
// if true, all following fields are ignored
|
// if true, all following fields are ignored
|
||||||
plain bool
|
plain bool
|
||||||
|
|
||||||
isFocused bool
|
|
||||||
// first line index for selected cursor range
|
|
||||||
firstLineIndex int
|
|
||||||
// last line index for selected cursor range
|
|
||||||
lastLineIndex int
|
|
||||||
// line indices for tagged lines (e.g. lines added to a custom patch)
|
// line indices for tagged lines (e.g. lines added to a custom patch)
|
||||||
incLineIndices *set.Set[int]
|
incLineIndices *set.Set[int]
|
||||||
}
|
}
|
||||||
@ -44,11 +39,6 @@ func formatRangePlain(patch *Patch, startIdx int, endIdx int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FormatViewOpts struct {
|
type FormatViewOpts struct {
|
||||||
IsFocused bool
|
|
||||||
// first line index for selected cursor range
|
|
||||||
FirstLineIndex int
|
|
||||||
// last line index for selected cursor range
|
|
||||||
LastLineIndex int
|
|
||||||
// line indices for tagged lines (e.g. lines added to a custom patch)
|
// line indices for tagged lines (e.g. lines added to a custom patch)
|
||||||
IncLineIndices *set.Set[int]
|
IncLineIndices *set.Set[int]
|
||||||
}
|
}
|
||||||
@ -63,9 +53,6 @@ func formatView(patch *Patch, opts FormatViewOpts) string {
|
|||||||
presenter := &patchPresenter{
|
presenter := &patchPresenter{
|
||||||
patch: patch,
|
patch: patch,
|
||||||
plain: false,
|
plain: false,
|
||||||
isFocused: opts.IsFocused,
|
|
||||||
firstLineIndex: opts.FirstLineIndex,
|
|
||||||
lastLineIndex: opts.LastLineIndex,
|
|
||||||
incLineIndices: includedLineIndices,
|
incLineIndices: includedLineIndices,
|
||||||
}
|
}
|
||||||
return presenter.format()
|
return presenter.format()
|
||||||
@ -112,7 +99,6 @@ func (self *patchPresenter) format() string {
|
|||||||
self.formatLineAux(
|
self.formatLineAux(
|
||||||
hunk.headerContext,
|
hunk.headerContext,
|
||||||
theme.DefaultTextColor,
|
theme.DefaultTextColor,
|
||||||
lineIdx,
|
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -139,23 +125,17 @@ func (self *patchPresenter) patchLineStyle(patchLine *PatchLine) style.TextStyle
|
|||||||
func (self *patchPresenter) formatLine(str string, textStyle style.TextStyle, index int) string {
|
func (self *patchPresenter) formatLine(str string, textStyle style.TextStyle, index int) string {
|
||||||
included := self.incLineIndices.Includes(index)
|
included := self.incLineIndices.Includes(index)
|
||||||
|
|
||||||
return self.formatLineAux(str, textStyle, index, included)
|
return self.formatLineAux(str, textStyle, included)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'selected' means you've got it highlighted with your cursor
|
// 'selected' means you've got it highlighted with your cursor
|
||||||
// 'included' means the line has been included in the patch (only applicable when
|
// 'included' means the line has been included in the patch (only applicable when
|
||||||
// building a patch)
|
// building a patch)
|
||||||
func (self *patchPresenter) formatLineAux(str string, textStyle style.TextStyle, index int, included bool) string {
|
func (self *patchPresenter) formatLineAux(str string, textStyle style.TextStyle, included bool) string {
|
||||||
if self.plain {
|
if self.plain {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
selected := self.isFocused && index >= self.firstLineIndex && index <= self.lastLineIndex
|
|
||||||
|
|
||||||
if selected {
|
|
||||||
textStyle = textStyle.MergeStyle(theme.SelectedRangeBgColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
firstCharStyle := textStyle
|
firstCharStyle := textStyle
|
||||||
if included {
|
if included {
|
||||||
firstCharStyle = firstCharStyle.MergeStyle(style.BgGreen)
|
firstCharStyle = firstCharStyle.MergeStyle(style.BgGreen)
|
||||||
|
@ -197,9 +197,7 @@ func (p *PatchBuilder) RenderPatchForFile(filename string, plain bool, reverse b
|
|||||||
if plain {
|
if plain {
|
||||||
return patch.FormatPlain()
|
return patch.FormatPlain()
|
||||||
} else {
|
} else {
|
||||||
return patch.FormatView(FormatViewOpts{
|
return patch.FormatView(FormatViewOpts{})
|
||||||
IsFocused: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,9 +154,6 @@ type ThemeConfig struct {
|
|||||||
// Background color of selected line.
|
// Background color of selected line.
|
||||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
|
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
|
||||||
SelectedLineBgColor []string `yaml:"selectedLineBgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
SelectedLineBgColor []string `yaml:"selectedLineBgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
||||||
// Background color of selected range
|
|
||||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
|
|
||||||
SelectedRangeBgColor []string `yaml:"selectedRangeBgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
|
||||||
// Foreground color of copied commit
|
// Foreground color of copied commit
|
||||||
CherryPickedCommitFgColor []string `yaml:"cherryPickedCommitFgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
CherryPickedCommitFgColor []string `yaml:"cherryPickedCommitFgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
||||||
// Background color of copied commit
|
// Background color of copied commit
|
||||||
@ -304,6 +301,9 @@ type KeybindingUniversalConfig struct {
|
|||||||
ScrollRight string `yaml:"scrollRight"`
|
ScrollRight string `yaml:"scrollRight"`
|
||||||
GotoTop string `yaml:"gotoTop"`
|
GotoTop string `yaml:"gotoTop"`
|
||||||
GotoBottom string `yaml:"gotoBottom"`
|
GotoBottom string `yaml:"gotoBottom"`
|
||||||
|
ToggleRangeSelect string `yaml:"toggleRangeSelect"`
|
||||||
|
RangeSelectDown string `yaml:"rangeSelectDown"`
|
||||||
|
RangeSelectUp string `yaml:"rangeSelectUp"`
|
||||||
PrevBlock string `yaml:"prevBlock"`
|
PrevBlock string `yaml:"prevBlock"`
|
||||||
NextBlock string `yaml:"nextBlock"`
|
NextBlock string `yaml:"nextBlock"`
|
||||||
PrevBlockAlt string `yaml:"prevBlock-alt"`
|
PrevBlockAlt string `yaml:"prevBlock-alt"`
|
||||||
@ -418,7 +418,6 @@ type KeybindingCommitsConfig struct {
|
|||||||
PickCommit string `yaml:"pickCommit"`
|
PickCommit string `yaml:"pickCommit"`
|
||||||
RevertCommit string `yaml:"revertCommit"`
|
RevertCommit string `yaml:"revertCommit"`
|
||||||
CherryPickCopy string `yaml:"cherryPickCopy"`
|
CherryPickCopy string `yaml:"cherryPickCopy"`
|
||||||
CherryPickCopyRange string `yaml:"cherryPickCopyRange"`
|
|
||||||
PasteCommits string `yaml:"pasteCommits"`
|
PasteCommits string `yaml:"pasteCommits"`
|
||||||
MarkCommitAsBaseForRebase string `yaml:"markCommitAsBaseForRebase"`
|
MarkCommitAsBaseForRebase string `yaml:"markCommitAsBaseForRebase"`
|
||||||
CreateTag string `yaml:"tagCommit"`
|
CreateTag string `yaml:"tagCommit"`
|
||||||
@ -441,11 +440,9 @@ type KeybindingCommitFilesConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KeybindingMainConfig struct {
|
type KeybindingMainConfig struct {
|
||||||
ToggleDragSelect string `yaml:"toggleDragSelect"`
|
ToggleSelectHunk string `yaml:"toggleSelectHunk"`
|
||||||
ToggleDragSelectAlt string `yaml:"toggleDragSelect-alt"`
|
PickBothHunks string `yaml:"pickBothHunks"`
|
||||||
ToggleSelectHunk string `yaml:"toggleSelectHunk"`
|
EditSelectHunk string `yaml:"editSelectHunk"`
|
||||||
PickBothHunks string `yaml:"pickBothHunks"`
|
|
||||||
EditSelectHunk string `yaml:"editSelectHunk"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeybindingSubmodulesConfig struct {
|
type KeybindingSubmodulesConfig struct {
|
||||||
@ -621,7 +618,6 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
InactiveBorderColor: []string{"default"},
|
InactiveBorderColor: []string{"default"},
|
||||||
OptionsTextColor: []string{"blue"},
|
OptionsTextColor: []string{"blue"},
|
||||||
SelectedLineBgColor: []string{"blue"},
|
SelectedLineBgColor: []string{"blue"},
|
||||||
SelectedRangeBgColor: []string{"blue"},
|
|
||||||
CherryPickedCommitBgColor: []string{"cyan"},
|
CherryPickedCommitBgColor: []string{"cyan"},
|
||||||
CherryPickedCommitFgColor: []string{"blue"},
|
CherryPickedCommitFgColor: []string{"blue"},
|
||||||
MarkedBaseCommitBgColor: []string{"yellow"},
|
MarkedBaseCommitBgColor: []string{"yellow"},
|
||||||
@ -704,6 +700,9 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
ScrollRight: "L",
|
ScrollRight: "L",
|
||||||
GotoTop: "<",
|
GotoTop: "<",
|
||||||
GotoBottom: ">",
|
GotoBottom: ">",
|
||||||
|
ToggleRangeSelect: "v",
|
||||||
|
RangeSelectDown: "<s-down>",
|
||||||
|
RangeSelectUp: "<s-up>",
|
||||||
PrevBlock: "<left>",
|
PrevBlock: "<left>",
|
||||||
NextBlock: "<right>",
|
NextBlock: "<right>",
|
||||||
PrevBlockAlt: "h",
|
PrevBlockAlt: "h",
|
||||||
@ -812,9 +811,8 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
ResetCommitAuthor: "a",
|
ResetCommitAuthor: "a",
|
||||||
PickCommit: "p",
|
PickCommit: "p",
|
||||||
RevertCommit: "t",
|
RevertCommit: "t",
|
||||||
CherryPickCopy: "c",
|
CherryPickCopy: "C",
|
||||||
CherryPickCopyRange: "C",
|
PasteCommits: "V",
|
||||||
PasteCommits: "v",
|
|
||||||
MarkCommitAsBaseForRebase: "B",
|
MarkCommitAsBaseForRebase: "B",
|
||||||
CreateTag: "T",
|
CreateTag: "T",
|
||||||
CheckoutCommit: "<space>",
|
CheckoutCommit: "<space>",
|
||||||
@ -833,11 +831,9 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
CheckoutCommitFile: "c",
|
CheckoutCommitFile: "c",
|
||||||
},
|
},
|
||||||
Main: KeybindingMainConfig{
|
Main: KeybindingMainConfig{
|
||||||
ToggleDragSelect: "v",
|
ToggleSelectHunk: "a",
|
||||||
ToggleDragSelectAlt: "V",
|
PickBothHunks: "b",
|
||||||
ToggleSelectHunk: "a",
|
EditSelectHunk: "E",
|
||||||
PickBothHunks: "b",
|
|
||||||
EditSelectHunk: "E",
|
|
||||||
},
|
},
|
||||||
Submodules: KeybindingSubmodulesConfig{
|
Submodules: KeybindingSubmodulesConfig{
|
||||||
Init: "i",
|
Init: "i",
|
||||||
|
@ -63,7 +63,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
||||||
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
|
ctx.GetList().SetSelection(selectedLineIdx)
|
||||||
return ctx.HandleFocus(types.OnFocusOpts{})
|
return ctx.HandleFocus(types.OnFocusOpts{})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -31,5 +31,5 @@ func (self *FilteredListViewModel[T]) ClearFilter() {
|
|||||||
|
|
||||||
self.FilteredList.ClearFilter()
|
self.FilteredList.ClearFilter()
|
||||||
|
|
||||||
self.SetSelectedLineIdx(unfilteredIndex)
|
self.SetSelection(unfilteredIndex)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,14 @@ func (self *ListContextTrait) FocusLine() {
|
|||||||
self.GetViewTrait().FocusPoint(
|
self.GetViewTrait().FocusPoint(
|
||||||
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()))
|
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()))
|
||||||
|
|
||||||
|
selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
|
||||||
|
if isSelectingRange {
|
||||||
|
selectRangeIndex = self.ModelIndexToViewIndex(selectRangeIndex)
|
||||||
|
self.GetViewTrait().SetRangeSelectStart(selectRangeIndex)
|
||||||
|
} else {
|
||||||
|
self.GetViewTrait().CancelRangeSelect()
|
||||||
|
}
|
||||||
|
|
||||||
// If FocusPoint() caused the view to scroll (because the selected line
|
// If FocusPoint() caused the view to scroll (because the selected line
|
||||||
// was out of view before), we need to rerender the view port again.
|
// was out of view before), we need to rerender the view port again.
|
||||||
// This can happen when pressing , or . to scroll by pages, or < or > to
|
// This can happen when pressing , or . to scroll by pages, or < or > to
|
||||||
@ -84,7 +92,7 @@ func (self *ListContextTrait) HandleFocusLost(opts types.OnFocusLostOpts) error
|
|||||||
|
|
||||||
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
|
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
|
||||||
func (self *ListContextTrait) HandleRender() error {
|
func (self *ListContextTrait) HandleRender() error {
|
||||||
self.list.RefreshSelectedIdx()
|
self.list.ClampSelection()
|
||||||
content := self.renderLines(-1, -1)
|
content := self.renderLines(-1, -1)
|
||||||
self.GetViewTrait().SetContent(content)
|
self.GetViewTrait().SetContent(content)
|
||||||
self.c.Render()
|
self.c.Render()
|
||||||
@ -94,7 +102,7 @@ func (self *ListContextTrait) HandleRender() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
|
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
|
||||||
self.GetList().SetSelectedLineIdx(selectedLineIdx)
|
self.GetList().SetSelection(selectedLineIdx)
|
||||||
return self.HandleFocus(types.OnFocusOpts{})
|
return self.HandleFocus(types.OnFocusOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,3 +118,8 @@ func (self *ListContextTrait) IsItemVisible(item types.HasUrn) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// By default, list contexts supporta range select
|
||||||
|
func (self *ListContextTrait) RangeSelectEnabled() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -85,7 +85,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
||||||
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
|
ctx.GetList().SetSelection(selectedLineIdx)
|
||||||
return ctx.HandleFocus(types.OnFocusOpts{})
|
return ctx.HandleFocus(types.OnFocusOpts{})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -195,3 +195,8 @@ func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is currently no need to use range-select in a menu so we're disabling it.
|
||||||
|
func (self *MenuContext) RangeSelectEnabled() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -68,8 +68,8 @@ func (self *MergeConflictsContext) IsUserScrolling() bool {
|
|||||||
return self.viewModel.userVerticalScrolling
|
return self.viewModel.userVerticalScrolling
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) RenderAndFocus(isFocused bool) error {
|
func (self *MergeConflictsContext) RenderAndFocus() error {
|
||||||
self.setContent(isFocused)
|
self.setContent()
|
||||||
self.FocusSelection()
|
self.FocusSelection()
|
||||||
|
|
||||||
self.c.Render()
|
self.c.Render()
|
||||||
@ -77,30 +77,41 @@ func (self *MergeConflictsContext) RenderAndFocus(isFocused bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) Render(isFocused bool) error {
|
func (self *MergeConflictsContext) Render() error {
|
||||||
self.setContent(isFocused)
|
self.setContent()
|
||||||
|
|
||||||
self.c.Render()
|
self.c.Render()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) GetContentToRender(isFocused bool) string {
|
func (self *MergeConflictsContext) GetContentToRender() string {
|
||||||
if self.GetState() == nil {
|
if self.GetState() == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeconflicts.ColoredConflictFile(self.GetState(), isFocused)
|
return mergeconflicts.ColoredConflictFile(self.GetState())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) setContent(isFocused bool) {
|
func (self *MergeConflictsContext) setContent() {
|
||||||
self.GetView().SetContent(self.GetContentToRender(isFocused))
|
self.GetView().SetContent(self.GetContentToRender())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) FocusSelection() {
|
func (self *MergeConflictsContext) FocusSelection() {
|
||||||
if !self.IsUserScrolling() {
|
if !self.IsUserScrolling() {
|
||||||
_ = self.GetView().SetOriginY(self.GetOriginY())
|
_ = self.GetView().SetOriginY(self.GetOriginY())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.SetSelectedLineRange()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *MergeConflictsContext) SetSelectedLineRange() {
|
||||||
|
startIdx, endIdx := self.GetState().GetSelectedRange()
|
||||||
|
view := self.GetView()
|
||||||
|
originY := view.OriginY()
|
||||||
|
// As far as the view is concerned, we are always selecting a range
|
||||||
|
view.SetRangeSelectStart(startIdx)
|
||||||
|
view.SetCursorY(endIdx - originY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsContext) GetOriginY() int {
|
func (self *MergeConflictsContext) GetOriginY() int {
|
||||||
|
@ -115,7 +115,10 @@ func (self *PatchExplorerContext) FocusSelection() {
|
|||||||
|
|
||||||
_ = view.SetOriginY(newOriginY)
|
_ = view.SetOriginY(newOriginY)
|
||||||
|
|
||||||
view.SetCursorY(state.GetSelectedLineIdx() - newOriginY)
|
startIdx, endIdx := state.SelectedRange()
|
||||||
|
// As far as the view is concerned, we are always selecting a range
|
||||||
|
view.SetRangeSelectStart(startIdx)
|
||||||
|
view.SetCursorY(endIdx - newOriginY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string {
|
func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string {
|
||||||
|
@ -134,7 +134,7 @@ func NewSubCommitsContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
||||||
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
|
ctx.GetList().SetSelection(selectedLineIdx)
|
||||||
return ctx.HandleFocus(types.OnFocusOpts{})
|
return ctx.HandleFocus(types.OnFocusOpts{})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func (self *SuggestionsContext) GetSelectedItemId() string {
|
|||||||
|
|
||||||
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
|
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
|
||||||
self.State.Suggestions = suggestions
|
self.State.Suggestions = suggestions
|
||||||
self.SetSelectedLineIdx(0)
|
self.SetSelection(0)
|
||||||
self.c.ResetViewOrigin(self.GetView())
|
self.c.ResetViewOrigin(self.GetView())
|
||||||
_ = self.HandleRender()
|
_ = self.HandleRender()
|
||||||
}
|
}
|
||||||
@ -90,3 +90,8 @@ func (self *SuggestionsContext) RefreshSuggestions() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is currently no need to use range-select in the suggestions view so we're disabling it.
|
||||||
|
func (self *SuggestionsContext) RangeSelectEnabled() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -9,13 +9,34 @@ type HasLength interface {
|
|||||||
Len() int
|
Len() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RangeSelectMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// None means we are not selecting a range
|
||||||
|
RangeSelectModeNone RangeSelectMode = iota
|
||||||
|
// Sticky range select is started by pressing 'v', then the range is expanded
|
||||||
|
// when you move up or down. It is cancelled by pressing 'v' again.
|
||||||
|
RangeSelectModeSticky
|
||||||
|
// Nonsticky range select is started by pressing shift+arrow and cancelled
|
||||||
|
// when pressing up/down without shift, or by pressing 'v'
|
||||||
|
RangeSelectModeNonSticky
|
||||||
|
)
|
||||||
|
|
||||||
type ListCursor struct {
|
type ListCursor struct {
|
||||||
selectedIdx int
|
selectedIdx int
|
||||||
list HasLength
|
rangeSelectMode RangeSelectMode
|
||||||
|
// value is ignored when rangeSelectMode is RangeSelectModeNone
|
||||||
|
rangeStartIdx int
|
||||||
|
list HasLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListCursor(list HasLength) *ListCursor {
|
func NewListCursor(list HasLength) *ListCursor {
|
||||||
return &ListCursor{selectedIdx: 0, list: list}
|
return &ListCursor{
|
||||||
|
selectedIdx: 0,
|
||||||
|
rangeStartIdx: 0,
|
||||||
|
rangeSelectMode: RangeSelectModeNone,
|
||||||
|
list: list,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IListCursor = (*ListCursor)(nil)
|
var _ types.IListCursor = (*ListCursor)(nil)
|
||||||
@ -24,25 +45,110 @@ func (self *ListCursor) GetSelectedLineIdx() int {
|
|||||||
return self.selectedIdx
|
return self.selectedIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the selected line index. Note, you probably don't want to use this directly,
|
||||||
|
// because it doesn't affect the range select mode or range start index. You should only
|
||||||
|
// use this for navigation situations where e.g. the user wants to jump to the top of
|
||||||
|
// a list while in range select mode so that the selection ends up being between
|
||||||
|
// the top of the list and the previous selection
|
||||||
func (self *ListCursor) SetSelectedLineIdx(value int) {
|
func (self *ListCursor) SetSelectedLineIdx(value int) {
|
||||||
|
self.selectedIdx = self.clampValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the selected index and cancels the range. You almost always want to use
|
||||||
|
// this instead of SetSelectedLineIdx. For example, if you want to jump the cursor
|
||||||
|
// to the top of a list after checking out a branch, you should use this method,
|
||||||
|
// or you may end up with a large range selection from the previous cursor position
|
||||||
|
// to the top of the list.
|
||||||
|
func (self *ListCursor) SetSelection(value int) {
|
||||||
|
self.selectedIdx = self.clampValue(value)
|
||||||
|
self.CancelRangeSelect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) clampValue(value int) int {
|
||||||
clampedValue := -1
|
clampedValue := -1
|
||||||
if self.list.Len() > 0 {
|
if self.list.Len() > 0 {
|
||||||
clampedValue = utils.Clamp(value, 0, self.list.Len()-1)
|
clampedValue = utils.Clamp(value, 0, self.list.Len()-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.selectedIdx = clampedValue
|
return clampedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// moves the cursor up or down by the given amount
|
// Moves the cursor up or down by the given amount.
|
||||||
func (self *ListCursor) MoveSelectedLine(delta int) {
|
// If we are in non-sticky range select mode, this will cancel the range select
|
||||||
self.SetSelectedLineIdx(self.selectedIdx + delta)
|
func (self *ListCursor) MoveSelectedLine(change int) {
|
||||||
|
if self.rangeSelectMode == RangeSelectModeNonSticky {
|
||||||
|
self.CancelRangeSelect()
|
||||||
|
}
|
||||||
|
|
||||||
|
self.SetSelectedLineIdx(self.selectedIdx + change)
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called when the model might have shrunk so that our selection is not not out of bounds
|
// Moves the cursor up or down by the given amount, and also moves the range start
|
||||||
func (self *ListCursor) RefreshSelectedIdx() {
|
// index by the same amount
|
||||||
self.SetSelectedLineIdx(self.selectedIdx)
|
func (self *ListCursor) MoveSelection(delta int) {
|
||||||
|
self.selectedIdx = self.clampValue(self.selectedIdx + delta)
|
||||||
|
if self.IsSelectingRange() {
|
||||||
|
self.rangeStartIdx = self.clampValue(self.rangeStartIdx + delta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To be called when the model might have shrunk so that our selection is not out of bounds
|
||||||
|
func (self *ListCursor) ClampSelection() {
|
||||||
|
self.selectedIdx = self.clampValue(self.selectedIdx)
|
||||||
|
self.rangeStartIdx = self.clampValue(self.rangeStartIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ListCursor) Len() int {
|
func (self *ListCursor) Len() int {
|
||||||
return self.list.Len()
|
return self.list.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) GetRangeStartIdx() (int, bool) {
|
||||||
|
if self.IsSelectingRange() {
|
||||||
|
return self.rangeStartIdx, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) CancelRangeSelect() {
|
||||||
|
self.rangeSelectMode = RangeSelectModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if we are in range select mode. Note that we may be in range select
|
||||||
|
// mode and still only selecting a single item. See AreMultipleItemsSelected below.
|
||||||
|
func (self *ListCursor) IsSelectingRange() bool {
|
||||||
|
return self.rangeSelectMode != RangeSelectModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if we are in range select mode and selecting multiple items
|
||||||
|
func (self *ListCursor) AreMultipleItemsSelected() bool {
|
||||||
|
startIdx, endIdx := self.GetSelectionRange()
|
||||||
|
return startIdx != endIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) GetSelectionRange() (int, int) {
|
||||||
|
if self.IsSelectingRange() {
|
||||||
|
return utils.MinMax(self.selectedIdx, self.rangeStartIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.selectedIdx, self.selectedIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) ToggleStickyRange() {
|
||||||
|
if self.IsSelectingRange() {
|
||||||
|
self.CancelRangeSelect()
|
||||||
|
} else {
|
||||||
|
self.rangeStartIdx = self.selectedIdx
|
||||||
|
self.rangeSelectMode = RangeSelectModeSticky
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListCursor) ExpandNonStickyRange(change int) {
|
||||||
|
if !self.IsSelectingRange() {
|
||||||
|
self.rangeStartIdx = self.selectedIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rangeSelectMode = RangeSelectModeNonSticky
|
||||||
|
|
||||||
|
self.SetSelectedLineIdx(self.selectedIdx + change)
|
||||||
|
}
|
||||||
|
@ -21,6 +21,14 @@ func (self *ViewTrait) FocusPoint(yIdx int) {
|
|||||||
self.view.FocusPoint(self.view.OriginX(), yIdx)
|
self.view.FocusPoint(self.view.OriginX(), yIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ViewTrait) SetRangeSelectStart(yIdx int) {
|
||||||
|
self.view.SetRangeSelectStart(yIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ViewTrait) CancelRangeSelect() {
|
||||||
|
self.view.CancelRangeSelect()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *ViewTrait) SetViewPortContent(content string) {
|
func (self *ViewTrait) SetViewPortContent(content string) {
|
||||||
_, y := self.view.Origin()
|
_, y := self.view.Origin()
|
||||||
self.view.OverwriteLines(y, content)
|
self.view.OverwriteLines(y, content)
|
||||||
|
@ -50,7 +50,7 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
||||||
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
|
ctx.GetList().SetSelection(selectedLineIdx)
|
||||||
return ctx.HandleFocus(types.OnFocusOpts{})
|
return ctx.HandleFocus(types.OnFocusOpts{})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ var _ types.IController = &BasicCommitsController{}
|
|||||||
|
|
||||||
type ContainsCommits interface {
|
type ContainsCommits interface {
|
||||||
types.Context
|
types.Context
|
||||||
|
types.IListContext
|
||||||
GetSelected() *models.Commit
|
GetSelected() *models.Commit
|
||||||
GetCommits() []*models.Commit
|
GetCommits() []*models.Commit
|
||||||
GetSelectedLineIdx() int
|
GetSelectedLineIdx() int
|
||||||
@ -21,87 +22,79 @@ type ContainsCommits interface {
|
|||||||
|
|
||||||
type BasicCommitsController struct {
|
type BasicCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Commit]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context ContainsCommits
|
context ContainsCommits
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasicCommitsController(controllerCommon *ControllerCommon, context ContainsCommits) *BasicCommitsController {
|
func NewBasicCommitsController(c *ControllerCommon, context ContainsCommits) *BasicCommitsController {
|
||||||
return &BasicCommitsController{
|
return &BasicCommitsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: controllerCommon,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||||
|
c,
|
||||||
|
context,
|
||||||
|
context.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
|
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
|
||||||
Handler: self.checkSelected(self.checkout),
|
Handler: self.withItem(self.checkout),
|
||||||
Description: self.c.Tr.CheckoutCommit,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CheckoutCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
|
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
|
||||||
Handler: self.checkSelected(self.copyCommitAttribute),
|
Handler: self.withItem(self.copyCommitAttribute),
|
||||||
Description: self.c.Tr.CopyCommitAttributeToClipboard,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.CopyCommitAttributeToClipboard,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
|
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
|
||||||
Handler: self.checkSelected(self.openInBrowser),
|
Handler: self.withItem(self.openInBrowser),
|
||||||
Description: self.c.Tr.OpenCommitInBrowser,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenCommitInBrowser,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
Handler: self.checkSelected(self.newBranch),
|
Handler: self.withItem(self.newBranch),
|
||||||
Description: self.c.Tr.CreateNewBranchFromCommit,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CreateNewBranchFromCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||||
Handler: self.checkSelected(self.createResetMenu),
|
Handler: self.withItem(self.createResetMenu),
|
||||||
Description: self.c.Tr.ViewResetOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewResetOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.CherryPickCopy),
|
Key: opts.GetKey(opts.Config.Commits.CherryPickCopy),
|
||||||
Handler: self.checkSelected(self.copy),
|
Handler: self.withItem(self.copyRange),
|
||||||
Description: self.c.Tr.CherryPickCopy,
|
Description: self.c.Tr.CherryPickCopy,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Key: opts.GetKey(opts.Config.Commits.CherryPickCopyRange),
|
|
||||||
Handler: self.checkSelected(self.copyRange),
|
|
||||||
Description: self.c.Tr.CherryPickCopyRange,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ResetCherryPick),
|
Key: opts.GetKey(opts.Config.Commits.ResetCherryPick),
|
||||||
Handler: self.c.Helpers().CherryPick.Reset,
|
Handler: self.c.Helpers().CherryPick.Reset,
|
||||||
Description: self.c.Tr.ResetCherryPick,
|
Description: self.c.Tr.ResetCherryPick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||||
Handler: self.checkSelected(self.openDiffTool),
|
Handler: self.withItem(self.openDiffTool),
|
||||||
Description: self.c.Tr.OpenDiffTool,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenDiffTool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BasicCommitsController) checkSelected(callback func(*models.Commit) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
commit := self.context.GetSelected()
|
|
||||||
if commit == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BasicCommitsController) Context() types.Context {
|
|
||||||
return self.context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
|
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
|
||||||
return self.c.Menu(types.CreateMenuOptions{
|
return self.c.Menu(types.CreateMenuOptions{
|
||||||
Title: self.c.Tr.Actions.CopyCommitAttributeToClipboard,
|
Title: self.c.Tr.Actions.CopyCommitAttributeToClipboard,
|
||||||
@ -271,12 +264,8 @@ func (self *BasicCommitsController) checkout(commit *models.Commit) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BasicCommitsController) copy(commit *models.Commit) error {
|
|
||||||
return self.c.Helpers().CherryPick.Copy(commit, self.context.GetCommits(), self.context)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BasicCommitsController) copyRange(*models.Commit) error {
|
func (self *BasicCommitsController) copyRange(*models.Commit) error {
|
||||||
return self.c.Helpers().CherryPick.CopyRange(self.context.GetSelectedLineIdx(), self.context.GetCommits(), self.context)
|
return self.c.Helpers().CherryPick.CopyRange(self.context.GetCommits(), self.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {
|
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {
|
||||||
|
@ -14,17 +14,23 @@ import (
|
|||||||
|
|
||||||
type BisectController struct {
|
type BisectController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Commit]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &BisectController{}
|
var _ types.IController = &BisectController{}
|
||||||
|
|
||||||
func NewBisectController(
|
func NewBisectController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *BisectController {
|
) *BisectController {
|
||||||
return &BisectController{
|
return &BisectController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||||
|
c,
|
||||||
|
c.Contexts().LocalCommits,
|
||||||
|
c.Contexts().LocalCommits.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +38,7 @@ func (self *BisectController) GetKeybindings(opts types.KeybindingsOpts) []*type
|
|||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewBisectOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewBisectOptions),
|
||||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.openMenu)),
|
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.openMenu)),
|
||||||
Description: self.c.Tr.ViewBisectOptions,
|
Description: self.c.Tr.ViewBisectOptions,
|
||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
@ -70,9 +76,19 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
|||||||
// If we have a current sha already, then we always want to use that one. If
|
// If we have a current sha already, then we always want to use that one. If
|
||||||
// not, we're still picking the initial commits before we really start, so
|
// not, we're still picking the initial commits before we really start, so
|
||||||
// use the selected commit in that case.
|
// use the selected commit in that case.
|
||||||
shaToMark := lo.Ternary(info.GetCurrentSha() != "", info.GetCurrentSha(), commit.Sha)
|
|
||||||
|
bisecting := info.GetCurrentSha() != ""
|
||||||
|
shaToMark := lo.Ternary(bisecting, info.GetCurrentSha(), commit.Sha)
|
||||||
shortShaToMark := utils.ShortSha(shaToMark)
|
shortShaToMark := utils.ShortSha(shaToMark)
|
||||||
|
|
||||||
|
// For marking a commit as bad, when we're not already bisecting, we require
|
||||||
|
// a single item selected, but once we are bisecting, it doesn't matter because
|
||||||
|
// the action applies to the HEAD commit rather than the selected commit.
|
||||||
|
var singleItemIfNotBisecting *types.DisabledReason
|
||||||
|
if !bisecting {
|
||||||
|
singleItemIfNotBisecting = self.require(self.singleItemSelected())()
|
||||||
|
}
|
||||||
|
|
||||||
menuItems := []*types.MenuItem{
|
menuItems := []*types.MenuItem{
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.NewTerm()),
|
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.NewTerm()),
|
||||||
@ -84,7 +100,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
|||||||
|
|
||||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||||
},
|
},
|
||||||
Key: 'b',
|
DisabledReason: singleItemIfNotBisecting,
|
||||||
|
Key: 'b',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.OldTerm()),
|
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.OldTerm()),
|
||||||
@ -96,7 +113,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
|||||||
|
|
||||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||||
},
|
},
|
||||||
Key: 'g',
|
DisabledReason: singleItemIfNotBisecting,
|
||||||
|
Key: 'g',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortShaToMark),
|
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortShaToMark),
|
||||||
@ -108,7 +126,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
|||||||
|
|
||||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||||
},
|
},
|
||||||
Key: 's',
|
DisabledReason: singleItemIfNotBisecting,
|
||||||
|
Key: 's',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if info.GetCurrentSha() != "" && info.GetCurrentSha() != commit.Sha {
|
if info.GetCurrentSha() != "" && info.GetCurrentSha() != commit.Sha {
|
||||||
@ -122,7 +141,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
|||||||
|
|
||||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||||
},
|
},
|
||||||
Key: 'S',
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
|
Key: 'S',
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
|
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
|
||||||
@ -157,7 +177,8 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
|||||||
|
|
||||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||||
},
|
},
|
||||||
Key: 'b',
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
|
Key: 'b',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.OldTerm()),
|
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.OldTerm()),
|
||||||
@ -173,7 +194,8 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
|||||||
|
|
||||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||||
},
|
},
|
||||||
Key: 'g',
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
|
Key: 'g',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: self.c.Tr.Bisect.ChooseTerms,
|
Label: self.c.Tr.Bisect.ChooseTerms,
|
||||||
@ -265,7 +287,7 @@ func (self *BisectController) selectCurrentBisectCommit() {
|
|||||||
// find index of commit with that sha, move cursor to that.
|
// find index of commit with that sha, move cursor to that.
|
||||||
for i, commit := range self.c.Model().Commits {
|
for i, commit := range self.c.Model().Commits {
|
||||||
if commit.Sha == info.GetCurrentSha() {
|
if commit.Sha == info.GetCurrentSha() {
|
||||||
self.context().SetSelectedLineIdx(i)
|
self.context().SetSelection(i)
|
||||||
_ = self.context().HandleFocus(types.OnFocusOpts{})
|
_ = self.context().HandleFocus(types.OnFocusOpts{})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -273,21 +295,6 @@ func (self *BisectController) selectCurrentBisectCommit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BisectController) checkSelected(callback func(*models.Commit) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
commit := self.context().GetSelected()
|
|
||||||
if commit == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BisectController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BisectController) context() *context.LocalCommitsContext {
|
func (self *BisectController) context() *context.LocalCommitsContext {
|
||||||
return self.c.Contexts().LocalCommits
|
return self.c.Contexts().LocalCommits
|
||||||
}
|
}
|
||||||
|
@ -17,48 +17,61 @@ import (
|
|||||||
|
|
||||||
type BranchesController struct {
|
type BranchesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Branch]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &BranchesController{}
|
var _ types.IController = &BranchesController{}
|
||||||
|
|
||||||
func NewBranchesController(
|
func NewBranchesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *BranchesController {
|
) *BranchesController {
|
||||||
return &BranchesController{
|
return &BranchesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*models.Branch](
|
||||||
|
c,
|
||||||
|
c.Contexts().Branches,
|
||||||
|
c.Contexts().Branches.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
return []*types.Binding{
|
return []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelected(self.press),
|
Handler: self.withItem(self.press),
|
||||||
GetDisabledReason: self.getDisabledReasonForPress,
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.Checkout,
|
self.singleItemSelected(),
|
||||||
|
self.notPulling,
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.Checkout,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
Handler: self.checkSelected(self.newBranch),
|
Handler: self.withItem(self.newBranch),
|
||||||
Description: self.c.Tr.NewBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.NewBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
|
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
|
||||||
Handler: self.checkSelected(self.handleCreatePullRequest),
|
Handler: self.withItem(self.handleCreatePullRequest),
|
||||||
Description: self.c.Tr.CreatePullRequest,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CreatePullRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
|
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
|
||||||
Handler: self.checkSelected(self.handleCreatePullRequestMenu),
|
Handler: self.withItem(self.handleCreatePullRequestMenu),
|
||||||
Description: self.c.Tr.CreatePullRequestOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.CreatePullRequestOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
|
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
|
||||||
Handler: self.copyPullRequestURL,
|
Handler: self.copyPullRequestURL,
|
||||||
Description: self.c.Tr.CopyPullRequestURL,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CopyPullRequestURL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.CheckoutBranchByName),
|
Key: opts.GetKey(opts.Config.Branches.CheckoutBranchByName),
|
||||||
@ -66,60 +79,69 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
|
|||||||
Description: self.c.Tr.CheckoutByName,
|
Description: self.c.Tr.CheckoutByName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
|
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
|
||||||
Handler: self.forceCheckout,
|
Handler: self.forceCheckout,
|
||||||
Description: self.c.Tr.ForceCheckout,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.ForceCheckout,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelectedAndReal(self.delete),
|
Handler: self.withItem(self.delete),
|
||||||
Description: self.c.Tr.ViewDeleteOptions,
|
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewDeleteOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||||
Handler: opts.Guards.OutsideFilterMode(self.rebase),
|
Handler: opts.Guards.OutsideFilterMode(self.rebase),
|
||||||
Description: self.c.Tr.RebaseBranch,
|
GetDisabledReason: self.require(
|
||||||
GetDisabledReason: self.getDisabledReasonForRebase,
|
self.singleItemSelected(self.notRebasingOntoSelf),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.RebaseBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||||
Handler: opts.Guards.OutsideFilterMode(self.merge),
|
Handler: opts.Guards.OutsideFilterMode(self.merge),
|
||||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.FastForward),
|
Key: opts.GetKey(opts.Config.Branches.FastForward),
|
||||||
Handler: self.checkSelectedAndReal(self.fastForward),
|
Handler: self.withItem(self.fastForward),
|
||||||
Description: self.c.Tr.FastForward,
|
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||||
|
Description: self.c.Tr.FastForward,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.CreateTag),
|
Key: opts.GetKey(opts.Config.Branches.CreateTag),
|
||||||
Handler: self.checkSelected(self.createTag),
|
Handler: self.withItem(self.createTag),
|
||||||
Description: self.c.Tr.CreateTag,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CreateTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
||||||
Handler: self.createSortMenu,
|
Handler: self.createSortMenu,
|
||||||
Description: self.c.Tr.SortOrder,
|
Description: self.c.Tr.SortOrder,
|
||||||
OpensMenu: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||||
Handler: self.checkSelected(self.createResetMenu),
|
Handler: self.withItem(self.createResetMenu),
|
||||||
Description: self.c.Tr.ViewResetOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewResetOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
|
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
|
||||||
Handler: self.checkSelectedAndReal(self.rename),
|
Handler: self.withItem(self.rename),
|
||||||
Description: self.c.Tr.RenameBranch,
|
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||||
|
Description: self.c.Tr.RenameBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||||
Handler: self.checkSelected(self.viewUpstreamOptions),
|
Handler: self.withItem(self.viewUpstreamOptions),
|
||||||
Description: self.c.Tr.ViewBranchUpstreamOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
|
Description: self.c.Tr.ViewBranchUpstreamOptions,
|
||||||
OpensMenu: true,
|
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,7 +187,6 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
|||||||
ShowBranchHeads: false,
|
ShowBranchHeads: false,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Key: 'v',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsetUpstreamItem := &types.MenuItem{
|
unsetUpstreamItem := &types.MenuItem{
|
||||||
@ -309,7 +330,7 @@ func (self *BranchesController) press(selectedBranch *models.Branch) error {
|
|||||||
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
|
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesController) getDisabledReasonForPress() *types.DisabledReason {
|
func (self *BranchesController) notPulling() *types.DisabledReason {
|
||||||
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
|
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
|
||||||
if currentBranch != nil {
|
if currentBranch != nil {
|
||||||
op := self.c.State().GetItemOperation(currentBranch)
|
op := self.c.State().GetItemOperation(currentBranch)
|
||||||
@ -425,7 +446,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
|
|||||||
return self.c.Error(err)
|
return self.c.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.context().SetSelectedLineIdx(0)
|
self.context().SetSelection(0)
|
||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,8 +583,8 @@ func (self *BranchesController) rebase() error {
|
|||||||
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
|
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesController) getDisabledReasonForRebase() *types.DisabledReason {
|
func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *types.DisabledReason {
|
||||||
selectedBranchName := self.context().GetSelected().Name
|
selectedBranchName := branch.Name
|
||||||
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
|
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
|
||||||
if selectedBranchName == checkedOutBranch {
|
if selectedBranchName == checkedOutBranch {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
|
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
|
||||||
@ -628,7 +649,7 @@ func (self *BranchesController) createSortMenu() error {
|
|||||||
if self.c.GetAppState().LocalBranchSortOrder != sortOrder {
|
if self.c.GetAppState().LocalBranchSortOrder != sortOrder {
|
||||||
self.c.GetAppState().LocalBranchSortOrder = sortOrder
|
self.c.GetAppState().LocalBranchSortOrder = sortOrder
|
||||||
self.c.SaveAppStateAndLogError()
|
self.c.SaveAppStateAndLogError()
|
||||||
self.c.Contexts().Branches.SetSelectedLineIdx(0)
|
self.c.Contexts().Branches.SetSelection(0)
|
||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -659,7 +680,7 @@ func (self *BranchesController) rename(branch *models.Branch) error {
|
|||||||
// now that we've got our stuff again we need to find that branch and reselect it.
|
// now that we've got our stuff again we need to find that branch and reselect it.
|
||||||
for i, newBranch := range self.c.Model().Branches {
|
for i, newBranch := range self.c.Model().Branches {
|
||||||
if newBranch.Name == newBranchName {
|
if newBranch.Name == newBranchName {
|
||||||
self.context().SetSelectedLineIdx(i)
|
self.context().SetSelection(i)
|
||||||
if err := self.context().HandleRender(); err != nil {
|
if err := self.context().HandleRender(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -754,24 +775,10 @@ func (self *BranchesController) createPullRequest(from string, to string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesController) checkSelected(callback func(*models.Branch) error) func() error {
|
func (self *BranchesController) branchIsReal(branch *models.Branch) *types.DisabledReason {
|
||||||
return func() error {
|
if !branch.IsRealBranch() {
|
||||||
selectedItem := self.context().GetSelected()
|
return &types.DisabledReason{Text: self.c.Tr.SelectedItemIsNotABranch}
|
||||||
if selectedItem == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(selectedItem)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BranchesController) checkSelectedAndReal(callback func(*models.Branch) error) func() error {
|
return nil
|
||||||
return func() error {
|
|
||||||
selectedItem := self.context().GetSelected()
|
|
||||||
if selectedItem == nil || !selectedItem.IsRealBranch() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(selectedItem)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@ type CommandLogController struct {
|
|||||||
var _ types.IController = &CommandLogController{}
|
var _ types.IController = &CommandLogController{}
|
||||||
|
|
||||||
func NewCommandLogController(
|
func NewCommandLogController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *CommandLogController {
|
) *CommandLogController {
|
||||||
return &CommandLogController{
|
return &CommandLogController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ type CommitDescriptionController struct {
|
|||||||
var _ types.IController = &CommitMessageController{}
|
var _ types.IController = &CommitMessageController{}
|
||||||
|
|
||||||
func NewCommitDescriptionController(
|
func NewCommitDescriptionController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *CommitDescriptionController {
|
) *CommitDescriptionController {
|
||||||
return &CommitDescriptionController{
|
return &CommitDescriptionController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@ type CommitMessageController struct {
|
|||||||
var _ types.IController = &CommitMessageController{}
|
var _ types.IController = &CommitMessageController{}
|
||||||
|
|
||||||
func NewCommitMessageController(
|
func NewCommitMessageController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *CommitMessageController {
|
) *CommitMessageController {
|
||||||
return &CommitMessageController{
|
return &CommitMessageController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,61 +12,74 @@ import (
|
|||||||
|
|
||||||
type CommitFilesController struct {
|
type CommitFilesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*filetree.CommitFileNode]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &CommitFilesController{}
|
var _ types.IController = &CommitFilesController{}
|
||||||
|
|
||||||
func NewCommitFilesController(
|
func NewCommitFilesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *CommitFilesController {
|
) *CommitFilesController {
|
||||||
return &CommitFilesController{
|
return &CommitFilesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*filetree.CommitFileNode](
|
||||||
|
c,
|
||||||
|
c.Contexts().CommitFiles,
|
||||||
|
c.Contexts().CommitFiles.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
|
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
|
||||||
Handler: self.checkSelected(self.checkout),
|
Handler: self.withItem(self.checkout),
|
||||||
Description: self.c.Tr.CheckoutCommitFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.CheckoutCommitFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.discard),
|
Handler: self.withItem(self.discard),
|
||||||
Description: self.c.Tr.DiscardOldFileChange,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.DiscardOldFileChange,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||||
Handler: self.checkSelected(self.open),
|
Handler: self.withItem(self.open),
|
||||||
Description: self.c.Tr.OpenFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||||
Handler: self.checkSelected(self.edit),
|
Handler: self.withItem(self.edit),
|
||||||
Description: self.c.Tr.EditFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EditFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||||
Handler: self.checkSelected(self.openDiffTool),
|
Handler: self.withItem(self.openDiffTool),
|
||||||
Description: self.c.Tr.OpenDiffTool,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenDiffTool,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelected(self.toggleForPatch),
|
Handler: self.withItem(self.toggleForPatch),
|
||||||
Description: self.c.Tr.ToggleAddToPatch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.ToggleAddToPatch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.ToggleStagedAll),
|
Key: opts.GetKey(opts.Config.Files.ToggleStagedAll),
|
||||||
Handler: self.checkSelected(self.toggleAllForPatch),
|
Handler: self.withItem(self.toggleAllForPatch),
|
||||||
Description: self.c.Tr.ToggleAllInPatch,
|
Description: self.c.Tr.ToggleAllInPatch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.EnterFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EnterFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.ToggleTreeView),
|
Key: opts.GetKey(opts.Config.Files.ToggleTreeView),
|
||||||
@ -89,21 +102,6 @@ func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFilesController) checkSelected(callback func(*filetree.CommitFileNode) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
selected := self.context().GetSelected()
|
|
||||||
if selected == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(selected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *CommitFilesController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *CommitFilesController) context() *context.CommitFilesContext {
|
func (self *CommitFilesController) context() *context.CommitFilesContext {
|
||||||
return self.c.Contexts().CommitFiles
|
return self.c.Contexts().CommitFiles
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@ type ConfirmationController struct {
|
|||||||
var _ types.IController = &ConfirmationController{}
|
var _ types.IController = &ConfirmationController{}
|
||||||
|
|
||||||
func NewConfirmationController(
|
func NewConfirmationController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *ConfirmationController {
|
) *ConfirmationController {
|
||||||
return &ConfirmationController{
|
return &ConfirmationController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ type ContextLinesController struct {
|
|||||||
var _ types.IController = &ContextLinesController{}
|
var _ types.IController = &ContextLinesController{}
|
||||||
|
|
||||||
func NewContextLinesController(
|
func NewContextLinesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *ContextLinesController {
|
) *ContextLinesController {
|
||||||
return &ContextLinesController{
|
return &ContextLinesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +62,22 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
|||||||
if self.c.CurrentContext().GetKey() == self.c.Contexts().LocalCommits.GetKey() {
|
if self.c.CurrentContext().GetKey() == self.c.Contexts().LocalCommits.GetKey() {
|
||||||
selectedCommit := self.c.Contexts().LocalCommits.GetSelected()
|
selectedCommit := self.c.Contexts().LocalCommits.GetSelected()
|
||||||
if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Sha {
|
if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Sha {
|
||||||
|
|
||||||
|
var disabledReason *types.DisabledReason
|
||||||
|
if self.c.Contexts().LocalCommits.AreMultipleItemsSelected() {
|
||||||
|
disabledReason = &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported}
|
||||||
|
}
|
||||||
|
|
||||||
// adding this option to index 1
|
// adding this option to index 1
|
||||||
menuItems = append(
|
menuItems = append(
|
||||||
menuItems[:1],
|
menuItems[:1],
|
||||||
append(
|
append(
|
||||||
[]*types.MenuItem{
|
[]*types.MenuItem{
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Sha),
|
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Sha),
|
||||||
OnPress: self.handleMovePatchToSelectedCommit,
|
OnPress: self.handleMovePatchToSelectedCommit,
|
||||||
Key: 'm',
|
Key: 'm',
|
||||||
|
DisabledReason: disabledReason,
|
||||||
},
|
},
|
||||||
}, menuItems[1:]...,
|
}, menuItems[1:]...,
|
||||||
)...,
|
)...,
|
||||||
|
@ -13,25 +13,32 @@ import (
|
|||||||
|
|
||||||
type FilesController struct {
|
type FilesController struct {
|
||||||
baseController // nolint: unused
|
baseController // nolint: unused
|
||||||
c *ControllerCommon
|
*ListControllerTrait[*filetree.FileNode]
|
||||||
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &FilesController{}
|
var _ types.IController = &FilesController{}
|
||||||
|
|
||||||
func NewFilesController(
|
func NewFilesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *FilesController {
|
) *FilesController {
|
||||||
return &FilesController{
|
return &FilesController{
|
||||||
c: common,
|
c: c,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*filetree.FileNode](
|
||||||
|
c,
|
||||||
|
c.Contexts().Files,
|
||||||
|
c.Contexts().Files.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
return []*types.Binding{
|
return []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelectedFileNode(self.press),
|
Handler: self.withItem(self.press),
|
||||||
Description: self.c.Tr.ToggleStaged,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.ToggleStaged,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.OpenStatusFilter),
|
Key: opts.GetKey(opts.Config.Files.OpenStatusFilter),
|
||||||
@ -71,20 +78,23 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
|||||||
Tooltip: self.c.Tr.FindBaseCommitForFixupTooltip,
|
Tooltip: self.c.Tr.FindBaseCommitForFixupTooltip,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||||
Handler: self.checkSelectedFileNode(self.edit),
|
Handler: self.withItem(self.edit),
|
||||||
Description: self.c.Tr.EditFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EditFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||||
Handler: self.Open,
|
Handler: self.Open,
|
||||||
Description: self.c.Tr.OpenFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.IgnoreFile),
|
Key: opts.GetKey(opts.Config.Files.IgnoreFile),
|
||||||
Handler: self.checkSelectedFileNode(self.ignoreOrExcludeMenu),
|
Handler: self.withItem(self.ignoreOrExcludeMenu),
|
||||||
Description: self.c.Tr.Actions.IgnoreExcludeFile,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.Actions.IgnoreExcludeFile,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.RefreshFiles),
|
Key: opts.GetKey(opts.Config.Files.RefreshFiles),
|
||||||
@ -108,9 +118,10 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
|||||||
Description: self.c.Tr.ToggleStagedAll,
|
Description: self.c.Tr.ToggleStagedAll,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
Handler: self.enter,
|
Handler: self.enter,
|
||||||
Description: self.c.Tr.FileEnter,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.FileEnter,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||||
@ -130,9 +141,10 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
|||||||
Description: self.c.Tr.ToggleTreeView,
|
Description: self.c.Tr.ToggleTreeView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||||
Handler: self.checkSelectedFileNode(self.openDiffTool),
|
Handler: self.withItem(self.openDiffTool),
|
||||||
Description: self.c.Tr.OpenDiffTool,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenDiffTool,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
||||||
@ -205,7 +217,7 @@ func (self *FilesController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hasConflicts {
|
if hasConflicts {
|
||||||
return self.c.Helpers().MergeConflicts.Render(false)
|
return self.c.Helpers().MergeConflicts.Render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +266,7 @@ func (self *FilesController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesController) GetOnClick() func() error {
|
func (self *FilesController) GetOnClick() func() error {
|
||||||
return self.checkSelectedFileNode(self.press)
|
return self.withItemGraceful(self.press)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are dealing with a status for which there is no key in this map,
|
// if we are dealing with a status for which there is no key in this map,
|
||||||
@ -411,17 +423,6 @@ func (self *FilesController) press(node *filetree.FileNode) error {
|
|||||||
return self.context().HandleFocus(types.OnFocusOpts{})
|
return self.context().HandleFocus(types.OnFocusOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
node := self.context().GetSelected()
|
|
||||||
if node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *FilesController) Context() types.Context {
|
func (self *FilesController) Context() types.Context {
|
||||||
return self.context()
|
return self.context()
|
||||||
}
|
}
|
||||||
@ -798,7 +799,8 @@ func (self *FilesController) openCopyMenu() error {
|
|||||||
self.c.Toast(self.c.Tr.FileNameCopiedToast)
|
self.c.Toast(self.c.Tr.FileNameCopiedToast)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Key: 'n',
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
|
Key: 'n',
|
||||||
}
|
}
|
||||||
copyPathItem := &types.MenuItem{
|
copyPathItem := &types.MenuItem{
|
||||||
Label: self.c.Tr.CopyFilePath,
|
Label: self.c.Tr.CopyFilePath,
|
||||||
@ -809,7 +811,8 @@ func (self *FilesController) openCopyMenu() error {
|
|||||||
self.c.Toast(self.c.Tr.FilePathCopiedToast)
|
self.c.Toast(self.c.Tr.FilePathCopiedToast)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Key: 'p',
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
|
Key: 'p',
|
||||||
}
|
}
|
||||||
copyFileDiffItem := &types.MenuItem{
|
copyFileDiffItem := &types.MenuItem{
|
||||||
Label: self.c.Tr.CopySelectedDiff,
|
Label: self.c.Tr.CopySelectedDiff,
|
||||||
@ -827,6 +830,14 @@ func (self *FilesController) openCopyMenu() error {
|
|||||||
self.c.Toast(self.c.Tr.FileDiffCopiedToast)
|
self.c.Toast(self.c.Tr.FileDiffCopiedToast)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
DisabledReason: self.require(self.singleItemSelected(
|
||||||
|
func(file *filetree.FileNode) *types.DisabledReason {
|
||||||
|
if !node.GetHasStagedOrTrackedChanges() {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
))(),
|
||||||
Key: 's',
|
Key: 's',
|
||||||
}
|
}
|
||||||
copyAllDiff := &types.MenuItem{
|
copyAllDiff := &types.MenuItem{
|
||||||
@ -844,21 +855,17 @@ func (self *FilesController) openCopyMenu() error {
|
|||||||
self.c.Toast(self.c.Tr.AllFilesDiffCopiedToast)
|
self.c.Toast(self.c.Tr.AllFilesDiffCopiedToast)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
DisabledReason: self.require(
|
||||||
|
func() *types.DisabledReason {
|
||||||
|
if !self.anyStagedOrTrackedFile() {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)(),
|
||||||
Key: 'a',
|
Key: 'a',
|
||||||
}
|
}
|
||||||
|
|
||||||
if node == nil {
|
|
||||||
copyNameItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
|
||||||
copyPathItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
|
||||||
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
|
||||||
}
|
|
||||||
if node != nil && !node.GetHasStagedOrTrackedChanges() {
|
|
||||||
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
|
||||||
}
|
|
||||||
if !self.anyStagedOrTrackedFile() {
|
|
||||||
copyAllDiff.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.c.Menu(types.CreateMenuOptions{
|
return self.c.Menu(types.CreateMenuOptions{
|
||||||
Title: self.c.Tr.CopyToClipboardMenu,
|
Title: self.c.Tr.CopyToClipboardMenu,
|
||||||
Items: []*types.MenuItem{
|
Items: []*types.MenuItem{
|
||||||
|
@ -3,7 +3,6 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
@ -13,27 +12,34 @@ import (
|
|||||||
|
|
||||||
type FilesRemoveController struct {
|
type FilesRemoveController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*filetree.FileNode]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &FilesRemoveController{}
|
var _ types.IController = &FilesRemoveController{}
|
||||||
|
|
||||||
func NewFilesRemoveController(
|
func NewFilesRemoveController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *FilesRemoveController {
|
) *FilesRemoveController {
|
||||||
return &FilesRemoveController{
|
return &FilesRemoveController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*filetree.FileNode](
|
||||||
|
c,
|
||||||
|
c.Contexts().Files,
|
||||||
|
c.Contexts().Files.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesRemoveController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *FilesRemoveController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelectedFileNode(self.remove),
|
Handler: self.withItem(self.remove),
|
||||||
Description: self.c.Tr.ViewDiscardOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewDiscardOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,22 +172,3 @@ func (self *FilesRemoveController) ResetSubmodule(submodule *models.SubmoduleCon
|
|||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesRemoveController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
node := self.context().GetSelected()
|
|
||||||
if node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *FilesRemoveController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *FilesRemoveController) context() *context.WorkingTreeContext {
|
|
||||||
return self.c.Contexts().Files
|
|
||||||
}
|
|
||||||
|
@ -73,7 +73,7 @@ func (self *FilteringMenuAction) setFiltering(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() {
|
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() {
|
||||||
self.c.Contexts().LocalCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||||
self.c.Contexts().LocalCommits.FocusLine()
|
self.c.Contexts().LocalCommits.FocusLine()
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,29 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GitFlowController struct {
|
type GitFlowController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Branch]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &GitFlowController{}
|
var _ types.IController = &GitFlowController{}
|
||||||
|
|
||||||
func NewGitFlowController(
|
func NewGitFlowController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *GitFlowController {
|
) *GitFlowController {
|
||||||
return &GitFlowController{
|
return &GitFlowController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Branch](
|
||||||
|
c,
|
||||||
|
c.Contexts().Branches,
|
||||||
|
c.Contexts().Branches.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +34,7 @@ func (self *GitFlowController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
|||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.ViewGitFlowOptions),
|
Key: opts.GetKey(opts.Config.Branches.ViewGitFlowOptions),
|
||||||
Handler: self.checkSelected(self.handleCreateGitFlowMenu),
|
Handler: self.withItem(self.handleCreateGitFlowMenu),
|
||||||
Description: self.c.Tr.GitFlowOptions,
|
Description: self.c.Tr.GitFlowOptions,
|
||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
@ -68,6 +73,7 @@ func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) er
|
|||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
return self.gitFlowFinishBranch(branch.Name)
|
return self.gitFlowFinishBranch(branch.Name)
|
||||||
},
|
},
|
||||||
|
DisabledReason: self.require(self.singleItemSelected())(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: "start feature",
|
Label: "start feature",
|
||||||
@ -102,22 +108,3 @@ func (self *GitFlowController) gitFlowFinishBranch(branchName string) error {
|
|||||||
self.c.LogAction(self.c.Tr.Actions.GitFlowFinish)
|
self.c.LogAction(self.c.Tr.Actions.GitFlowFinish)
|
||||||
return self.c.RunSubprocessAndRefresh(cmdObj)
|
return self.c.RunSubprocessAndRefresh(cmdObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *GitFlowController) checkSelected(callback func(*models.Branch) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
node := self.context().GetSelected()
|
|
||||||
if node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *GitFlowController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *GitFlowController) context() *context.BranchesContext {
|
|
||||||
return self.c.Contexts().Branches
|
|
||||||
}
|
|
||||||
|
@ -11,11 +11,11 @@ type GlobalController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewGlobalController(
|
func NewGlobalController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *GlobalController {
|
) *GlobalController {
|
||||||
return &GlobalController{
|
return &GlobalController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking"
|
"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CherryPickHelper struct {
|
type CherryPickHelper struct {
|
||||||
@ -45,25 +46,30 @@ func (self *CherryPickHelper) Copy(commit *models.Commit, commitsList []*models.
|
|||||||
return self.rerender()
|
return self.rerender()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPickHelper) CopyRange(selectedIndex int, commitsList []*models.Commit, context types.Context) error {
|
func (self *CherryPickHelper) CopyRange(commitsList []*models.Commit, context types.IListContext) error {
|
||||||
|
startIdx, endIdx := context.GetList().GetSelectionRange()
|
||||||
|
|
||||||
if err := self.resetIfNecessary(context); err != nil {
|
if err := self.resetIfNecessary(context); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitSet := self.getData().SelectedShaSet()
|
commitSet := self.getData().SelectedShaSet()
|
||||||
|
|
||||||
// find the last commit that is copied that's above our position
|
allCommitsCopied := lo.EveryBy(commitsList[startIdx:endIdx+1], func(commit *models.Commit) bool {
|
||||||
// if there are none, startIndex = 0
|
return commitSet.Includes(commit.Sha)
|
||||||
startIndex := 0
|
})
|
||||||
for index, commit := range commitsList[0:selectedIndex] {
|
|
||||||
if commitSet.Includes(commit.Sha) {
|
|
||||||
startIndex = index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for index := startIndex; index <= selectedIndex; index++ {
|
// if all selected commits are already copied, we'll uncopy them
|
||||||
commit := commitsList[index]
|
if allCommitsCopied {
|
||||||
self.getData().Add(commit, commitsList)
|
for index := startIdx; index <= endIdx; index++ {
|
||||||
|
commit := commitsList[index]
|
||||||
|
self.getData().Remove(commit, commitsList)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for index := startIdx; index <= endIdx; index++ {
|
||||||
|
commit := commitsList[index]
|
||||||
|
self.getData().Add(commit, commitsList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.rerender()
|
return self.rerender()
|
||||||
|
@ -87,7 +87,7 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
|
|||||||
_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
|
_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.c.Contexts().LocalCommits.SetSelectedLineIdx(index)
|
self.c.Contexts().LocalCommits.SetSelection(index)
|
||||||
return self.c.PushContext(self.c.Contexts().LocalCommits)
|
return self.c.PushContext(self.c.Contexts().LocalCommits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,6 @@ func (self *MergeAndRebaseHelper) PromptForConflictHandling() error {
|
|||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
return self.c.PushContext(self.c.Contexts().Files)
|
return self.c.PushContext(self.c.Contexts().Files)
|
||||||
},
|
},
|
||||||
Key: 'v',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Label: fmt.Sprintf(self.c.Tr.AbortMenuItem, mode),
|
Label: fmt.Sprintf(self.c.Tr.AbortMenuItem, mode),
|
||||||
|
@ -69,14 +69,14 @@ func (self *MergeConflictsHelper) EscapeMerge() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsHelper) SetConflictsAndRender(path string, isFocused bool) (bool, error) {
|
func (self *MergeConflictsHelper) SetConflictsAndRender(path string) (bool, error) {
|
||||||
hasConflicts, err := self.setMergeStateWithoutLock(path)
|
hasConflicts, err := self.setMergeStateWithoutLock(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasConflicts {
|
if hasConflicts {
|
||||||
return true, self.context().Render(isFocused)
|
return true, self.context().Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -100,8 +100,8 @@ func (self *MergeConflictsHelper) context() *context.MergeConflictsContext {
|
|||||||
return self.c.Contexts().MergeConflicts
|
return self.c.Contexts().MergeConflicts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsHelper) Render(isFocused bool) error {
|
func (self *MergeConflictsHelper) Render() error {
|
||||||
content := self.context().GetContentToRender(isFocused)
|
content := self.context().GetContentToRender()
|
||||||
|
|
||||||
var task types.UpdateTask
|
var task types.UpdateTask
|
||||||
if self.context().IsUserScrolling() {
|
if self.context().IsUserScrolling() {
|
||||||
@ -127,7 +127,7 @@ func (self *MergeConflictsHelper) RefreshMergeState() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hasConflicts, err := self.SetConflictsAndRender(self.c.Contexts().MergeConflicts.GetState().GetPath(), true)
|
hasConflicts, err := self.SetConflictsAndRender(self.c.Contexts().MergeConflicts.GetState().GetPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return self.c.Error(err)
|
return self.c.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,9 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
|
|||||||
cmdOptions := git_commands.CheckoutOptions{Force: false, EnvVars: options.EnvVars}
|
cmdOptions := git_commands.CheckoutOptions{Force: false, EnvVars: options.EnvVars}
|
||||||
|
|
||||||
onSuccess := func() {
|
onSuccess := func() {
|
||||||
self.c.Contexts().Branches.SetSelectedLineIdx(0)
|
self.c.Contexts().Branches.SetSelection(0)
|
||||||
self.c.Contexts().ReflogCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().ReflogCommits.SetSelection(0)
|
||||||
self.c.Contexts().LocalCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||||
// loading a heap of commits is slow so we limit them whenever doing a reset
|
// loading a heap of commits is slow so we limit them whenever doing a reset
|
||||||
self.c.Contexts().LocalCommits.SetLimitCommits(true)
|
self.c.Contexts().LocalCommits.SetLimitCommits(true)
|
||||||
}
|
}
|
||||||
@ -107,8 +107,8 @@ func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string
|
|||||||
return self.c.Error(err)
|
return self.c.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.c.Contexts().LocalCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||||
self.c.Contexts().ReflogCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().ReflogCommits.SetSelection(0)
|
||||||
// loading a heap of commits is slow so we limit them whenever doing a reset
|
// loading a heap of commits is slow so we limit them whenever doing a reset
|
||||||
self.c.Contexts().LocalCommits.SetLimitCommits(true)
|
self.c.Contexts().LocalCommits.SetLimitCommits(true)
|
||||||
|
|
||||||
@ -215,8 +215,8 @@ func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.c.Contexts().LocalCommits.SetSelectedLineIdx(0)
|
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||||
self.c.Contexts().Branches.SetSelectedLineIdx(0)
|
self.c.Contexts().Branches.SetSelection(0)
|
||||||
|
|
||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||||
},
|
},
|
||||||
|
@ -216,7 +216,7 @@ func (self *SearchHelper) OnPromptContentChanged(searchString string) {
|
|||||||
state := self.searchState()
|
state := self.searchState()
|
||||||
switch context := state.Context.(type) {
|
switch context := state.Context.(type) {
|
||||||
case types.IFilterableContext:
|
case types.IFilterableContext:
|
||||||
context.SetSelectedLineIdx(0)
|
context.SetSelection(0)
|
||||||
_ = context.GetView().SetOriginY(0)
|
_ = context.GetView().SetOriginY(0)
|
||||||
context.SetFilter(searchString)
|
context.SetFilter(searchString)
|
||||||
_ = self.c.PostRefreshUpdate(context)
|
_ = self.c.PostRefreshUpdate(context)
|
||||||
@ -232,7 +232,7 @@ func (self *SearchHelper) ReApplyFilter(context types.Context) {
|
|||||||
if context == state.Context {
|
if context == state.Context {
|
||||||
filterableContext, ok := context.(types.IFilterableContext)
|
filterableContext, ok := context.(types.IFilterableContext)
|
||||||
if ok {
|
if ok {
|
||||||
filterableContext.SetSelectedLineIdx(0)
|
filterableContext.SetSelection(0)
|
||||||
_ = filterableContext.GetView().SetOriginY(0)
|
_ = filterableContext.GetView().SetOriginY(0)
|
||||||
filterableContext.ReApplyFilter()
|
filterableContext.ReApplyFilter()
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func (self *SubCommitsHelper) ViewSubCommits(opts ViewSubCommitsOpts) error {
|
|||||||
self.refreshHelper.RefreshAuthors(commits)
|
self.refreshHelper.RefreshAuthors(commits)
|
||||||
|
|
||||||
subCommitsContext := self.c.Contexts().SubCommits
|
subCommitsContext := self.c.Contexts().SubCommits
|
||||||
subCommitsContext.SetSelectedLineIdx(0)
|
subCommitsContext.SetSelection(0)
|
||||||
subCommitsContext.SetParentContext(opts.Context)
|
subCommitsContext.SetParentContext(opts.Context)
|
||||||
subCommitsContext.SetWindowName(opts.Context.GetWindowName())
|
subCommitsContext.SetWindowName(opts.Context.GetWindowName())
|
||||||
subCommitsContext.SetTitleRef(utils.TruncateWithEllipsis(opts.TitleRef, 50))
|
subCommitsContext.SetTitleRef(utils.TruncateWithEllipsis(opts.TitleRef, 50))
|
||||||
|
@ -14,11 +14,11 @@ type JumpToSideWindowController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewJumpToSideWindowController(
|
func NewJumpToSideWindowController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *JumpToSideWindowController {
|
) *JumpToSideWindowController {
|
||||||
return &JumpToSideWindowController{
|
return &JumpToSideWindowController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +71,25 @@ func (self *ListController) scrollHorizontal(scrollFunc func()) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ListController) handleLineChange(change int) error {
|
func (self *ListController) handleLineChange(change int) error {
|
||||||
before := self.context.GetList().GetSelectedLineIdx()
|
return self.handleLineChangeAux(
|
||||||
self.context.GetList().MoveSelectedLine(change)
|
self.context.GetList().MoveSelectedLine, change,
|
||||||
after := self.context.GetList().GetSelectedLineIdx()
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListController) HandleRangeSelectChange(change int) error {
|
||||||
|
return self.handleLineChangeAux(
|
||||||
|
self.context.GetList().ExpandNonStickyRange, change,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListController) handleLineChangeAux(f func(int), change int) error {
|
||||||
|
list := self.context.GetList()
|
||||||
|
|
||||||
|
rangeBefore := list.IsSelectingRange()
|
||||||
|
before := list.GetSelectedLineIdx()
|
||||||
|
f(change)
|
||||||
|
rangeAfter := list.IsSelectingRange()
|
||||||
|
after := list.GetSelectedLineIdx()
|
||||||
|
|
||||||
if err := self.pushContextIfNotFocused(); err != nil {
|
if err := self.pushContextIfNotFocused(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -81,7 +97,8 @@ func (self *ListController) handleLineChange(change int) error {
|
|||||||
|
|
||||||
// doing this check so that if we're holding the up key at the start of the list
|
// doing this check so that if we're holding the up key at the start of the list
|
||||||
// we're not constantly re-rendering the main view.
|
// we're not constantly re-rendering the main view.
|
||||||
if before != after {
|
cursorMoved := before != after
|
||||||
|
if cursorMoved {
|
||||||
if change == -1 {
|
if change == -1 {
|
||||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig,
|
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig,
|
||||||
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
||||||
@ -89,7 +106,9 @@ func (self *ListController) handleLineChange(change int) error {
|
|||||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig,
|
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig,
|
||||||
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursorMoved || rangeBefore != rangeAfter {
|
||||||
return self.context.HandleFocus(types.OnFocusOpts{})
|
return self.context.HandleFocus(types.OnFocusOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +131,22 @@ func (self *ListController) HandleGotoBottom() error {
|
|||||||
return self.handleLineChange(self.context.GetList().Len())
|
return self.handleLineChange(self.context.GetList().Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ListController) HandleToggleRangeSelect() error {
|
||||||
|
list := self.context.GetList()
|
||||||
|
|
||||||
|
list.ToggleStickyRange()
|
||||||
|
|
||||||
|
return self.context.HandleFocus(types.OnFocusOpts{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListController) HandleRangeSelectDown() error {
|
||||||
|
return self.HandleRangeSelectChange(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListController) HandleRangeSelectUp() error {
|
||||||
|
return self.HandleRangeSelectChange(-1)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *ListController) HandleClick(opts gocui.ViewMouseBindingOpts) error {
|
func (self *ListController) HandleClick(opts gocui.ViewMouseBindingOpts) error {
|
||||||
prevSelectedLineIdx := self.context.GetList().GetSelectedLineIdx()
|
prevSelectedLineIdx := self.context.GetList().GetSelectedLineIdx()
|
||||||
newSelectedLineIdx := self.context.ViewIndexToModelIndex(opts.Y)
|
newSelectedLineIdx := self.context.ViewIndexToModelIndex(opts.Y)
|
||||||
@ -125,7 +160,7 @@ func (self *ListController) HandleClick(opts gocui.ViewMouseBindingOpts) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.context.GetList().SetSelectedLineIdx(newSelectedLineIdx)
|
self.context.GetList().SetSelection(newSelectedLineIdx)
|
||||||
|
|
||||||
if prevSelectedLineIdx == newSelectedLineIdx && alreadyFocused && self.context.GetOnClick() != nil {
|
if prevSelectedLineIdx == newSelectedLineIdx && alreadyFocused && self.context.GetOnClick() != nil {
|
||||||
return self.context.GetOnClick()()
|
return self.context.GetOnClick()()
|
||||||
@ -148,7 +183,7 @@ func (self *ListController) isFocused() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ListController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *ListController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
return []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Handler: self.HandlePrevLine},
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Handler: self.HandlePrevLine},
|
||||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Handler: self.HandlePrevLine},
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Handler: self.HandlePrevLine},
|
||||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Handler: self.HandleNextLine},
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Handler: self.HandleNextLine},
|
||||||
@ -160,6 +195,18 @@ func (self *ListController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
|||||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollRight), Handler: self.HandleScrollRight},
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollRight), Handler: self.HandleScrollRight},
|
||||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Handler: self.HandleGotoBottom, Description: self.c.Tr.GotoBottom},
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Handler: self.HandleGotoBottom, Description: self.c.Tr.GotoBottom},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.context.RangeSelectEnabled() {
|
||||||
|
bindings = append(bindings,
|
||||||
|
[]*types.Binding{
|
||||||
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ToggleRangeSelect), Handler: self.HandleToggleRangeSelect, Description: self.c.Tr.ToggleRangeSelect},
|
||||||
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.RangeSelectDown), Handler: self.HandleRangeSelectDown, Description: self.c.Tr.RangeSelectDown},
|
||||||
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.RangeSelectUp), Handler: self.HandleRangeSelectUp, Description: self.c.Tr.RangeSelectUp},
|
||||||
|
}...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ListController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
func (self *ListController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
||||||
|
95
pkg/gui/controllers/list_controller_trait.go
Normal file
95
pkg/gui/controllers/list_controller_trait.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
|
||||||
|
// Embed this into your list controller to get some convenience methods for
|
||||||
|
// ensuring a single item is selected, etc.
|
||||||
|
|
||||||
|
type ListControllerTrait[T comparable] struct {
|
||||||
|
c *ControllerCommon
|
||||||
|
context types.IListContext
|
||||||
|
getSelected func() T
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListControllerTrait[T comparable](
|
||||||
|
c *ControllerCommon,
|
||||||
|
context types.IListContext,
|
||||||
|
getSelected func() T,
|
||||||
|
) *ListControllerTrait[T] {
|
||||||
|
return &ListControllerTrait[T]{
|
||||||
|
c: c,
|
||||||
|
context: context,
|
||||||
|
getSelected: getSelected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience function for combining multiple disabledReason callbacks.
|
||||||
|
// The first callback to return a disabled reason will be the one returned.
|
||||||
|
func (self *ListControllerTrait[T]) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
|
||||||
|
return func() *types.DisabledReason {
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
if disabledReason := callback(); disabledReason != nil {
|
||||||
|
return disabledReason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience function for enforcing that a single item is selected.
|
||||||
|
// Also takes callbacks for additional disabled reasons, and passes the selected
|
||||||
|
// item into each one.
|
||||||
|
func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *types.DisabledReason) func() *types.DisabledReason {
|
||||||
|
return func() *types.DisabledReason {
|
||||||
|
if self.context.GetList().AreMultipleItemsSelected() {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported}
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroValue T
|
||||||
|
item := self.getSelected()
|
||||||
|
if item == zeroValue {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
if reason := callback(item); reason != nil {
|
||||||
|
return reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passes the selected item to the callback. Used for handler functions.
|
||||||
|
func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() error {
|
||||||
|
return func() error {
|
||||||
|
var zeroValue T
|
||||||
|
commit := self.getSelected()
|
||||||
|
if commit == zeroValue {
|
||||||
|
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(commit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like withItem, but doesn't show an error message if no item is selected.
|
||||||
|
// Use this for click actions (it's a no-op to click empty space)
|
||||||
|
func (self *ListControllerTrait[T]) withItemGraceful(callback func(T) error) func() error {
|
||||||
|
return func() error {
|
||||||
|
var zeroValue T
|
||||||
|
commit := self.getSelected()
|
||||||
|
if commit == zeroValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(commit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All controllers must implement this method so we're defining it here for convenience
|
||||||
|
func (self *ListControllerTrait[T]) Context() types.Context {
|
||||||
|
return self.context
|
||||||
|
}
|
@ -25,6 +25,7 @@ type (
|
|||||||
|
|
||||||
type LocalCommitsController struct {
|
type LocalCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Commit]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
|
|
||||||
pullFiles PullFilesFn
|
pullFiles PullFilesFn
|
||||||
@ -33,13 +34,18 @@ type LocalCommitsController struct {
|
|||||||
var _ types.IController = &LocalCommitsController{}
|
var _ types.IController = &LocalCommitsController{}
|
||||||
|
|
||||||
func NewLocalCommitsController(
|
func NewLocalCommitsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
pullFiles PullFilesFn,
|
pullFiles PullFilesFn,
|
||||||
) *LocalCommitsController {
|
) *LocalCommitsController {
|
||||||
return &LocalCommitsController{
|
return &LocalCommitsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
pullFiles: pullFiles,
|
pullFiles: pullFiles,
|
||||||
|
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||||
|
c,
|
||||||
|
c.Contexts().LocalCommits,
|
||||||
|
c.Contexts().LocalCommits.GetSelected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,47 +54,59 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
|||||||
|
|
||||||
outsideFilterModeBindings := []*types.Binding{
|
outsideFilterModeBindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.SquashDown),
|
Key: opts.GetKey(opts.Config.Commits.SquashDown),
|
||||||
Handler: self.checkSelected(self.squashDown),
|
Handler: self.withItem(self.squashDown),
|
||||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForSquashDown),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.SquashDown,
|
self.singleItemSelected(self.getDisabledReasonForSquashDown),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.SquashDown,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup),
|
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup),
|
||||||
Handler: self.checkSelected(self.fixup),
|
Handler: self.withItem(self.fixup),
|
||||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForFixup),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.FixupCommit,
|
self.singleItemSelected(self.getDisabledReasonForFixup),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.FixupCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
|
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
|
||||||
Handler: self.checkSelected(self.reword),
|
Handler: self.withItem(self.reword),
|
||||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Reword),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.RewordCommit,
|
self.singleItemSelected(self.rebaseCommandEnabled(todo.Reword)),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.RewordCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.RenameCommitWithEditor),
|
Key: opts.GetKey(opts.Config.Commits.RenameCommitWithEditor),
|
||||||
Handler: self.checkSelected(self.rewordEditor),
|
Handler: self.withItem(self.rewordEditor),
|
||||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Reword),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.RenameCommitEditor,
|
self.singleItemSelected(self.rebaseCommandEnabled(todo.Reword)),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.RenameCommitEditor,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.drop),
|
Handler: self.withItem(self.drop),
|
||||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Drop),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.DeleteCommit,
|
self.singleItemSelected(self.rebaseCommandEnabled(todo.Drop)),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.DeleteCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(editCommitKey),
|
Key: opts.GetKey(editCommitKey),
|
||||||
Handler: self.checkSelected(self.edit),
|
Handler: self.withItem(self.edit),
|
||||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Edit),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.EditCommit,
|
self.singleItemSelected(self.rebaseCommandEnabled(todo.Edit)),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.EditCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// The user-facing description here is 'Start interactive rebase' but internally
|
// The user-facing description here is 'Start interactive rebase' but internally
|
||||||
// we're calling it 'quick-start interactive rebase' to differentiate it from
|
// we're calling it 'quick-start interactive rebase' to differentiate it from
|
||||||
// when you manually select the base commit.
|
// when you manually select the base commit.
|
||||||
Key: opts.GetKey(opts.Config.Commits.StartInteractiveRebase),
|
Key: opts.GetKey(opts.Config.Commits.StartInteractiveRebase),
|
||||||
Handler: self.checkSelected(self.quickStartInteractiveRebase),
|
Handler: self.withItem(self.quickStartInteractiveRebase),
|
||||||
GetDisabledReason: self.require(self.notMidRebase, self.canFindCommitForQuickStart),
|
GetDisabledReason: self.require(self.notMidRebase, self.canFindCommitForQuickStart),
|
||||||
Description: self.c.Tr.QuickStartInteractiveRebase,
|
Description: self.c.Tr.QuickStartInteractiveRebase,
|
||||||
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.QuickStartInteractiveRebaseTooltip, map[string]string{
|
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.QuickStartInteractiveRebaseTooltip, map[string]string{
|
||||||
@ -96,45 +114,50 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.PickCommit),
|
Key: opts.GetKey(opts.Config.Commits.PickCommit),
|
||||||
Handler: self.checkSelected(self.pick),
|
Handler: self.withItem(self.pick),
|
||||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Pick),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.PickCommit,
|
self.singleItemSelected(self.rebaseCommandEnabled(todo.Pick)),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.PickCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit),
|
Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit),
|
||||||
Handler: self.checkSelected(self.createFixupCommit),
|
Handler: self.withItem(self.createFixupCommit),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.CreateFixupCommitDescription,
|
Description: self.c.Tr.CreateFixupCommitDescription,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
|
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
|
||||||
Handler: self.checkSelected(self.squashAllAboveFixupCommits),
|
Handler: self.withItem(self.squashAllAboveFixupCommits),
|
||||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForSquashAllAboveFixupCommits),
|
GetDisabledReason: self.require(
|
||||||
Description: self.c.Tr.SquashAboveCommits,
|
self.notMidRebase,
|
||||||
|
self.singleItemSelected(),
|
||||||
|
),
|
||||||
|
Description: self.c.Tr.SquashAboveCommits,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
|
Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
|
||||||
Handler: self.checkSelected(self.moveDown),
|
Handler: self.withItem(self.moveDown),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.MoveDownCommit,
|
Description: self.c.Tr.MoveDownCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
|
Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
|
||||||
Handler: self.checkSelected(self.moveUp),
|
Handler: self.withItem(self.moveUp),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.MoveUpCommit,
|
Description: self.c.Tr.MoveUpCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.PasteCommits),
|
Key: opts.GetKey(opts.Config.Commits.PasteCommits),
|
||||||
Handler: self.paste,
|
Handler: self.paste,
|
||||||
GetDisabledReason: self.getDisabledReasonForPaste,
|
GetDisabledReason: self.require(self.canPaste),
|
||||||
Description: self.c.Tr.PasteCommits,
|
Description: self.c.Tr.PasteCommits,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
|
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
|
||||||
Handler: self.checkSelected(self.markAsBaseCommit),
|
Handler: self.withItem(self.markAsBaseCommit),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.MarkAsBaseCommit,
|
Description: self.c.Tr.MarkAsBaseCommit,
|
||||||
Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
|
Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
|
||||||
},
|
},
|
||||||
@ -161,27 +184,27 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
|||||||
bindings := append(outsideFilterModeBindings, []*types.Binding{
|
bindings := append(outsideFilterModeBindings, []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.AmendToCommit),
|
Key: opts.GetKey(opts.Config.Commits.AmendToCommit),
|
||||||
Handler: self.checkSelected(self.amendTo),
|
Handler: self.withItem(self.amendTo),
|
||||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
|
GetDisabledReason: self.require(self.singleItemSelected(self.canAmend)),
|
||||||
Description: self.c.Tr.AmendToCommit,
|
Description: self.c.Tr.AmendToCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ResetCommitAuthor),
|
Key: opts.GetKey(opts.Config.Commits.ResetCommitAuthor),
|
||||||
Handler: self.checkSelected(self.amendAttribute),
|
Handler: self.withItem(self.amendAttribute),
|
||||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
|
GetDisabledReason: self.require(self.singleItemSelected(self.canAmend)),
|
||||||
Description: self.c.Tr.SetResetCommitAuthor,
|
Description: self.c.Tr.SetResetCommitAuthor,
|
||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.RevertCommit),
|
Key: opts.GetKey(opts.Config.Commits.RevertCommit),
|
||||||
Handler: self.checkSelected(self.revert),
|
Handler: self.withItem(self.revert),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.RevertCommit,
|
Description: self.c.Tr.RevertCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.CreateTag),
|
Key: opts.GetKey(opts.Config.Commits.CreateTag),
|
||||||
Handler: self.checkSelected(self.createTag),
|
Handler: self.withItem(self.createTag),
|
||||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.TagCommit,
|
Description: self.c.Tr.TagCommit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -266,7 +289,7 @@ func (self *LocalCommitsController) getDisabledReasonForSquashDown(commit *model
|
|||||||
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.rebaseCommandEnabled(todo.Squash, commit)
|
return self.rebaseCommandEnabled(todo.Squash)(commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) fixup(commit *models.Commit) error {
|
func (self *LocalCommitsController) fixup(commit *models.Commit) error {
|
||||||
@ -295,7 +318,7 @@ func (self *LocalCommitsController) getDisabledReasonForFixup(commit *models.Com
|
|||||||
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.rebaseCommandEnabled(todo.Squash, commit)
|
return self.rebaseCommandEnabled(todo.Squash)(commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
||||||
@ -459,7 +482,7 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
|
|||||||
return c.Sha == selectedCommit.Sha
|
return c.Sha == selectedCommit.Sha
|
||||||
})
|
})
|
||||||
if ok {
|
if ok {
|
||||||
self.context().SetSelectedLineIdx(index)
|
self.context().SetSelection(index)
|
||||||
}
|
}
|
||||||
}})
|
}})
|
||||||
})
|
})
|
||||||
@ -528,36 +551,38 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoComma
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand, commit *models.Commit) *types.DisabledReason {
|
func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand) func(*models.Commit) *types.DisabledReason {
|
||||||
if commit.Action == models.ActionConflict {
|
return func(commit *models.Commit) *types.DisabledReason {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
if commit.Action == models.ActionConflict {
|
||||||
}
|
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||||
|
}
|
||||||
|
|
||||||
if !commit.IsTODO() {
|
if !commit.IsTODO() {
|
||||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||||
// If we are in a rebase, the only action that is allowed for
|
// If we are in a rebase, the only action that is allowed for
|
||||||
// non-todo commits is rewording the current head commit
|
// non-todo commits is rewording the current head commit
|
||||||
if !(action == todo.Reword && self.isHeadCommit()) {
|
if !(action == todo.Reword && self.isHeadCommit()) {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// for now we do not support setting 'reword' because it requires an editor
|
||||||
|
// and that means we either unconditionally wait around for the subprocess to ask for
|
||||||
|
// our input or we set a lazygit client as the EDITOR env variable and have it
|
||||||
|
// request us to edit the commit message when prompted.
|
||||||
|
if action == todo.Reword {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported}
|
||||||
|
}
|
||||||
|
|
||||||
|
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// for now we do not support setting 'reword' because it requires an editor
|
|
||||||
// and that means we either unconditionally wait around for the subprocess to ask for
|
|
||||||
// our input or we set a lazygit client as the EDITOR env variable and have it
|
|
||||||
// request us to edit the commit message when prompted.
|
|
||||||
if action == todo.Reword {
|
|
||||||
return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported}
|
|
||||||
}
|
|
||||||
|
|
||||||
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
|
|
||||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) moveDown(commit *models.Commit) error {
|
func (self *LocalCommitsController) moveDown(commit *models.Commit) error {
|
||||||
@ -687,7 +712,7 @@ func (self *LocalCommitsController) amendTo(commit *models.Commit) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) getDisabledReasonForAmendTo(commit *models.Commit) *types.DisabledReason {
|
func (self *LocalCommitsController) canAmend(commit *models.Commit) *types.DisabledReason {
|
||||||
if !self.isHeadCommit() && self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
if !self.isHeadCommit() && self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||||
}
|
}
|
||||||
@ -870,14 +895,6 @@ func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Co
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) getDisabledReasonForSquashAllAboveFixupCommits(commit *models.Commit) *types.DisabledReason {
|
|
||||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
|
||||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// For getting disabled reason
|
// For getting disabled reason
|
||||||
func (self *LocalCommitsController) notMidRebase() *types.DisabledReason {
|
func (self *LocalCommitsController) notMidRebase() *types.DisabledReason {
|
||||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||||
@ -1016,39 +1033,6 @@ func (self *LocalCommitsController) handleOpenLogMenu() error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) checkSelected(callback func(*models.Commit) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
commit := self.context().GetSelected()
|
|
||||||
if commit == nil {
|
|
||||||
// The enabled callback should have checked for this
|
|
||||||
panic("no commit selected")
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) *types.DisabledReason) func() *types.DisabledReason {
|
|
||||||
return func() *types.DisabledReason {
|
|
||||||
commit := self.context().GetSelected()
|
|
||||||
if commit == nil {
|
|
||||||
return &types.DisabledReason{Text: self.c.Tr.NoCommitSelected}
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() *types.DisabledReason {
|
|
||||||
return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) *types.DisabledReason { return nil })
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() *types.DisabledReason {
|
|
||||||
return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) *types.DisabledReason {
|
|
||||||
return self.rebaseCommandEnabled(action, commit)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||||
return func(types.OnFocusOpts) error {
|
return func(types.OnFocusOpts) error {
|
||||||
context := self.context()
|
context := self.context()
|
||||||
@ -1065,10 +1049,6 @@ func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *LocalCommitsController) context() *context.LocalCommitsContext {
|
func (self *LocalCommitsController) context() *context.LocalCommitsContext {
|
||||||
return self.c.Contexts().LocalCommits
|
return self.c.Contexts().LocalCommits
|
||||||
}
|
}
|
||||||
@ -1077,7 +1057,7 @@ func (self *LocalCommitsController) paste() error {
|
|||||||
return self.c.Helpers().CherryPick.Paste()
|
return self.c.Helpers().CherryPick.Paste()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) getDisabledReasonForPaste() *types.DisabledReason {
|
func (self *LocalCommitsController) canPaste() *types.DisabledReason {
|
||||||
if !self.c.Helpers().CherryPick.CanPaste() {
|
if !self.c.Helpers().CherryPick.CanPaste() {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.NoCopiedCommits}
|
return &types.DisabledReason{Text: self.c.Tr.NoCopiedCommits}
|
||||||
}
|
}
|
||||||
@ -1099,19 +1079,6 @@ func (self *LocalCommitsController) isHeadCommit() bool {
|
|||||||
return models.IsHeadCommit(self.c.Model().Commits, self.context().GetSelectedLineIdx())
|
return models.IsHeadCommit(self.c.Model().Commits, self.context().GetSelectedLineIdx())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience function for composing multiple disabled reason functions
|
|
||||||
func (self *LocalCommitsController) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
|
|
||||||
return func() *types.DisabledReason {
|
|
||||||
for _, callback := range callbacks {
|
|
||||||
if disabledReason := callback(); disabledReason != nil {
|
|
||||||
return disabledReason
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isChangeOfRebaseTodoAllowed(action todo.TodoCommand) bool {
|
func isChangeOfRebaseTodoAllowed(action todo.TodoCommand) bool {
|
||||||
allowedActions := []todo.TodoCommand{
|
allowedActions := []todo.TodoCommand{
|
||||||
todo.Pick,
|
todo.Pick,
|
||||||
|
@ -7,17 +7,23 @@ import (
|
|||||||
|
|
||||||
type MenuController struct {
|
type MenuController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*types.MenuItem]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &MenuController{}
|
var _ types.IController = &MenuController{}
|
||||||
|
|
||||||
func NewMenuController(
|
func NewMenuController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *MenuController {
|
) *MenuController {
|
||||||
return &MenuController{
|
return &MenuController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*types.MenuItem](
|
||||||
|
c,
|
||||||
|
c.Contexts().Menu,
|
||||||
|
c.Contexts().Menu.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,14 +32,16 @@ func NewMenuController(
|
|||||||
func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.press,
|
Handler: self.withItem(self.press),
|
||||||
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
Handler: self.press,
|
Handler: self.withItem(self.press),
|
||||||
Description: self.c.Tr.Execute,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Display: true,
|
Description: self.c.Tr.Execute,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
@ -47,7 +55,7 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuController) GetOnClick() func() error {
|
func (self *MenuController) GetOnClick() func() error {
|
||||||
return self.press
|
return self.withItemGraceful(self.press)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
|
func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||||
@ -60,8 +68,8 @@ func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuController) press() error {
|
func (self *MenuController) press(selectedItem *types.MenuItem) error {
|
||||||
return self.context().OnMenuPress(self.context().GetSelected())
|
return self.context().OnMenuPress(selectedItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuController) close() error {
|
func (self *MenuController) close() error {
|
||||||
@ -73,10 +81,6 @@ func (self *MenuController) close() error {
|
|||||||
return self.c.PopContext()
|
return self.c.PopContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MenuController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *MenuController) context() *context.MenuContext {
|
func (self *MenuController) context() *context.MenuContext {
|
||||||
return self.c.Contexts().Menu
|
return self.c.Contexts().Menu
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ type MergeConflictsController struct {
|
|||||||
var _ types.IController = &MergeConflictsController{}
|
var _ types.IController = &MergeConflictsController{}
|
||||||
|
|
||||||
func NewMergeConflictsController(
|
func NewMergeConflictsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *MergeConflictsController {
|
) *MergeConflictsController {
|
||||||
return &MergeConflictsController{
|
return &MergeConflictsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,13 @@ func (self *MergeConflictsController) GetOnFocus() func(types.OnFocusOpts) error
|
|||||||
return func(types.OnFocusOpts) error {
|
return func(types.OnFocusOpts) error {
|
||||||
self.c.Views().MergeConflicts.Wrap = false
|
self.c.Views().MergeConflicts.Wrap = false
|
||||||
|
|
||||||
return self.c.Helpers().MergeConflicts.Render(true)
|
if err := self.c.Helpers().MergeConflicts.Render(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.context().SetSelectedLineRange()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,17 +319,13 @@ func (self *MergeConflictsController) onLastConflictResolved() error {
|
|||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsController) isFocused() bool {
|
|
||||||
return self.c.CurrentContext().GetKey() == self.context().GetKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *MergeConflictsController) withRenderAndFocus(f func() error) func() error {
|
func (self *MergeConflictsController) withRenderAndFocus(f func() error) func() error {
|
||||||
return self.withLock(func() error {
|
return self.withLock(func() error {
|
||||||
if err := f(); err != nil {
|
if err := f(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.context().RenderAndFocus(self.isFocused())
|
return self.context().RenderAndFocus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@ type PatchBuildingController struct {
|
|||||||
var _ types.IController = &PatchBuildingController{}
|
var _ types.IController = &PatchBuildingController{}
|
||||||
|
|
||||||
func NewPatchBuildingController(
|
func NewPatchBuildingController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *PatchBuildingController {
|
) *PatchBuildingController {
|
||||||
return &PatchBuildingController{
|
return &PatchBuildingController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,5 +154,13 @@ func (self *PatchBuildingController) toggleSelection() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchBuildingController) Escape() error {
|
func (self *PatchBuildingController) Escape() error {
|
||||||
|
context := self.c.Contexts().CustomPatchBuilder
|
||||||
|
state := context.GetState()
|
||||||
|
|
||||||
|
if state.SelectingRange() || state.SelectingHunk() {
|
||||||
|
state.SetLineSelectMode()
|
||||||
|
return self.c.PostRefreshUpdate(context)
|
||||||
|
}
|
||||||
|
|
||||||
return self.c.Helpers().PatchBuilding.Escape()
|
return self.c.Helpers().PatchBuilding.Escape()
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,18 @@ func (self *PatchExplorerController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||||
Handler: self.withRenderAndFocus(self.HandleNextLine),
|
Handler: self.withRenderAndFocus(self.HandleNextLine),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Tag: "navigation",
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.RangeSelectUp),
|
||||||
|
Handler: self.withRenderAndFocus(self.HandlePrevLineRange),
|
||||||
|
Description: self.c.Tr.RangeSelectUp,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Tag: "navigation",
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.RangeSelectDown),
|
||||||
|
Handler: self.withRenderAndFocus(self.HandleNextLineRange),
|
||||||
|
Description: self.c.Tr.RangeSelectDown,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
||||||
Handler: self.withRenderAndFocus(self.HandlePrevHunk),
|
Handler: self.withRenderAndFocus(self.HandlePrevHunk),
|
||||||
@ -75,14 +87,9 @@ func (self *PatchExplorerController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Handler: self.withRenderAndFocus(self.HandleNextHunk),
|
Handler: self.withRenderAndFocus(self.HandleNextHunk),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Main.ToggleDragSelect),
|
Key: opts.GetKey(opts.Config.Universal.ToggleRangeSelect),
|
||||||
Handler: self.withRenderAndFocus(self.HandleToggleSelectRange),
|
Handler: self.withRenderAndFocus(self.HandleToggleSelectRange),
|
||||||
Description: self.c.Tr.ToggleDragSelect,
|
Description: self.c.Tr.ToggleRangeSelect,
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: opts.GetKey(opts.Config.Main.ToggleDragSelectAlt),
|
|
||||||
Handler: self.withRenderAndFocus(self.HandleToggleSelectRange),
|
|
||||||
Description: self.c.Tr.ToggleDragSelect,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Main.ToggleSelectHunk),
|
Key: opts.GetKey(opts.Config.Main.ToggleSelectHunk),
|
||||||
@ -182,6 +189,22 @@ func (self *PatchExplorerController) HandleNextLine() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *PatchExplorerController) HandlePrevLineRange() error {
|
||||||
|
s := self.context.GetState()
|
||||||
|
|
||||||
|
s.CycleRange(false)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *PatchExplorerController) HandleNextLineRange() error {
|
||||||
|
s := self.context.GetState()
|
||||||
|
|
||||||
|
s.CycleRange(true)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *PatchExplorerController) HandlePrevHunk() error {
|
func (self *PatchExplorerController) HandlePrevHunk() error {
|
||||||
self.context.GetState().CycleHunk(false)
|
self.context.GetState().CycleHunk(false)
|
||||||
|
|
||||||
@ -195,7 +218,7 @@ func (self *PatchExplorerController) HandleNextHunk() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchExplorerController) HandleToggleSelectRange() error {
|
func (self *PatchExplorerController) HandleToggleSelectRange() error {
|
||||||
self.context.GetState().ToggleSelectRange()
|
self.context.GetState().ToggleStickySelectRange()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,13 @@ func (self *QuitActions) confirmQuitDuringUpdate() error {
|
|||||||
func (self *QuitActions) Escape() error {
|
func (self *QuitActions) Escape() error {
|
||||||
currentContext := self.c.CurrentContext()
|
currentContext := self.c.CurrentContext()
|
||||||
|
|
||||||
|
if listContext, ok := currentContext.(types.IListContext); ok {
|
||||||
|
if listContext.GetList().IsSelectingRange() {
|
||||||
|
listContext.GetList().CancelRangeSelect()
|
||||||
|
return self.c.PostRefreshUpdate(listContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch ctx := currentContext.(type) {
|
switch ctx := currentContext.(type) {
|
||||||
case types.IFilterableContext:
|
case types.IFilterableContext:
|
||||||
if ctx.IsFiltering() {
|
if ctx.IsFiltering() {
|
||||||
|
@ -1,23 +1,30 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReflogCommitsController struct {
|
type ReflogCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Commit]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &ReflogCommitsController{}
|
var _ types.IController = &ReflogCommitsController{}
|
||||||
|
|
||||||
func NewReflogCommitsController(
|
func NewReflogCommitsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *ReflogCommitsController {
|
) *ReflogCommitsController {
|
||||||
return &ReflogCommitsController{
|
return &ReflogCommitsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||||
|
c,
|
||||||
|
c.Contexts().ReflogCommits,
|
||||||
|
c.Contexts().ReflogCommits.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,17 +11,23 @@ import (
|
|||||||
|
|
||||||
type RemoteBranchesController struct {
|
type RemoteBranchesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.RemoteBranch]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &RemoteBranchesController{}
|
var _ types.IController = &RemoteBranchesController{}
|
||||||
|
|
||||||
func NewRemoteBranchesController(
|
func NewRemoteBranchesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *RemoteBranchesController {
|
) *RemoteBranchesController {
|
||||||
return &RemoteBranchesController{
|
return &RemoteBranchesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.RemoteBranch](
|
||||||
|
c,
|
||||||
|
c.Contexts().RemoteBranches,
|
||||||
|
c.Contexts().RemoteBranches.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,33 +36,39 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
// gonna use the exact same handler as the 'n' keybinding because everybody wants this to happen when they checkout a remote branch
|
// gonna use the exact same handler as the 'n' keybinding because everybody wants this to happen when they checkout a remote branch
|
||||||
Handler: self.checkSelected(self.newLocalBranch),
|
Handler: self.withItem(self.newLocalBranch),
|
||||||
Description: self.c.Tr.Checkout,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.Checkout,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
Handler: self.checkSelected(self.newLocalBranch),
|
Handler: self.withItem(self.newLocalBranch),
|
||||||
Description: self.c.Tr.NewBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.NewBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.merge)),
|
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.merge)),
|
||||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.rebase)),
|
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.rebase)),
|
||||||
Description: self.c.Tr.RebaseBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.RebaseBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.delete),
|
Handler: self.withItem(self.delete),
|
||||||
Description: self.c.Tr.DeleteRemoteTag,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.DeleteRemoteTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||||
Handler: self.checkSelected(self.setAsUpstream),
|
Handler: self.withItem(self.setAsUpstream),
|
||||||
Description: self.c.Tr.SetAsUpstream,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.SetAsUpstream,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
||||||
@ -65,10 +77,11 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||||
Handler: self.checkSelected(self.createResetMenu),
|
Handler: self.withItem(self.createResetMenu),
|
||||||
Description: self.c.Tr.ViewResetOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewResetOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,25 +109,10 @@ func (self *RemoteBranchesController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *RemoteBranchesController) context() *context.RemoteBranchesContext {
|
func (self *RemoteBranchesController) context() *context.RemoteBranchesContext {
|
||||||
return self.c.Contexts().RemoteBranches
|
return self.c.Contexts().RemoteBranches
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesController) checkSelected(callback func(*models.RemoteBranch) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
selectedItem := self.context().GetSelected()
|
|
||||||
if selectedItem == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(selectedItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch) error {
|
func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch) error {
|
||||||
return self.c.Helpers().BranchesHelper.ConfirmDeleteRemote(selectedBranch.RemoteName, selectedBranch.Name)
|
return self.c.Helpers().BranchesHelper.ConfirmDeleteRemote(selectedBranch.RemoteName, selectedBranch.Name)
|
||||||
}
|
}
|
||||||
@ -132,7 +130,7 @@ func (self *RemoteBranchesController) createSortMenu() error {
|
|||||||
if self.c.GetAppState().RemoteBranchSortOrder != sortOrder {
|
if self.c.GetAppState().RemoteBranchSortOrder != sortOrder {
|
||||||
self.c.GetAppState().RemoteBranchSortOrder = sortOrder
|
self.c.GetAppState().RemoteBranchSortOrder = sortOrder
|
||||||
self.c.SaveAppStateAndLogError()
|
self.c.SaveAppStateAndLogError()
|
||||||
self.c.Contexts().RemoteBranches.SetSelectedLineIdx(0)
|
self.c.Contexts().RemoteBranches.SetSelection(0)
|
||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.REMOTES}})
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.REMOTES}})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
type RemotesController struct {
|
type RemotesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Remote]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
|
|
||||||
setRemoteBranches func([]*models.RemoteBranch)
|
setRemoteBranches func([]*models.RemoteBranch)
|
||||||
@ -22,12 +23,17 @@ type RemotesController struct {
|
|||||||
var _ types.IController = &RemotesController{}
|
var _ types.IController = &RemotesController{}
|
||||||
|
|
||||||
func NewRemotesController(
|
func NewRemotesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
setRemoteBranches func([]*models.RemoteBranch),
|
setRemoteBranches func([]*models.RemoteBranch),
|
||||||
) *RemotesController {
|
) *RemotesController {
|
||||||
return &RemotesController{
|
return &RemotesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Remote](
|
||||||
|
c,
|
||||||
|
c.Contexts().Remotes,
|
||||||
|
c.Contexts().Remotes.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
setRemoteBranches: setRemoteBranches,
|
setRemoteBranches: setRemoteBranches,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,13 +41,15 @@ func NewRemotesController(
|
|||||||
func (self *RemotesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *RemotesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.FetchRemote),
|
Key: opts.GetKey(opts.Config.Branches.FetchRemote),
|
||||||
Handler: self.checkSelected(self.fetch),
|
Handler: self.withItem(self.fetch),
|
||||||
Description: self.c.Tr.FetchRemote,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.FetchRemote,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
@ -49,24 +57,22 @@ func (self *RemotesController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
|||||||
Description: self.c.Tr.AddNewRemote,
|
Description: self.c.Tr.AddNewRemote,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.remove),
|
Handler: self.withItem(self.remove),
|
||||||
Description: self.c.Tr.RemoveRemote,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.RemoveRemote,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||||
Handler: self.checkSelected(self.edit),
|
Handler: self.withItem(self.edit),
|
||||||
Description: self.c.Tr.EditRemote,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EditRemote,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemotesController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *RemotesController) context() *context.RemotesContext {
|
func (self *RemotesController) context() *context.RemotesContext {
|
||||||
return self.c.Contexts().Remotes
|
return self.c.Contexts().Remotes
|
||||||
}
|
}
|
||||||
@ -94,7 +100,7 @@ func (self *RemotesController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemotesController) GetOnClick() func() error {
|
func (self *RemotesController) GetOnClick() func() error {
|
||||||
return self.checkSelected(self.enter)
|
return self.withItemGraceful(self.enter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemotesController) enter(remote *models.Remote) error {
|
func (self *RemotesController) enter(remote *models.Remote) error {
|
||||||
@ -106,7 +112,7 @@ func (self *RemotesController) enter(remote *models.Remote) error {
|
|||||||
newSelectedLine = -1
|
newSelectedLine = -1
|
||||||
}
|
}
|
||||||
remoteBranchesContext := self.c.Contexts().RemoteBranches
|
remoteBranchesContext := self.c.Contexts().RemoteBranches
|
||||||
remoteBranchesContext.SetSelectedLineIdx(newSelectedLine)
|
remoteBranchesContext.SetSelection(newSelectedLine)
|
||||||
remoteBranchesContext.SetTitleRef(remote.Name)
|
remoteBranchesContext.SetTitleRef(remote.Name)
|
||||||
remoteBranchesContext.SetParentContext(self.Context())
|
remoteBranchesContext.SetParentContext(self.Context())
|
||||||
remoteBranchesContext.GetView().TitlePrefix = self.Context().GetView().TitlePrefix
|
remoteBranchesContext.GetView().TitlePrefix = self.Context().GetView().TitlePrefix
|
||||||
@ -208,14 +214,3 @@ func (self *RemotesController) fetch(remote *models.Remote) error {
|
|||||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemotesController) checkSelected(callback func(*models.Remote) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
file := self.context().GetSelected()
|
|
||||||
if file == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -13,11 +13,11 @@ type SearchPromptController struct {
|
|||||||
var _ types.IController = &SearchPromptController{}
|
var _ types.IController = &SearchPromptController{}
|
||||||
|
|
||||||
func NewSearchPromptController(
|
func NewSearchPromptController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *SearchPromptController {
|
) *SearchPromptController {
|
||||||
return &SearchPromptController{
|
return &SearchPromptController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ type SideWindowControllerFactory struct {
|
|||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSideWindowControllerFactory(common *ControllerCommon) *SideWindowControllerFactory {
|
func NewSideWindowControllerFactory(c *ControllerCommon) *SideWindowControllerFactory {
|
||||||
return &SideWindowControllerFactory{c: common}
|
return &SideWindowControllerFactory{c: c}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideWindowControllerFactory) Create(context types.Context) types.IController {
|
func (self *SideWindowControllerFactory) Create(context types.Context) types.IController {
|
||||||
@ -24,12 +24,12 @@ type SideWindowController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSideWindowController(
|
func NewSideWindowController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
context types.Context,
|
context types.Context,
|
||||||
) *SideWindowController {
|
) *SideWindowController {
|
||||||
return &SideWindowController{
|
return &SideWindowController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@ type SnakeController struct {
|
|||||||
var _ types.IController = &SnakeController{}
|
var _ types.IController = &SnakeController{}
|
||||||
|
|
||||||
func NewSnakeController(
|
func NewSnakeController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *SnakeController {
|
) *SnakeController {
|
||||||
return &SnakeController{
|
return &SnakeController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,14 +23,14 @@ type StagingController struct {
|
|||||||
var _ types.IController = &StagingController{}
|
var _ types.IController = &StagingController{}
|
||||||
|
|
||||||
func NewStagingController(
|
func NewStagingController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
context types.IPatchExplorerContext,
|
context types.IPatchExplorerContext,
|
||||||
otherContext types.IPatchExplorerContext,
|
otherContext types.IPatchExplorerContext,
|
||||||
staged bool,
|
staged bool,
|
||||||
) *StagingController {
|
) *StagingController {
|
||||||
return &StagingController{
|
return &StagingController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
otherContext: otherContext,
|
otherContext: otherContext,
|
||||||
staged: staged,
|
staged: staged,
|
||||||
@ -151,6 +151,11 @@ func (self *StagingController) EditFile() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *StagingController) Escape() error {
|
func (self *StagingController) Escape() error {
|
||||||
|
if self.context.GetState().SelectingRange() || self.context.GetState().SelectingHunk() {
|
||||||
|
self.context.GetState().SetLineSelectMode()
|
||||||
|
return self.c.PostRefreshUpdate(self.context)
|
||||||
|
}
|
||||||
|
|
||||||
return self.c.PopContext()
|
return self.c.PopContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,46 +9,57 @@ import (
|
|||||||
|
|
||||||
type StashController struct {
|
type StashController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.StashEntry]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &StashController{}
|
var _ types.IController = &StashController{}
|
||||||
|
|
||||||
func NewStashController(
|
func NewStashController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *StashController {
|
) *StashController {
|
||||||
return &StashController{
|
return &StashController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.StashEntry](
|
||||||
|
c,
|
||||||
|
c.Contexts().Stash,
|
||||||
|
c.Contexts().Stash.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *StashController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelected(self.handleStashApply),
|
Handler: self.withItem(self.handleStashApply),
|
||||||
Description: self.c.Tr.Apply,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.Apply,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Stash.PopStash),
|
Key: opts.GetKey(opts.Config.Stash.PopStash),
|
||||||
Handler: self.checkSelected(self.handleStashPop),
|
Handler: self.withItem(self.handleStashPop),
|
||||||
Description: self.c.Tr.Pop,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.Pop,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.handleStashDrop),
|
Handler: self.withItem(self.handleStashDrop),
|
||||||
Description: self.c.Tr.Drop,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.Drop,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
Handler: self.checkSelected(self.handleNewBranchOffStashEntry),
|
Handler: self.withItem(self.handleNewBranchOffStashEntry),
|
||||||
Description: self.c.Tr.NewBranch,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.NewBranch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Stash.RenameStash),
|
Key: opts.GetKey(opts.Config.Stash.RenameStash),
|
||||||
Handler: self.checkSelected(self.handleRenameStashEntry),
|
Handler: self.withItem(self.handleRenameStashEntry),
|
||||||
Description: self.c.Tr.RenameStash,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.RenameStash,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,21 +91,6 @@ func (self *StashController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashController) checkSelected(callback func(*models.StashEntry) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
item := self.context().GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *StashController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *StashController) context() *context.StashContext {
|
func (self *StashController) context() *context.StashContext {
|
||||||
return self.c.Contexts().Stash
|
return self.c.Contexts().Stash
|
||||||
}
|
}
|
||||||
@ -189,7 +185,7 @@ func (self *StashController) handleRenameStashEntry(stashEntry *models.StashEntr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.context().SetSelectedLineIdx(0) // Select the renamed stash
|
self.context().SetSelection(0) // Select the renamed stash
|
||||||
self.context().FocusLine()
|
self.context().FocusLine()
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -22,11 +22,11 @@ type StatusController struct {
|
|||||||
var _ types.IController = &StatusController{}
|
var _ types.IController = &StatusController{}
|
||||||
|
|
||||||
func NewStatusController(
|
func NewStatusController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *StatusController {
|
) *StatusController {
|
||||||
return &StatusController{
|
return &StatusController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,23 +2,30 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SubCommitsController struct {
|
type SubCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Commit]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &SubCommitsController{}
|
var _ types.IController = &SubCommitsController{}
|
||||||
|
|
||||||
func NewSubCommitsController(
|
func NewSubCommitsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *SubCommitsController {
|
) *SubCommitsController {
|
||||||
return &SubCommitsController{
|
return &SubCommitsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||||
|
c,
|
||||||
|
c.Contexts().SubCommits,
|
||||||
|
c.Contexts().SubCommits.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,41 +14,51 @@ import (
|
|||||||
|
|
||||||
type SubmodulesController struct {
|
type SubmodulesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.SubmoduleConfig]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &SubmodulesController{}
|
var _ types.IController = &SubmodulesController{}
|
||||||
|
|
||||||
func NewSubmodulesController(
|
func NewSubmodulesController(
|
||||||
controllerCommon *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *SubmodulesController {
|
) *SubmodulesController {
|
||||||
return &SubmodulesController{
|
return &SubmodulesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: controllerCommon,
|
ListControllerTrait: NewListControllerTrait[*models.SubmoduleConfig](
|
||||||
|
c,
|
||||||
|
c.Contexts().Submodules,
|
||||||
|
c.Contexts().Submodules.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
return []*types.Binding{
|
return []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.EnterSubmodule,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EnterSubmodule,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.EnterSubmodule,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EnterSubmodule,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.remove),
|
Handler: self.withItem(self.remove),
|
||||||
Description: self.c.Tr.RemoveSubmodule,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.RemoveSubmodule,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Submodules.Update),
|
Key: opts.GetKey(opts.Config.Submodules.Update),
|
||||||
Handler: self.checkSelected(self.update),
|
Handler: self.withItem(self.update),
|
||||||
Description: self.c.Tr.SubmoduleUpdate,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.SubmoduleUpdate,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
@ -56,14 +66,16 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
|
|||||||
Description: self.c.Tr.AddSubmodule,
|
Description: self.c.Tr.AddSubmodule,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||||
Handler: self.checkSelected(self.editURL),
|
Handler: self.withItem(self.editURL),
|
||||||
Description: self.c.Tr.EditSubmoduleUrl,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.EditSubmoduleUrl,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Submodules.Init),
|
Key: opts.GetKey(opts.Config.Submodules.Init),
|
||||||
Handler: self.checkSelected(self.init),
|
Handler: self.withItem(self.init),
|
||||||
Description: self.c.Tr.InitSubmodule,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.InitSubmodule,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Submodules.BulkMenu),
|
Key: opts.GetKey(opts.Config.Submodules.BulkMenu),
|
||||||
@ -80,7 +92,7 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmodulesController) GetOnClick() func() error {
|
func (self *SubmodulesController) GetOnClick() func() error {
|
||||||
return self.checkSelected(self.enter)
|
return self.withItemGraceful(self.enter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmodulesController) GetOnRenderToMain() func() error {
|
func (self *SubmodulesController) GetOnRenderToMain() func() error {
|
||||||
@ -265,21 +277,6 @@ func (self *SubmodulesController) easterEgg() error {
|
|||||||
return self.c.PushContext(self.c.Contexts().Snake)
|
return self.c.PushContext(self.c.Contexts().Snake)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmodulesController) checkSelected(callback func(*models.SubmoduleConfig) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
submodule := self.context().GetSelected()
|
|
||||||
if submodule == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(submodule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SubmodulesController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SubmodulesController) context() *context.SubmodulesContext {
|
func (self *SubmodulesController) context() *context.SubmodulesContext {
|
||||||
return self.c.Contexts().Submodules
|
return self.c.Contexts().Submodules
|
||||||
}
|
}
|
||||||
|
@ -7,25 +7,32 @@ import (
|
|||||||
|
|
||||||
type SuggestionsController struct {
|
type SuggestionsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*types.Suggestion]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &SuggestionsController{}
|
var _ types.IController = &SuggestionsController{}
|
||||||
|
|
||||||
func NewSuggestionsController(
|
func NewSuggestionsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *SuggestionsController {
|
) *SuggestionsController {
|
||||||
return &SuggestionsController{
|
return &SuggestionsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*types.Suggestion](
|
||||||
|
c,
|
||||||
|
c.Contexts().Suggestions,
|
||||||
|
c.Contexts().Suggestions.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
Handler: func() error { return self.context().State.OnConfirm() },
|
Handler: func() error { return self.context().State.OnConfirm() },
|
||||||
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
@ -47,10 +54,6 @@ func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SuggestionsController) context() *context.SuggestionsContext {
|
func (self *SuggestionsController) context() *context.SuggestionsContext {
|
||||||
return self.c.Contexts().Suggestions
|
return self.c.Contexts().Suggestions
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,16 @@ import (
|
|||||||
var _ types.IController = &SwitchToDiffFilesController{}
|
var _ types.IController = &SwitchToDiffFilesController{}
|
||||||
|
|
||||||
type CanSwitchToDiffFiles interface {
|
type CanSwitchToDiffFiles interface {
|
||||||
types.Context
|
types.IListContext
|
||||||
CanRebase() bool
|
CanRebase() bool
|
||||||
GetSelectedRef() types.Ref
|
GetSelectedRef() types.Ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not using our ListControllerTrait because our 'selected' item is not a list item
|
||||||
|
// but an attribute on it i.e. the ref of an item.
|
||||||
type SwitchToDiffFilesController struct {
|
type SwitchToDiffFilesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[types.Ref]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context CanSwitchToDiffFiles
|
context CanSwitchToDiffFiles
|
||||||
diffFilesContext *context.CommitFilesContext
|
diffFilesContext *context.CommitFilesContext
|
||||||
@ -28,7 +31,12 @@ func NewSwitchToDiffFilesController(
|
|||||||
diffFilesContext *context.CommitFilesContext,
|
diffFilesContext *context.CommitFilesContext,
|
||||||
) *SwitchToDiffFilesController {
|
) *SwitchToDiffFilesController {
|
||||||
return &SwitchToDiffFilesController{
|
return &SwitchToDiffFilesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
|
ListControllerTrait: NewListControllerTrait[types.Ref](
|
||||||
|
c,
|
||||||
|
context,
|
||||||
|
context.GetSelectedRef,
|
||||||
|
),
|
||||||
c: c,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
diffFilesContext: diffFilesContext,
|
diffFilesContext: diffFilesContext,
|
||||||
@ -38,9 +46,10 @@ func NewSwitchToDiffFilesController(
|
|||||||
func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.ViewItemFiles,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.ViewItemFiles,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,18 +57,7 @@ func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *SwitchToDiffFilesController) GetOnClick() func() error {
|
func (self *SwitchToDiffFilesController) GetOnClick() func() error {
|
||||||
return self.checkSelected(self.enter)
|
return self.withItemGraceful(self.enter)
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SwitchToDiffFilesController) checkSelected(callback func(types.Ref) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
ref := self.context.GetSelectedRef()
|
|
||||||
if ref == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(ref)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SwitchToDiffFilesController) enter(ref types.Ref) error {
|
func (self *SwitchToDiffFilesController) enter(ref types.Ref) error {
|
||||||
@ -70,14 +68,10 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SwitchToDiffFilesController) Context() types.Context {
|
|
||||||
return self.context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesContextOpts) error {
|
func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesContextOpts) error {
|
||||||
diffFilesContext := self.diffFilesContext
|
diffFilesContext := self.diffFilesContext
|
||||||
|
|
||||||
diffFilesContext.SetSelectedLineIdx(0)
|
diffFilesContext.SetSelection(0)
|
||||||
diffFilesContext.SetRef(opts.Ref)
|
diffFilesContext.SetRef(opts.Ref)
|
||||||
diffFilesContext.SetTitleRef(opts.Ref.Description())
|
diffFilesContext.SetTitleRef(opts.Ref.Description())
|
||||||
diffFilesContext.SetCanRebase(opts.CanRebase)
|
diffFilesContext.SetCanRebase(opts.CanRebase)
|
||||||
|
@ -8,34 +8,43 @@ import (
|
|||||||
var _ types.IController = &SwitchToSubCommitsController{}
|
var _ types.IController = &SwitchToSubCommitsController{}
|
||||||
|
|
||||||
type CanSwitchToSubCommits interface {
|
type CanSwitchToSubCommits interface {
|
||||||
types.Context
|
types.IListContext
|
||||||
GetSelectedRef() types.Ref
|
GetSelectedRef() types.Ref
|
||||||
ShowBranchHeadsInSubCommits() bool
|
ShowBranchHeadsInSubCommits() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not using our ListControllerTrait because our 'selected' item is not a list item
|
||||||
|
// but an attribute on it i.e. the ref of an item.
|
||||||
type SwitchToSubCommitsController struct {
|
type SwitchToSubCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[types.Ref]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context CanSwitchToSubCommits
|
context CanSwitchToSubCommits
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwitchToSubCommitsController(
|
func NewSwitchToSubCommitsController(
|
||||||
controllerCommon *ControllerCommon,
|
c *ControllerCommon,
|
||||||
context CanSwitchToSubCommits,
|
context CanSwitchToSubCommits,
|
||||||
) *SwitchToSubCommitsController {
|
) *SwitchToSubCommitsController {
|
||||||
return &SwitchToSubCommitsController{
|
return &SwitchToSubCommitsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: controllerCommon,
|
ListControllerTrait: NewListControllerTrait[types.Ref](
|
||||||
context: context,
|
c,
|
||||||
|
context,
|
||||||
|
context.GetSelectedRef,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
|
context: context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SwitchToSubCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *SwitchToSubCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Handler: self.viewCommits,
|
Handler: self.viewCommits,
|
||||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
Description: self.c.Tr.ViewCommits,
|
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||||
|
Description: self.c.Tr.ViewCommits,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +68,3 @@ func (self *SwitchToSubCommitsController) viewCommits() error {
|
|||||||
ShowBranchHeads: self.context.ShowBranchHeadsInSubCommits(),
|
ShowBranchHeads: self.context.ShowBranchHeadsInSubCommits(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SwitchToSubCommitsController) Context() types.Context {
|
|
||||||
return self.context
|
|
||||||
}
|
|
||||||
|
@ -10,37 +10,46 @@ import (
|
|||||||
|
|
||||||
type TagsController struct {
|
type TagsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Tag]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &TagsController{}
|
var _ types.IController = &TagsController{}
|
||||||
|
|
||||||
func NewTagsController(
|
func NewTagsController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *TagsController {
|
) *TagsController {
|
||||||
return &TagsController{
|
return &TagsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Tag](
|
||||||
|
c,
|
||||||
|
c.Contexts().Tags,
|
||||||
|
c.Contexts().Tags.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.withSelectedTag(self.checkout),
|
Handler: self.withItem(self.checkout),
|
||||||
Description: self.c.Tr.Checkout,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.Checkout,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.withSelectedTag(self.delete),
|
Handler: self.withItem(self.delete),
|
||||||
Description: self.c.Tr.ViewDeleteOptions,
|
Description: self.c.Tr.ViewDeleteOptions,
|
||||||
OpensMenu: true,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Branches.PushTag),
|
Key: opts.GetKey(opts.Config.Branches.PushTag),
|
||||||
Handler: self.withSelectedTag(self.push),
|
Handler: self.withItem(self.push),
|
||||||
Description: self.c.Tr.PushTag,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.PushTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.New),
|
Key: opts.GetKey(opts.Config.Universal.New),
|
||||||
@ -48,10 +57,11 @@ func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
|||||||
Description: self.c.Tr.CreateTag,
|
Description: self.c.Tr.CreateTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||||
Handler: self.withSelectedTag(self.createResetMenu),
|
Handler: self.withItem(self.createResetMenu),
|
||||||
Description: self.c.Tr.ViewResetOptions,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
OpensMenu: true,
|
Description: self.c.Tr.ViewResetOptions,
|
||||||
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,22 +220,9 @@ func (self *TagsController) createResetMenu(tag *models.Tag) error {
|
|||||||
|
|
||||||
func (self *TagsController) create() error {
|
func (self *TagsController) create() error {
|
||||||
// leaving commit SHA blank so that we're just creating the tag for the current commit
|
// leaving commit SHA blank so that we're just creating the tag for the current commit
|
||||||
return self.c.Helpers().Tags.OpenCreateTagPrompt("", func() { self.context().SetSelectedLineIdx(0) })
|
return self.c.Helpers().Tags.OpenCreateTagPrompt("", func() {
|
||||||
}
|
self.context().SetSelection(0)
|
||||||
|
})
|
||||||
func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
tag := self.context().GetSelected()
|
|
||||||
if tag == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return f(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *TagsController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagsController) context() *context.TagsContext {
|
func (self *TagsController) context() *context.TagsContext {
|
||||||
|
@ -27,11 +27,11 @@ type UndoController struct {
|
|||||||
var _ types.IController = &UndoController{}
|
var _ types.IController = &UndoController{}
|
||||||
|
|
||||||
func NewUndoController(
|
func NewUndoController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *UndoController {
|
) *UndoController {
|
||||||
return &UndoController{
|
return &UndoController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,15 +14,21 @@ type CanViewWorktreeOptions interface {
|
|||||||
|
|
||||||
type WorktreeOptionsController struct {
|
type WorktreeOptionsController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[string]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context CanViewWorktreeOptions
|
context CanViewWorktreeOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorktreeOptionsController(controllerCommon *ControllerCommon, context CanViewWorktreeOptions) *WorktreeOptionsController {
|
func NewWorktreeOptionsController(c *ControllerCommon, context CanViewWorktreeOptions) *WorktreeOptionsController {
|
||||||
return &WorktreeOptionsController{
|
return &WorktreeOptionsController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: controllerCommon,
|
ListControllerTrait: NewListControllerTrait[string](
|
||||||
context: context,
|
c,
|
||||||
|
context,
|
||||||
|
context.GetSelectedItemId,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
|
context: context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +36,7 @@ func (self *WorktreeOptionsController) GetKeybindings(opts types.KeybindingsOpts
|
|||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Worktrees.ViewWorktreeOptions),
|
Key: opts.GetKey(opts.Config.Worktrees.ViewWorktreeOptions),
|
||||||
Handler: self.checkSelected(self.viewWorktreeOptions),
|
Handler: self.withItem(self.viewWorktreeOptions),
|
||||||
Description: self.c.Tr.ViewWorktreeOptions,
|
Description: self.c.Tr.ViewWorktreeOptions,
|
||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
@ -39,21 +45,6 @@ func (self *WorktreeOptionsController) GetKeybindings(opts types.KeybindingsOpts
|
|||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorktreeOptionsController) checkSelected(callback func(string) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
ref := self.context.GetSelectedItemId()
|
|
||||||
if ref == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *WorktreeOptionsController) Context() types.Context {
|
|
||||||
return self.context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *WorktreeOptionsController) viewWorktreeOptions(ref string) error {
|
func (self *WorktreeOptionsController) viewWorktreeOptions(ref string) error {
|
||||||
return self.c.Helpers().Worktree.ViewWorktreeOptions(self.context, ref)
|
return self.c.Helpers().Worktree.ViewWorktreeOptions(self.context, ref)
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,23 @@ import (
|
|||||||
|
|
||||||
type WorktreesController struct {
|
type WorktreesController struct {
|
||||||
baseController
|
baseController
|
||||||
|
*ListControllerTrait[*models.Worktree]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &WorktreesController{}
|
var _ types.IController = &WorktreesController{}
|
||||||
|
|
||||||
func NewWorktreesController(
|
func NewWorktreesController(
|
||||||
common *ControllerCommon,
|
c *ControllerCommon,
|
||||||
) *WorktreesController {
|
) *WorktreesController {
|
||||||
return &WorktreesController{
|
return &WorktreesController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
c: common,
|
ListControllerTrait: NewListControllerTrait[*models.Worktree](
|
||||||
|
c,
|
||||||
|
c.Contexts().Worktrees,
|
||||||
|
c.Contexts().Worktrees.GetSelected,
|
||||||
|
),
|
||||||
|
c: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,24 +41,28 @@ func (self *WorktreesController) GetKeybindings(opts types.KeybindingsOpts) []*t
|
|||||||
Description: self.c.Tr.CreateWorktree,
|
Description: self.c.Tr.CreateWorktree,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.SwitchToWorktree,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.SwitchToWorktree,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
Handler: self.checkSelected(self.enter),
|
Handler: self.withItem(self.enter),
|
||||||
Description: self.c.Tr.SwitchToWorktree,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.SwitchToWorktree,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||||
Handler: self.checkSelected(self.open),
|
Handler: self.withItem(self.open),
|
||||||
Description: self.c.Tr.OpenInEditor,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.OpenInEditor,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
Handler: self.checkSelected(self.remove),
|
Handler: self.withItem(self.remove),
|
||||||
Description: self.c.Tr.RemoveWorktree,
|
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||||
|
Description: self.c.Tr.RemoveWorktree,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +123,7 @@ func (self *WorktreesController) remove(worktree *models.Worktree) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorktreesController) GetOnClick() func() error {
|
func (self *WorktreesController) GetOnClick() func() error {
|
||||||
return self.checkSelected(self.enter)
|
return self.withItemGraceful(self.enter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorktreesController) enter(worktree *models.Worktree) error {
|
func (self *WorktreesController) enter(worktree *models.Worktree) error {
|
||||||
@ -124,21 +134,6 @@ func (self *WorktreesController) open(worktree *models.Worktree) error {
|
|||||||
return self.c.Helpers().Files.OpenDirInEditor(worktree.Path)
|
return self.c.Helpers().Files.OpenDirInEditor(worktree.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorktreesController) checkSelected(callback func(worktree *models.Worktree) error) func() error {
|
|
||||||
return func() error {
|
|
||||||
worktree := self.context().GetSelected()
|
|
||||||
if worktree == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(worktree)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *WorktreesController) Context() types.Context {
|
|
||||||
return self.context()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *WorktreesController) context() *context.WorktreesContext {
|
func (self *WorktreesController) context() *context.WorktreesContext {
|
||||||
return self.c.Contexts().Worktrees
|
return self.c.Contexts().Worktrees
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,6 @@ func (self *CommitFileTreeViewModel) ToggleShowTree() {
|
|||||||
|
|
||||||
index, found := self.GetIndexForPath(path)
|
index, found := self.GetIndexForPath(path)
|
||||||
if found {
|
if found {
|
||||||
self.SetSelectedLineIdx(index)
|
self.SetSelection(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,11 +81,11 @@ func (self *FileTreeViewModel) SetTree() {
|
|||||||
newNodes := self.GetAllItems()
|
newNodes := self.GetAllItems()
|
||||||
newIdx := self.findNewSelectedIdx(prevNodes[prevSelectedLineIdx:], newNodes)
|
newIdx := self.findNewSelectedIdx(prevNodes[prevSelectedLineIdx:], newNodes)
|
||||||
if newIdx != -1 && newIdx != prevSelectedLineIdx {
|
if newIdx != -1 && newIdx != prevSelectedLineIdx {
|
||||||
self.SetSelectedLineIdx(newIdx)
|
self.SetSelection(newIdx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.RefreshSelectedIdx()
|
self.ClampSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's try to find our file again and move the cursor to that.
|
// Let's try to find our file again and move the cursor to that.
|
||||||
@ -128,7 +128,7 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod
|
|||||||
|
|
||||||
func (self *FileTreeViewModel) SetStatusFilter(filter FileTreeDisplayFilter) {
|
func (self *FileTreeViewModel) SetStatusFilter(filter FileTreeDisplayFilter) {
|
||||||
self.IFileTree.SetStatusFilter(filter)
|
self.IFileTree.SetStatusFilter(filter)
|
||||||
self.IListCursor.SetSelectedLineIdx(0)
|
self.IListCursor.SetSelection(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're going from flat to tree we want to select the same file.
|
// If we're going from flat to tree we want to select the same file.
|
||||||
|
@ -139,6 +139,28 @@ func (gui *Gui) handleCopySelectedSideContextItemToClipboard() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) getCopySelectedSideContextItemToClipboardDisabledReason() *types.DisabledReason {
|
||||||
|
// important to note that this assumes we've selected an item in a side context
|
||||||
|
currentSideContext := gui.c.CurrentSideContext()
|
||||||
|
if currentSideContext == nil {
|
||||||
|
// This should never happen but if it does we'll just ignore the keypress
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
listContext, ok := currentSideContext.(types.IListContext)
|
||||||
|
if !ok {
|
||||||
|
// This should never happen but if it does we'll just ignore the keypress
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
startIdx, endIdx := listContext.GetList().GetSelectionRange()
|
||||||
|
if startIdx != endIdx {
|
||||||
|
return &types.DisabledReason{Text: gui.Tr.RangeSelectNotSupported}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) setCaption(caption string) {
|
func (gui *Gui) setCaption(caption string) {
|
||||||
gui.Views.Options.FgColor = gocui.ColorWhite
|
gui.Views.Options.FgColor = gocui.ColorWhite
|
||||||
gui.Views.Options.FgColor |= gocui.AttrBold
|
gui.Views.Options.FgColor |= gocui.AttrBold
|
||||||
|
@ -329,7 +329,7 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
|
|||||||
// because e.g. with worktrees, we'll show the current worktree at the top of the list.
|
// because e.g. with worktrees, we'll show the current worktree at the top of the list.
|
||||||
listContext, ok := contextToPush.(types.IListContext)
|
listContext, ok := contextToPush.(types.IListContext)
|
||||||
if ok {
|
if ok {
|
||||||
listContext.GetList().SetSelectedLineIdx(0)
|
listContext.GetList().SetSelection(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +88,18 @@ func (self *GuiDriver) ContextForView(viewName string) types.Context {
|
|||||||
|
|
||||||
func (self *GuiDriver) Fail(message string) {
|
func (self *GuiDriver) Fail(message string) {
|
||||||
currentView := self.gui.g.CurrentView()
|
currentView := self.gui.g.CurrentView()
|
||||||
|
|
||||||
|
// Check for unacknowledged toast: it may give us a hint as to why the test failed
|
||||||
|
toastMessage := ""
|
||||||
|
if t := self.NextToast(); t != nil {
|
||||||
|
toastMessage = fmt.Sprintf("Unacknowledged toast message: %s\n", *t)
|
||||||
|
}
|
||||||
|
|
||||||
fullMessage := fmt.Sprintf(
|
fullMessage := fmt.Sprintf(
|
||||||
"%s\nFinal Lazygit state:\n%s\nUpon failure, focused view was '%s'.\nLog:\n%s", message,
|
"%s\nFinal Lazygit state:\n%s\nUpon failure, focused view was '%s'.\n%sLog:\n%s", message,
|
||||||
self.gui.g.Snapshot(),
|
self.gui.g.Snapshot(),
|
||||||
currentView.Name(),
|
currentView.Name(),
|
||||||
|
toastMessage,
|
||||||
strings.Join(self.gui.GuiLog, "\n"),
|
strings.Join(self.gui.GuiLog, "\n"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -123,28 +123,32 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
|||||||
Handler: self.scrollDownMain,
|
Handler: self.scrollDownMain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "files",
|
ViewName: "files",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyFileNameToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyFileNameToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "localBranches",
|
ViewName: "localBranches",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyBranchNameToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyBranchNameToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "remoteBranches",
|
ViewName: "remoteBranches",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyBranchNameToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyBranchNameToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "commits",
|
ViewName: "commits",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyCommitShaToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyCommitShaToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "commits",
|
ViewName: "commits",
|
||||||
@ -153,16 +157,18 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
|||||||
Description: self.c.Tr.ResetCherryPick,
|
Description: self.c.Tr.ResetCherryPick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "reflogCommits",
|
ViewName: "reflogCommits",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyCommitShaToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyCommitShaToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "subCommits",
|
ViewName: "subCommits",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyCommitShaToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyCommitShaToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "information",
|
ViewName: "information",
|
||||||
@ -171,10 +177,11 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
|||||||
Handler: self.handleInfoClick,
|
Handler: self.handleInfoClick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "commitFiles",
|
ViewName: "commitFiles",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopyCommitFileNameToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopyCommitFileNameToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "",
|
ViewName: "",
|
||||||
@ -240,10 +247,11 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
|||||||
Handler: self.scrollDownConfirmationPanel,
|
Handler: self.scrollDownConfirmationPanel,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "submodules",
|
ViewName: "submodules",
|
||||||
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
||||||
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
||||||
Description: self.c.Tr.CopySubmoduleNameToClipboard,
|
GetDisabledReason: self.getCopySelectedSideContextItemToClipboardDisabledReason,
|
||||||
|
Description: self.c.Tr.CopySubmoduleNameToClipboard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "extras",
|
ViewName: "extras",
|
||||||
|
@ -13,66 +13,68 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var labelByKey = map[gocui.Key]string{
|
var labelByKey = map[gocui.Key]string{
|
||||||
gocui.KeyF1: "<f1>",
|
gocui.KeyF1: "<f1>",
|
||||||
gocui.KeyF2: "<f2>",
|
gocui.KeyF2: "<f2>",
|
||||||
gocui.KeyF3: "<f3>",
|
gocui.KeyF3: "<f3>",
|
||||||
gocui.KeyF4: "<f4>",
|
gocui.KeyF4: "<f4>",
|
||||||
gocui.KeyF5: "<f5>",
|
gocui.KeyF5: "<f5>",
|
||||||
gocui.KeyF6: "<f6>",
|
gocui.KeyF6: "<f6>",
|
||||||
gocui.KeyF7: "<f7>",
|
gocui.KeyF7: "<f7>",
|
||||||
gocui.KeyF8: "<f8>",
|
gocui.KeyF8: "<f8>",
|
||||||
gocui.KeyF9: "<f9>",
|
gocui.KeyF9: "<f9>",
|
||||||
gocui.KeyF10: "<f10>",
|
gocui.KeyF10: "<f10>",
|
||||||
gocui.KeyF11: "<f11>",
|
gocui.KeyF11: "<f11>",
|
||||||
gocui.KeyF12: "<f12>",
|
gocui.KeyF12: "<f12>",
|
||||||
gocui.KeyInsert: "<insert>",
|
gocui.KeyInsert: "<insert>",
|
||||||
gocui.KeyDelete: "<delete>",
|
gocui.KeyDelete: "<delete>",
|
||||||
gocui.KeyHome: "<home>",
|
gocui.KeyHome: "<home>",
|
||||||
gocui.KeyEnd: "<end>",
|
gocui.KeyEnd: "<end>",
|
||||||
gocui.KeyPgup: "<pgup>",
|
gocui.KeyPgup: "<pgup>",
|
||||||
gocui.KeyPgdn: "<pgdown>",
|
gocui.KeyPgdn: "<pgdown>",
|
||||||
gocui.KeyArrowUp: "<up>",
|
gocui.KeyArrowUp: "<up>",
|
||||||
gocui.KeyArrowDown: "<down>",
|
gocui.KeyShiftArrowUp: "<s-up>",
|
||||||
gocui.KeyArrowLeft: "<left>",
|
gocui.KeyArrowDown: "<down>",
|
||||||
gocui.KeyArrowRight: "<right>",
|
gocui.KeyShiftArrowDown: "<s-down>",
|
||||||
gocui.KeyTab: "<tab>", // <c-i>
|
gocui.KeyArrowLeft: "<left>",
|
||||||
gocui.KeyBacktab: "<backtab>",
|
gocui.KeyArrowRight: "<right>",
|
||||||
gocui.KeyEnter: "<enter>", // <c-m>
|
gocui.KeyTab: "<tab>", // <c-i>
|
||||||
gocui.KeyAltEnter: "<a-enter>",
|
gocui.KeyBacktab: "<backtab>",
|
||||||
gocui.KeyEsc: "<esc>", // <c-[>, <c-3>
|
gocui.KeyEnter: "<enter>", // <c-m>
|
||||||
gocui.KeyBackspace: "<backspace>", // <c-h>
|
gocui.KeyAltEnter: "<a-enter>",
|
||||||
gocui.KeyCtrlSpace: "<c-space>", // <c-~>, <c-2>
|
gocui.KeyEsc: "<esc>", // <c-[>, <c-3>
|
||||||
gocui.KeyCtrlSlash: "<c-/>", // <c-_>
|
gocui.KeyBackspace: "<backspace>", // <c-h>
|
||||||
gocui.KeySpace: "<space>",
|
gocui.KeyCtrlSpace: "<c-space>", // <c-~>, <c-2>
|
||||||
gocui.KeyCtrlA: "<c-a>",
|
gocui.KeyCtrlSlash: "<c-/>", // <c-_>
|
||||||
gocui.KeyCtrlB: "<c-b>",
|
gocui.KeySpace: "<space>",
|
||||||
gocui.KeyCtrlC: "<c-c>",
|
gocui.KeyCtrlA: "<c-a>",
|
||||||
gocui.KeyCtrlD: "<c-d>",
|
gocui.KeyCtrlB: "<c-b>",
|
||||||
gocui.KeyCtrlE: "<c-e>",
|
gocui.KeyCtrlC: "<c-c>",
|
||||||
gocui.KeyCtrlF: "<c-f>",
|
gocui.KeyCtrlD: "<c-d>",
|
||||||
gocui.KeyCtrlG: "<c-g>",
|
gocui.KeyCtrlE: "<c-e>",
|
||||||
gocui.KeyCtrlJ: "<c-j>",
|
gocui.KeyCtrlF: "<c-f>",
|
||||||
gocui.KeyCtrlK: "<c-k>",
|
gocui.KeyCtrlG: "<c-g>",
|
||||||
gocui.KeyCtrlL: "<c-l>",
|
gocui.KeyCtrlJ: "<c-j>",
|
||||||
gocui.KeyCtrlN: "<c-n>",
|
gocui.KeyCtrlK: "<c-k>",
|
||||||
gocui.KeyCtrlO: "<c-o>",
|
gocui.KeyCtrlL: "<c-l>",
|
||||||
gocui.KeyCtrlP: "<c-p>",
|
gocui.KeyCtrlN: "<c-n>",
|
||||||
gocui.KeyCtrlQ: "<c-q>",
|
gocui.KeyCtrlO: "<c-o>",
|
||||||
gocui.KeyCtrlR: "<c-r>",
|
gocui.KeyCtrlP: "<c-p>",
|
||||||
gocui.KeyCtrlS: "<c-s>",
|
gocui.KeyCtrlQ: "<c-q>",
|
||||||
gocui.KeyCtrlT: "<c-t>",
|
gocui.KeyCtrlR: "<c-r>",
|
||||||
gocui.KeyCtrlU: "<c-u>",
|
gocui.KeyCtrlS: "<c-s>",
|
||||||
gocui.KeyCtrlV: "<c-v>",
|
gocui.KeyCtrlT: "<c-t>",
|
||||||
gocui.KeyCtrlW: "<c-w>",
|
gocui.KeyCtrlU: "<c-u>",
|
||||||
gocui.KeyCtrlX: "<c-x>",
|
gocui.KeyCtrlV: "<c-v>",
|
||||||
gocui.KeyCtrlY: "<c-y>",
|
gocui.KeyCtrlW: "<c-w>",
|
||||||
gocui.KeyCtrlZ: "<c-z>",
|
gocui.KeyCtrlX: "<c-x>",
|
||||||
gocui.KeyCtrl4: "<c-4>", // <c-\>
|
gocui.KeyCtrlY: "<c-y>",
|
||||||
gocui.KeyCtrl5: "<c-5>", // <c-]>
|
gocui.KeyCtrlZ: "<c-z>",
|
||||||
gocui.KeyCtrl6: "<c-6>",
|
gocui.KeyCtrl4: "<c-4>", // <c-\>
|
||||||
gocui.KeyCtrl8: "<c-8>",
|
gocui.KeyCtrl5: "<c-5>", // <c-]>
|
||||||
gocui.MouseWheelUp: "mouse wheel up",
|
gocui.KeyCtrl6: "<c-6>",
|
||||||
gocui.MouseWheelDown: "mouse wheel down",
|
gocui.KeyCtrl8: "<c-8>",
|
||||||
|
gocui.MouseWheelUp: "mouse wheel up",
|
||||||
|
gocui.MouseWheelDown: "mouse wheel down",
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyByLabel = lo.Invert(labelByKey)
|
var keyByLabel = lo.Invert(labelByKey)
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
@ -143,15 +142,6 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
gui.State.ViewsSetup = true
|
gui.State.ViewsSetup = true
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, listContext := range gui.c.Context().AllList() {
|
|
||||||
view, err := gui.g.View(listContext.GetViewName())
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
view.SelBgColor = theme.GocuiSelectedLineBgColor
|
|
||||||
}
|
|
||||||
|
|
||||||
mainViewWidth, mainViewHeight := gui.Views.Main.Size()
|
mainViewWidth, mainViewHeight := gui.Views.Main.Size()
|
||||||
if mainViewWidth != gui.PrevLayout.MainWidth || mainViewHeight != gui.PrevLayout.MainHeight {
|
if mainViewWidth != gui.PrevLayout.MainWidth || mainViewHeight != gui.PrevLayout.MainHeight {
|
||||||
gui.PrevLayout.MainWidth = mainViewWidth
|
gui.PrevLayout.MainWidth = mainViewWidth
|
||||||
|
@ -43,7 +43,7 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gui.State.Contexts.Menu.SetMenuItems(opts.Items, opts.ColumnAlignment)
|
gui.State.Contexts.Menu.SetMenuItems(opts.Items, opts.ColumnAlignment)
|
||||||
gui.State.Contexts.Menu.SetSelectedLineIdx(0)
|
gui.State.Contexts.Menu.SetSelection(0)
|
||||||
|
|
||||||
gui.Views.Menu.Title = opts.Title
|
gui.Views.Menu.Title = opts.Title
|
||||||
gui.Views.Menu.FgColor = theme.GocuiDefaultTextColor
|
gui.Views.Menu.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ColoredConflictFile(state *State, hasFocus bool) string {
|
func ColoredConflictFile(state *State) string {
|
||||||
content := state.GetContent()
|
content := state.GetContent()
|
||||||
if len(state.conflicts) == 0 {
|
if len(state.conflicts) == 0 {
|
||||||
return content
|
return content
|
||||||
@ -21,9 +21,6 @@ func ColoredConflictFile(state *State, hasFocus bool) string {
|
|||||||
textStyle = style.FgRed
|
textStyle = style.FgRed
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasFocus && state.conflictIndex < len(state.conflicts) && *state.conflicts[state.conflictIndex] == *conflict && shouldHighlightLine(i, conflict, state.Selection()) {
|
|
||||||
textStyle = textStyle.MergeStyle(theme.SelectedRangeBgColor).SetBold()
|
|
||||||
}
|
|
||||||
if i == conflict.end && len(remainingConflicts) > 0 {
|
if i == conflict.end && len(remainingConflicts) > 0 {
|
||||||
conflict, remainingConflicts = shiftConflict(remainingConflicts)
|
conflict, remainingConflicts = shiftConflict(remainingConflicts)
|
||||||
}
|
}
|
||||||
@ -35,8 +32,3 @@ func ColoredConflictFile(state *State, hasFocus bool) string {
|
|||||||
func shiftConflict(conflicts []*mergeConflict) (*mergeConflict, []*mergeConflict) {
|
func shiftConflict(conflicts []*mergeConflict) (*mergeConflict, []*mergeConflict) {
|
||||||
return conflicts[0], conflicts[1:]
|
return conflicts[0], conflicts[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldHighlightLine(index int, conflict *mergeConflict, selection Selection) bool {
|
|
||||||
selectionStart, selectionEnd := selection.bounds(conflict)
|
|
||||||
return index >= selectionStart && index <= selectionEnd
|
|
||||||
}
|
|
||||||
|
@ -12,9 +12,12 @@ import (
|
|||||||
type State struct {
|
type State struct {
|
||||||
selectedLineIdx int
|
selectedLineIdx int
|
||||||
rangeStartLineIdx int
|
rangeStartLineIdx int
|
||||||
diff string
|
// If a range is sticky, it means we expand the range when we move up or down.
|
||||||
patch *patch.Patch
|
// Otherwise, we cancel the range when we move up or down.
|
||||||
selectMode selectMode
|
rangeIsSticky bool
|
||||||
|
diff string
|
||||||
|
patch *patch.Patch
|
||||||
|
selectMode selectMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// these represent what select mode we're in
|
// these represent what select mode we're in
|
||||||
@ -46,10 +49,12 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectMode := LINE
|
selectMode := LINE
|
||||||
|
rangeIsSticky := false
|
||||||
// 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 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 {
|
if selectedLineIdx >= 0 {
|
||||||
selectMode = RANGE
|
selectMode = RANGE
|
||||||
rangeStartLineIdx = selectedLineIdx
|
rangeStartLineIdx = selectedLineIdx
|
||||||
|
rangeIsSticky = true
|
||||||
} else if oldState != nil {
|
} else if oldState != nil {
|
||||||
// if we previously had a selectMode of RANGE, we want that to now be line again
|
// if we previously had a selectMode of RANGE, we want that to now be line again
|
||||||
if oldState.selectMode == HUNK {
|
if oldState.selectMode == HUNK {
|
||||||
@ -65,6 +70,7 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
|
|||||||
selectedLineIdx: selectedLineIdx,
|
selectedLineIdx: selectedLineIdx,
|
||||||
selectMode: selectMode,
|
selectMode: selectMode,
|
||||||
rangeStartLineIdx: rangeStartLineIdx,
|
rangeStartLineIdx: rangeStartLineIdx,
|
||||||
|
rangeIsSticky: rangeIsSticky,
|
||||||
diff: diff,
|
diff: diff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,15 +91,24 @@ func (s *State) ToggleSelectHunk() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) ToggleSelectRange() {
|
func (s *State) ToggleStickySelectRange() {
|
||||||
|
s.ToggleSelectRange(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *State) ToggleSelectRange(sticky bool) {
|
||||||
if s.selectMode == RANGE {
|
if s.selectMode == RANGE {
|
||||||
s.selectMode = LINE
|
s.selectMode = LINE
|
||||||
} else {
|
} else {
|
||||||
s.selectMode = RANGE
|
s.selectMode = RANGE
|
||||||
s.rangeStartLineIdx = s.selectedLineIdx
|
s.rangeStartLineIdx = s.selectedLineIdx
|
||||||
|
s.rangeIsSticky = sticky
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *State) SetRangeIsSticky(value bool) {
|
||||||
|
s.rangeIsSticky = value
|
||||||
|
}
|
||||||
|
|
||||||
func (s *State) SelectingHunk() bool {
|
func (s *State) SelectingHunk() bool {
|
||||||
return s.selectMode == HUNK
|
return s.selectMode == HUNK
|
||||||
}
|
}
|
||||||
@ -110,7 +125,18 @@ func (s *State) SetLineSelectMode() {
|
|||||||
s.selectMode = LINE
|
s.selectMode = LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For when you move the cursor without holding shift (meaning if we're in
|
||||||
|
// a non-sticky range select, we'll cancel it)
|
||||||
func (s *State) SelectLine(newSelectedLineIdx int) {
|
func (s *State) SelectLine(newSelectedLineIdx int) {
|
||||||
|
if s.selectMode == RANGE && !s.rangeIsSticky {
|
||||||
|
s.selectMode = LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
s.selectLineWithoutRangeCheck(newSelectedLineIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This just moves the cursor without caring about range select
|
||||||
|
func (s *State) selectLineWithoutRangeCheck(newSelectedLineIdx int) {
|
||||||
if newSelectedLineIdx < 0 {
|
if newSelectedLineIdx < 0 {
|
||||||
newSelectedLineIdx = 0
|
newSelectedLineIdx = 0
|
||||||
} else if newSelectedLineIdx > s.patch.LineCount()-1 {
|
} else if newSelectedLineIdx > s.patch.LineCount()-1 {
|
||||||
@ -124,8 +150,9 @@ func (s *State) SelectNewLineForRange(newSelectedLineIdx int) {
|
|||||||
s.rangeStartLineIdx = newSelectedLineIdx
|
s.rangeStartLineIdx = newSelectedLineIdx
|
||||||
|
|
||||||
s.selectMode = RANGE
|
s.selectMode = RANGE
|
||||||
|
s.rangeIsSticky = true
|
||||||
|
|
||||||
s.SelectLine(newSelectedLineIdx)
|
s.selectLineWithoutRangeCheck(newSelectedLineIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) CycleSelection(forward bool) {
|
func (s *State) CycleSelection(forward bool) {
|
||||||
@ -161,6 +188,23 @@ func (s *State) CycleLine(forward bool) {
|
|||||||
s.SelectLine(s.selectedLineIdx + change)
|
s.SelectLine(s.selectedLineIdx + change)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called when we use shift+arrow to expand the range (i.e. a non-sticky
|
||||||
|
// range)
|
||||||
|
func (s *State) CycleRange(forward bool) {
|
||||||
|
if !s.SelectingRange() {
|
||||||
|
s.ToggleSelectRange(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.SetRangeIsSticky(false)
|
||||||
|
|
||||||
|
change := 1
|
||||||
|
if !forward {
|
||||||
|
change = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
s.selectLineWithoutRangeCheck(s.selectedLineIdx + change)
|
||||||
|
}
|
||||||
|
|
||||||
// returns first and last patch line index of current hunk
|
// returns first and last patch line index of current hunk
|
||||||
func (s *State) CurrentHunkBounds() (int, int) {
|
func (s *State) CurrentHunkBounds() (int, int) {
|
||||||
hunkIdx := s.patch.HunkContainingLine(s.selectedLineIdx)
|
hunkIdx := s.patch.HunkContainingLine(s.selectedLineIdx)
|
||||||
@ -196,12 +240,8 @@ func (s *State) AdjustSelectedLineIdx(change int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) RenderForLineIndices(isFocused bool, includedLineIndices []int) string {
|
func (s *State) RenderForLineIndices(isFocused bool, includedLineIndices []int) string {
|
||||||
firstLineIdx, lastLineIdx := s.SelectedRange()
|
|
||||||
includedLineIndicesSet := set.NewFromSlice(includedLineIndices)
|
includedLineIndicesSet := set.NewFromSlice(includedLineIndices)
|
||||||
return s.patch.FormatView(patch.FormatViewOpts{
|
return s.patch.FormatView(patch.FormatViewOpts{
|
||||||
IsFocused: isFocused,
|
|
||||||
FirstLineIndex: firstLineIdx,
|
|
||||||
LastLineIndex: lastLineIdx,
|
|
||||||
IncLineIndices: includedLineIndicesSet,
|
IncLineIndices: includedLineIndicesSet,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -226,3 +266,11 @@ func (s *State) CalculateOrigin(currentOrigin int, bufferHeight int, numLines in
|
|||||||
|
|
||||||
return calculateOrigin(currentOrigin, bufferHeight, numLines, firstLineIdx, lastLineIdx, s.GetSelectedLineIdx(), s.selectMode)
|
return calculateOrigin(currentOrigin, bufferHeight, numLines, firstLineIdx, lastLineIdx, s.GetSelectedLineIdx(), s.selectMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *State) RangeStartLineIdx() (int, bool) {
|
||||||
|
if s.selectMode == RANGE {
|
||||||
|
return s.rangeStartLineIdx, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
@ -144,6 +144,7 @@ type IListContext interface {
|
|||||||
|
|
||||||
FocusLine()
|
FocusLine()
|
||||||
IsListContext() // used for type switch
|
IsListContext() // used for type switch
|
||||||
|
RangeSelectEnabled() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPatchExplorerContext interface {
|
type IPatchExplorerContext interface {
|
||||||
@ -163,6 +164,8 @@ type IPatchExplorerContext interface {
|
|||||||
|
|
||||||
type IViewTrait interface {
|
type IViewTrait interface {
|
||||||
FocusPoint(yIdx int)
|
FocusPoint(yIdx int)
|
||||||
|
SetRangeSelectStart(yIdx int)
|
||||||
|
CancelRangeSelect()
|
||||||
SetViewPortContent(content string)
|
SetViewPortContent(content string)
|
||||||
SetContent(content string)
|
SetContent(content string)
|
||||||
SetFooter(value string)
|
SetFooter(value string)
|
||||||
@ -222,12 +225,21 @@ type IList interface {
|
|||||||
type IListCursor interface {
|
type IListCursor interface {
|
||||||
GetSelectedLineIdx() int
|
GetSelectedLineIdx() int
|
||||||
SetSelectedLineIdx(value int)
|
SetSelectedLineIdx(value int)
|
||||||
|
SetSelection(value int)
|
||||||
MoveSelectedLine(delta int)
|
MoveSelectedLine(delta int)
|
||||||
RefreshSelectedIdx()
|
ClampSelection()
|
||||||
|
CancelRangeSelect()
|
||||||
|
GetRangeStartIdx() (int, bool)
|
||||||
|
GetSelectionRange() (int, int)
|
||||||
|
IsSelectingRange() bool
|
||||||
|
AreMultipleItemsSelected() bool
|
||||||
|
ToggleStickyRange()
|
||||||
|
ExpandNonStickyRange(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IListPanelState interface {
|
type IListPanelState interface {
|
||||||
SetSelectedLineIdx(int)
|
SetSelectedLineIdx(int)
|
||||||
|
SetSelection(int)
|
||||||
GetSelectedLineIdx() int
|
GetSelectedLineIdx() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ func (gui *Gui) createAllViews() error {
|
|||||||
}
|
}
|
||||||
(*mapping.viewPtr).FrameRunes = frameRunes
|
(*mapping.viewPtr).FrameRunes = frameRunes
|
||||||
(*mapping.viewPtr).FgColor = theme.GocuiDefaultTextColor
|
(*mapping.viewPtr).FgColor = theme.GocuiDefaultTextColor
|
||||||
|
(*mapping.viewPtr).SelBgColor = theme.GocuiSelectedLineBgColor
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.Views.Options.FgColor = theme.OptionsColor
|
gui.Views.Options.FgColor = theme.OptionsColor
|
||||||
@ -134,23 +135,18 @@ func (gui *Gui) createAllViews() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gui.Views.Staging.Title = gui.c.Tr.UnstagedChanges
|
gui.Views.Staging.Title = gui.c.Tr.UnstagedChanges
|
||||||
gui.Views.Staging.Highlight = false
|
|
||||||
gui.Views.Staging.Wrap = true
|
gui.Views.Staging.Wrap = true
|
||||||
|
|
||||||
gui.Views.StagingSecondary.Title = gui.c.Tr.StagedChanges
|
gui.Views.StagingSecondary.Title = gui.c.Tr.StagedChanges
|
||||||
gui.Views.StagingSecondary.Highlight = false
|
|
||||||
gui.Views.StagingSecondary.Wrap = true
|
gui.Views.StagingSecondary.Wrap = true
|
||||||
|
|
||||||
gui.Views.PatchBuilding.Title = gui.Tr.Patch
|
gui.Views.PatchBuilding.Title = gui.Tr.Patch
|
||||||
gui.Views.PatchBuilding.Highlight = false
|
|
||||||
gui.Views.PatchBuilding.Wrap = true
|
gui.Views.PatchBuilding.Wrap = true
|
||||||
|
|
||||||
gui.Views.PatchBuildingSecondary.Title = gui.Tr.CustomPatch
|
gui.Views.PatchBuildingSecondary.Title = gui.Tr.CustomPatch
|
||||||
gui.Views.PatchBuildingSecondary.Highlight = false
|
|
||||||
gui.Views.PatchBuildingSecondary.Wrap = true
|
gui.Views.PatchBuildingSecondary.Wrap = true
|
||||||
|
|
||||||
gui.Views.MergeConflicts.Title = gui.c.Tr.MergeConflictsTitle
|
gui.Views.MergeConflicts.Title = gui.c.Tr.MergeConflictsTitle
|
||||||
gui.Views.MergeConflicts.Highlight = false
|
|
||||||
gui.Views.MergeConflicts.Wrap = false
|
gui.Views.MergeConflicts.Wrap = false
|
||||||
|
|
||||||
gui.Views.Limit.Title = gui.c.Tr.NotEnoughSpace
|
gui.Views.Limit.Title = gui.c.Tr.NotEnoughSpace
|
||||||
|
@ -163,7 +163,7 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
FileStagingRequirements: `只能暂存跟踪文件的单独行`,
|
FileStagingRequirements: `只能暂存跟踪文件的单独行`,
|
||||||
StageSelection: `切换行暂存状态`,
|
StageSelection: `切换行暂存状态`,
|
||||||
DiscardSelection: `取消变更 (git reset)`,
|
DiscardSelection: `取消变更 (git reset)`,
|
||||||
ToggleDragSelect: `切换拖动选择`,
|
ToggleRangeSelect: `切换拖动选择`,
|
||||||
ToggleSelectHunk: `切换选择区块`,
|
ToggleSelectHunk: `切换选择区块`,
|
||||||
ToggleSelectionForPatch: `添加/移除 行到补丁`,
|
ToggleSelectionForPatch: `添加/移除 行到补丁`,
|
||||||
ToggleStagingPanel: `切换到其他面板`,
|
ToggleStagingPanel: `切换到其他面板`,
|
||||||
@ -198,7 +198,6 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
YouAreHere: "您在这里",
|
YouAreHere: "您在这里",
|
||||||
RewordNotSupported: "当前不支持交互式重新基准化时的重新措词提交",
|
RewordNotSupported: "当前不支持交互式重新基准化时的重新措词提交",
|
||||||
CherryPickCopy: "复制提交(拣选)",
|
CherryPickCopy: "复制提交(拣选)",
|
||||||
CherryPickCopyRange: "复制提交范围(拣选)",
|
|
||||||
PasteCommits: "粘贴提交(拣选)",
|
PasteCommits: "粘贴提交(拣选)",
|
||||||
SureCherryPick: "您确定要将选中的提交进行拣选到这个分支吗?",
|
SureCherryPick: "您确定要将选中的提交进行拣选到这个分支吗?",
|
||||||
CherryPick: "拣选 (Cherry-Pick)",
|
CherryPick: "拣选 (Cherry-Pick)",
|
||||||
|
@ -128,7 +128,7 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
FileStagingRequirements: `Kan alleen individuele lijnen stagen van getrackte bestanden met onstaged veranderingen`,
|
FileStagingRequirements: `Kan alleen individuele lijnen stagen van getrackte bestanden met onstaged veranderingen`,
|
||||||
StageSelection: `Toggle lijnen staged / unstaged`,
|
StageSelection: `Toggle lijnen staged / unstaged`,
|
||||||
DiscardSelection: `Verwijdert change (git reset)`,
|
DiscardSelection: `Verwijdert change (git reset)`,
|
||||||
ToggleDragSelect: `Toggle drag selecteer`,
|
ToggleRangeSelect: `Toggle drag selecteer`,
|
||||||
ToggleSelectHunk: `Toggle selecteer hunk`,
|
ToggleSelectHunk: `Toggle selecteer hunk`,
|
||||||
ToggleSelectionForPatch: `Voeg toe/verwijder lijn(en) in patch`,
|
ToggleSelectionForPatch: `Voeg toe/verwijder lijn(en) in patch`,
|
||||||
ToggleStagingPanel: `Ga naar een ander paneel`,
|
ToggleStagingPanel: `Ga naar een ander paneel`,
|
||||||
@ -163,7 +163,6 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
YouAreHere: "JE BENT HIER",
|
YouAreHere: "JE BENT HIER",
|
||||||
RewordNotSupported: "Herformatteren van commits in interactief rebasen is nog niet ondersteund",
|
RewordNotSupported: "Herformatteren van commits in interactief rebasen is nog niet ondersteund",
|
||||||
CherryPickCopy: "Kopieer commit (cherry-pick)",
|
CherryPickCopy: "Kopieer commit (cherry-pick)",
|
||||||
CherryPickCopyRange: "Kopieer commit reeks (cherry-pick)",
|
|
||||||
PasteCommits: "Plak commits (cherry-pick)",
|
PasteCommits: "Plak commits (cherry-pick)",
|
||||||
SureCherryPick: "Weet je zeker dat je de gekopieerde commits naar deze branch wil cherry-picken?",
|
SureCherryPick: "Weet je zeker dat je de gekopieerde commits naar deze branch wil cherry-picken?",
|
||||||
CherryPick: "Cherry-Pick",
|
CherryPick: "Cherry-Pick",
|
||||||
|
@ -200,7 +200,6 @@ type TranslationSet struct {
|
|||||||
FileStagingRequirements string
|
FileStagingRequirements string
|
||||||
StageSelection string
|
StageSelection string
|
||||||
DiscardSelection string
|
DiscardSelection string
|
||||||
ToggleDragSelect string
|
|
||||||
ToggleSelectHunk string
|
ToggleSelectHunk string
|
||||||
ToggleSelectionForPatch string
|
ToggleSelectionForPatch string
|
||||||
EditHunk string
|
EditHunk string
|
||||||
@ -252,7 +251,6 @@ type TranslationSet struct {
|
|||||||
RewordNotSupported string
|
RewordNotSupported string
|
||||||
ChangingThisActionIsNotAllowed string
|
ChangingThisActionIsNotAllowed string
|
||||||
CherryPickCopy string
|
CherryPickCopy string
|
||||||
CherryPickCopyRange string
|
|
||||||
PasteCommits string
|
PasteCommits string
|
||||||
SureCherryPick string
|
SureCherryPick string
|
||||||
CherryPick string
|
CherryPick string
|
||||||
@ -646,11 +644,16 @@ type TranslationSet struct {
|
|||||||
MarkedCommitMarker string
|
MarkedCommitMarker string
|
||||||
PleaseGoToURL string
|
PleaseGoToURL string
|
||||||
DisabledMenuItemPrefix string
|
DisabledMenuItemPrefix string
|
||||||
NoCommitSelected string
|
|
||||||
NoCopiedCommits string
|
NoCopiedCommits string
|
||||||
QuickStartInteractiveRebase string
|
QuickStartInteractiveRebase string
|
||||||
QuickStartInteractiveRebaseTooltip string
|
QuickStartInteractiveRebaseTooltip string
|
||||||
CannotQuickStartInteractiveRebase string
|
CannotQuickStartInteractiveRebase string
|
||||||
|
ToggleRangeSelect string
|
||||||
|
RangeSelectUp string
|
||||||
|
RangeSelectDown string
|
||||||
|
RangeSelectNotSupported string
|
||||||
|
NoItemSelected string
|
||||||
|
SelectedItemIsNotABranch string
|
||||||
Actions Actions
|
Actions Actions
|
||||||
Bisect Bisect
|
Bisect Bisect
|
||||||
Log Log
|
Log Log
|
||||||
@ -1033,7 +1036,7 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
FileStagingRequirements: `Can only stage individual lines for tracked files`,
|
FileStagingRequirements: `Can only stage individual lines for tracked files`,
|
||||||
StageSelection: `Toggle line staged / unstaged`,
|
StageSelection: `Toggle line staged / unstaged`,
|
||||||
DiscardSelection: `Discard change (git reset)`,
|
DiscardSelection: `Discard change (git reset)`,
|
||||||
ToggleDragSelect: `Toggle drag select`,
|
ToggleRangeSelect: `Toggle range select`,
|
||||||
ToggleSelectHunk: `Toggle select hunk`,
|
ToggleSelectHunk: `Toggle select hunk`,
|
||||||
ToggleSelectionForPatch: `Add/Remove line(s) to patch`,
|
ToggleSelectionForPatch: `Add/Remove line(s) to patch`,
|
||||||
EditHunk: `Edit hunk`,
|
EditHunk: `Edit hunk`,
|
||||||
@ -1088,7 +1091,6 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
RewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
RewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
||||||
ChangingThisActionIsNotAllowed: "Changing this kind of rebase todo entry is not allowed",
|
ChangingThisActionIsNotAllowed: "Changing this kind of rebase todo entry is not allowed",
|
||||||
CherryPickCopy: "Copy commit (cherry-pick)",
|
CherryPickCopy: "Copy commit (cherry-pick)",
|
||||||
CherryPickCopyRange: "Copy commit range (cherry-pick)",
|
|
||||||
PasteCommits: "Paste commits (cherry-pick)",
|
PasteCommits: "Paste commits (cherry-pick)",
|
||||||
SureCherryPick: "Are you sure you want to cherry-pick the copied commits onto this branch?",
|
SureCherryPick: "Are you sure you want to cherry-pick the copied commits onto this branch?",
|
||||||
CherryPick: "Cherry-pick",
|
CherryPick: "Cherry-pick",
|
||||||
@ -1478,11 +1480,15 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
MarkedCommitMarker: "↑↑↑ Will rebase from here ↑↑↑",
|
MarkedCommitMarker: "↑↑↑ Will rebase from here ↑↑↑",
|
||||||
PleaseGoToURL: "Please go to {{.url}}",
|
PleaseGoToURL: "Please go to {{.url}}",
|
||||||
DisabledMenuItemPrefix: "Disabled: ",
|
DisabledMenuItemPrefix: "Disabled: ",
|
||||||
NoCommitSelected: "No commit selected",
|
|
||||||
NoCopiedCommits: "No copied commits",
|
NoCopiedCommits: "No copied commits",
|
||||||
QuickStartInteractiveRebase: "Start interactive rebase",
|
QuickStartInteractiveRebase: "Start interactive rebase",
|
||||||
QuickStartInteractiveRebaseTooltip: "Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.\nIf you would instead like to start an interactive rebase from the selected commit, press `{{.editKey}}`.",
|
QuickStartInteractiveRebaseTooltip: "Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.\nIf you would instead like to start an interactive rebase from the selected commit, press `{{.editKey}}`.",
|
||||||
CannotQuickStartInteractiveRebase: "Cannot start interactive rebase: the HEAD commit is a merge commit or is present on the main branch, so there is no appropriate base commit to start the rebase from. You can start an interactive rebase from a specific commit by selecting the commit and pressing `{{.editKey}}`.",
|
CannotQuickStartInteractiveRebase: "Cannot start interactive rebase: the HEAD commit is a merge commit or is present on the main branch, so there is no appropriate base commit to start the rebase from. You can start an interactive rebase from a specific commit by selecting the commit and pressing `{{.editKey}}`.",
|
||||||
|
RangeSelectUp: "Range select up",
|
||||||
|
RangeSelectDown: "Range select down",
|
||||||
|
RangeSelectNotSupported: "Action does not support range selection, please select a single item",
|
||||||
|
NoItemSelected: "No item selected",
|
||||||
|
SelectedItemIsNotABranch: "Selected item is not a branch",
|
||||||
Actions: Actions{
|
Actions: Actions{
|
||||||
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
|
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
|
||||||
CheckoutCommit: "Checkout commit",
|
CheckoutCommit: "Checkout commit",
|
||||||
|
@ -162,7 +162,7 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
// FileStagingRequirements: `Can only stage individual lines for tracked files`,
|
// FileStagingRequirements: `Can only stage individual lines for tracked files`,
|
||||||
StageSelection: `選択行をステージ/アンステージ`,
|
StageSelection: `選択行をステージ/アンステージ`,
|
||||||
DiscardSelection: `変更を削除 (git reset)`,
|
DiscardSelection: `変更を削除 (git reset)`,
|
||||||
ToggleDragSelect: `範囲選択を切り替え`,
|
ToggleRangeSelect: `範囲選択を切り替え`,
|
||||||
ToggleSelectHunk: `Hunk選択を切り替え`,
|
ToggleSelectHunk: `Hunk選択を切り替え`,
|
||||||
ToggleSelectionForPatch: `行をパッチに追加/削除`,
|
ToggleSelectionForPatch: `行をパッチに追加/削除`,
|
||||||
ToggleStagingPanel: `パネルを切り替え`,
|
ToggleStagingPanel: `パネルを切り替え`,
|
||||||
@ -201,9 +201,8 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
// NoRoom: "Not enough room",
|
// NoRoom: "Not enough room",
|
||||||
YouAreHere: "現在位置",
|
YouAreHere: "現在位置",
|
||||||
// LcRewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
// LcRewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
||||||
CherryPickCopy: "コミットをコピー (cherry-pick)",
|
CherryPickCopy: "コミットをコピー (cherry-pick)",
|
||||||
CherryPickCopyRange: "コミットを範囲コピー (cherry-pick)",
|
PasteCommits: "コミットを貼り付け (cherry-pick)",
|
||||||
PasteCommits: "コミットを貼り付け (cherry-pick)",
|
|
||||||
// SureCherryPick: "Are you sure you want to cherry-pick the copied commits onto this branch?",
|
// SureCherryPick: "Are you sure you want to cherry-pick the copied commits onto this branch?",
|
||||||
CherryPick: "Cherry-Pick",
|
CherryPick: "Cherry-Pick",
|
||||||
Donate: "支援",
|
Donate: "支援",
|
||||||
|
@ -164,7 +164,7 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
FileStagingRequirements: `추적된 파일에 대해 개별 라인만 stage할 수 있습니다.`,
|
FileStagingRequirements: `추적된 파일에 대해 개별 라인만 stage할 수 있습니다.`,
|
||||||
StageSelection: `선택한 행을 staged / unstaged`,
|
StageSelection: `선택한 행을 staged / unstaged`,
|
||||||
DiscardSelection: `변경을 삭제 (git reset)`,
|
DiscardSelection: `변경을 삭제 (git reset)`,
|
||||||
ToggleDragSelect: `드래그 선택 전환`,
|
ToggleRangeSelect: `드래그 선택 전환`,
|
||||||
ToggleSelectHunk: `Toggle select hunk`,
|
ToggleSelectHunk: `Toggle select hunk`,
|
||||||
ToggleSelectionForPatch: `Line(s)을 패치에 추가/삭제`,
|
ToggleSelectionForPatch: `Line(s)을 패치에 추가/삭제`,
|
||||||
ToggleStagingPanel: `패널 전환`,
|
ToggleStagingPanel: `패널 전환`,
|
||||||
@ -199,7 +199,6 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
YouAreHere: "현재 위치",
|
YouAreHere: "현재 위치",
|
||||||
RewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
RewordNotSupported: "Rewording commits while interactively rebasing is not currently supported",
|
||||||
CherryPickCopy: "커밋을 복사 (cherry-pick)",
|
CherryPickCopy: "커밋을 복사 (cherry-pick)",
|
||||||
CherryPickCopyRange: "커밋을 범위로 복사 (cherry-pick)",
|
|
||||||
PasteCommits: "커밋을 붙여넣기 (cherry-pick)",
|
PasteCommits: "커밋을 붙여넣기 (cherry-pick)",
|
||||||
SureCherryPick: "정말로 복사한 커밋을 이 브랜치에 체리픽하시겠습니까?",
|
SureCherryPick: "정말로 복사한 커밋을 이 브랜치에 체리픽하시겠습니까?",
|
||||||
CherryPick: "체리픽",
|
CherryPick: "체리픽",
|
||||||
|
@ -131,7 +131,6 @@ func polishTranslationSet() TranslationSet {
|
|||||||
YouAreHere: "JESTEŚ TU",
|
YouAreHere: "JESTEŚ TU",
|
||||||
RewordNotSupported: "Przeredagowanie commitów podczas interaktywnej zmiany bazy nie jest obecnie wspierane",
|
RewordNotSupported: "Przeredagowanie commitów podczas interaktywnej zmiany bazy nie jest obecnie wspierane",
|
||||||
CherryPickCopy: "Kopiuj commit (przebieranie)",
|
CherryPickCopy: "Kopiuj commit (przebieranie)",
|
||||||
CherryPickCopyRange: "Kopiuj zakres commitów (przebieranie)",
|
|
||||||
PasteCommits: "Wklej commity (przebieranie)",
|
PasteCommits: "Wklej commity (przebieranie)",
|
||||||
SureCherryPick: "Czy na pewno chcesz przebierać w skopiowanych commitach na tej gałęzi?",
|
SureCherryPick: "Czy na pewno chcesz przebierać w skopiowanych commitach na tej gałęzi?",
|
||||||
CherryPick: "Przebieranie",
|
CherryPick: "Przebieranie",
|
||||||
|
@ -194,7 +194,7 @@ func RussianTranslationSet() TranslationSet {
|
|||||||
FileStagingRequirements: `Можно проиндексировать только отдельные строки для отслеживаемых файлов`,
|
FileStagingRequirements: `Можно проиндексировать только отдельные строки для отслеживаемых файлов`,
|
||||||
StageSelection: `Переключить строку в проиндексированные / непроиндексированные`,
|
StageSelection: `Переключить строку в проиндексированные / непроиндексированные`,
|
||||||
DiscardSelection: `Отменить изменение (git reset)`,
|
DiscardSelection: `Отменить изменение (git reset)`,
|
||||||
ToggleDragSelect: `Переключить выборку перетаскивания`,
|
ToggleRangeSelect: `Переключить выборку перетаскивания`,
|
||||||
ToggleSelectHunk: `Переключить выборку частей`,
|
ToggleSelectHunk: `Переключить выборку частей`,
|
||||||
ToggleSelectionForPatch: `Добавить/удалить строку(и) для патча`,
|
ToggleSelectionForPatch: `Добавить/удалить строку(и) для патча`,
|
||||||
EditHunk: `Изменить эту часть`,
|
EditHunk: `Изменить эту часть`,
|
||||||
@ -243,7 +243,6 @@ func RussianTranslationSet() TranslationSet {
|
|||||||
RewordNotSupported: "Переформулировка коммитов при интерактивном перебазировании в настоящее время не поддерживается",
|
RewordNotSupported: "Переформулировка коммитов при интерактивном перебазировании в настоящее время не поддерживается",
|
||||||
ChangingThisActionIsNotAllowed: "Изменение этого типа записи todo перебазирования не допускается",
|
ChangingThisActionIsNotAllowed: "Изменение этого типа записи todo перебазирования не допускается",
|
||||||
CherryPickCopy: "Скопировать отобранные коммит (cherry-pick)",
|
CherryPickCopy: "Скопировать отобранные коммит (cherry-pick)",
|
||||||
CherryPickCopyRange: "Скопировать несколько отобранных коммитов (cherry-pick)",
|
|
||||||
PasteCommits: "Вставить отобранные коммиты (cherry-pick)",
|
PasteCommits: "Вставить отобранные коммиты (cherry-pick)",
|
||||||
SureCherryPick: "Вы уверены, что хотите выборочно применить (cherry-picked) отобранные коммиты в эту ветку?",
|
SureCherryPick: "Вы уверены, что хотите выборочно применить (cherry-picked) отобранные коммиты в эту ветку?",
|
||||||
CherryPick: "Выборочная отборка (Cherry-Pick)",
|
CherryPick: "Выборочная отборка (Cherry-Pick)",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user