mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Remove the explorer behavior behind the retired panels
Focused main views now own selection, staging, patch construction, copying, and context-size rerenders. Remove the parallel controller/helper stack and its refresh scopes, while retaining custom-patch reset as mode behavior. Co-Authored-By: GitHub Copilot <copilot@github.com>
This commit is contained in:
co-authored by
GitHub Copilot
parent
28d5bdbc08
commit
aada2fb6d5
@@ -245,38 +245,12 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Go to previous hunk | |
|
||||
| `` <right>, l `` | Go to next hunk | |
|
||||
| `` v `` | Toggle range select | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Copy selected text to clipboard | |
|
||||
| `` o `` | Open file | Open file in default application. |
|
||||
| `` e `` | Edit file | Open file in external editor. |
|
||||
| `` <space> `` | Toggle lines in patch | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Exit custom patch builder | |
|
||||
| `` / `` | Search the current view by text | |
|
||||
|
||||
## Main panel (staging)
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Go to previous hunk | |
|
||||
| `` <right>, l `` | Go to next hunk | |
|
||||
| `` v `` | Toggle range select | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Copy selected text to clipboard | |
|
||||
| `` <space> `` | Stage | Toggle selection staged / unstaged. |
|
||||
| `` d `` | Discard | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||
| `` o `` | Open file | Open file in default application. |
|
||||
| `` e `` | Edit file | Open file in external editor. |
|
||||
| `` <esc> `` | Return to files panel | |
|
||||
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
|
||||
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||
| `` c `` | Commit | Commit staged changes. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
| `` C `` | Commit changes using git editor | |
|
||||
| `` <ctrl+f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | Search the current view by text | |
|
||||
|
||||
## Menu
|
||||
|
||||
@@ -263,38 +263,12 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 前のハンクに移動 | |
|
||||
| `` <right>, l `` | 次のハンクに移動 | |
|
||||
| `` v `` | 範囲選択を切り替え | |
|
||||
| `` a `` | ハンクの選択を切り替える | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | 選択したテキストをクリップボードにコピー | |
|
||||
| `` <space> `` | ステージ | 選択された部分のステージ / アンステージを切り替えます。 |
|
||||
| `` d `` | 破棄 | ステージされていない変更が選択されている場合、`git reset`を使用して変更を破棄します。ステージされた変更が選択されている場合、変更をアンステージします。 |
|
||||
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
|
||||
| `` e `` | ファイルを編集 | 外部エディタでファイルを開きます。 |
|
||||
| `` <esc> `` | ファイルパネルに戻る | |
|
||||
| `` <tab> `` | ビューを切り替え | 他のビュー(ステージされた変更/ステージされていない変更)に切り替えます。 |
|
||||
| `` E `` | ハンクを編集 | 選択したハンクを外部エディタで編集します。 |
|
||||
| `` c `` | コミット | ステージされた変更をコミットします。 |
|
||||
| `` w `` | pre-commitフックなしで変更をコミット | |
|
||||
| `` C `` | Gitエディタを使用して変更をコミット | |
|
||||
| `` <ctrl+f> `` | フィックスアップのベースコミットを検索 | 現在の変更が基づいているコミットを見つけて、コミットの修正/フィックスアップを行います。これにより、ブランチのコミットを一つずつ確認して、どのコミットを修正/フィックスアップすべきかを調べる手間が省けます。詳細はドキュメントを参照: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | 現在のビューをテキストで検索 | |
|
||||
|
||||
## メインパネル(パッチ作成)
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 前のハンクに移動 | |
|
||||
| `` <right>, l `` | 次のハンクに移動 | |
|
||||
| `` v `` | 範囲選択を切り替え | |
|
||||
| `` a `` | ハンクの選択を切り替える | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | 選択したテキストをクリップボードにコピー | |
|
||||
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
|
||||
| `` e `` | ファイルを編集 | 外部エディタでファイルを開きます。 |
|
||||
| `` <space> `` | パッチ内の行を切り替え | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | カスタムパッチビルダーを終了 | |
|
||||
| `` / `` | 現在のビューをテキストで検索 | |
|
||||
|
||||
## メインパネル(マージ中)
|
||||
|
||||
@@ -199,38 +199,12 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 이전 hunk를 선택 | |
|
||||
| `` <right>, l `` | 다음 hunk를 선택 | |
|
||||
| `` v `` | 드래그 선택 전환 | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | 선택한 텍스트를 클립보드에 복사 | |
|
||||
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||
| `` e `` | 파일 편집 | Open file in external editor. |
|
||||
| `` <space> `` | Line(s)을 패치에 추가/삭제 | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Exit custom patch builder | |
|
||||
| `` / `` | 검색 시작 | |
|
||||
|
||||
## 메인 패널 (Staging)
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 이전 hunk를 선택 | |
|
||||
| `` <right>, l `` | 다음 hunk를 선택 | |
|
||||
| `` v `` | 드래그 선택 전환 | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | 선택한 텍스트를 클립보드에 복사 | |
|
||||
| `` <space> `` | Staged 전환 | 선택한 행을 staged / unstaged |
|
||||
| `` d `` | 변경을 삭제 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||
| `` e `` | 파일 편집 | Open file in external editor. |
|
||||
| `` <esc> `` | 파일 목록으로 돌아가기 | |
|
||||
| `` <tab> `` | 패널 전환 | Switch to other view (staged/unstaged changes). |
|
||||
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||
| `` c `` | 커밋 변경내용 | 스테이징된 변경 사항 커밋. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
| `` C `` | Git 편집기를 사용하여 변경 내용을 커밋합니다. | |
|
||||
| `` <ctrl+f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | 검색 시작 | |
|
||||
|
||||
## 브랜치
|
||||
|
||||
@@ -253,16 +253,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Selecteer de vorige hunk | |
|
||||
| `` <right>, l `` | Selecteer de volgende hunk | |
|
||||
| `` v `` | Toggle drag selecteer | |
|
||||
| `` a `` | Wissel tussen hunk selectie aan of uit | Wissel tussen regel-voor-regel of hunk selectie modus. |
|
||||
| `` <ctrl+o> `` | Copy selected text to clipboard | |
|
||||
| `` o `` | Open bestand | Open bestand in standaardapplicatie. |
|
||||
| `` e `` | Verander bestand | Open bestand in externe editor. |
|
||||
| `` <space> `` | Voeg toe/verwijder lijn(en) in patch | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Sluit lijn-bij-lijn modus | |
|
||||
| `` / `` | Start met zoeken | |
|
||||
|
||||
## Reflog
|
||||
@@ -343,22 +333,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Selecteer de vorige hunk | |
|
||||
| `` <right>, l `` | Selecteer de volgende hunk | |
|
||||
| `` v `` | Toggle drag selecteer | |
|
||||
| `` a `` | Wissel tussen hunk selectie aan of uit | Wissel tussen regel-voor-regel of hunk selectie modus. |
|
||||
| `` <ctrl+o> `` | Copy selected text to clipboard | |
|
||||
| `` <space> `` | Toggle staged | Toggle lijnen staged / unstaged |
|
||||
| `` d `` | Verwijdert change (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||
| `` o `` | Open bestand | Open bestand in standaardapplicatie. |
|
||||
| `` e `` | Verander bestand | Open bestand in externe editor. |
|
||||
| `` <esc> `` | Ga terug naar het bestanden paneel | |
|
||||
| `` <tab> `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). |
|
||||
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||
| `` c `` | Commit veranderingen | Commit gestagede wijzigingen. |
|
||||
| `` w `` | Commit veranderingen zonder pre-commit hook | |
|
||||
| `` C `` | Commit veranderingen met de git editor | |
|
||||
| `` <ctrl+f> `` | Find base commit for fixup | Vind de commit waar je huidige wijzigingen bovenop zijn gebouwd met als doel die commit te amenden/fixen. Hierdoor hoef je dit niet met de hand te doen. Zie: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | Start met zoeken | |
|
||||
|
||||
## Stash
|
||||
|
||||
@@ -151,16 +151,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Idź do poprzedniego fragmentu | |
|
||||
| `` <right>, l `` | Idź do następnego fragmentu | |
|
||||
| `` v `` | Przełącz zaznaczenie zakresu | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Kopiuj zaznaczony tekst do schowka | |
|
||||
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
|
||||
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
|
||||
| `` <space> `` | Przełącz linie w łatce | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Wyjdź z budowniczego niestandardowej łatki | |
|
||||
| `` / `` | Szukaj w bieżącym widoku po tekście | |
|
||||
|
||||
## Input prompt
|
||||
@@ -254,22 +244,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Idź do poprzedniego fragmentu | |
|
||||
| `` <right>, l `` | Idź do następnego fragmentu | |
|
||||
| `` v `` | Przełącz zaznaczenie zakresu | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Kopiuj zaznaczony tekst do schowka | |
|
||||
| `` <space> `` | Zatwierdź | Przełącz zaznaczenie zatwierdzone/niezatwierdzone. |
|
||||
| `` d `` | Odrzuć | Gdy zaznaczona jest niezatwierdzona zmiana, odrzuć ją używając `git reset`. Gdy zaznaczona jest zatwierdzona zmiana, cofnij zatwierdzenie. |
|
||||
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
|
||||
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
|
||||
| `` <esc> `` | Wróć do panelu plików | |
|
||||
| `` <tab> `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). |
|
||||
| `` E `` | Edytuj fragment | Edytuj wybrany fragment w zewnętrznym edytorze. |
|
||||
| `` c `` | Commit | Zatwierdź zmiany zatwierdzone. |
|
||||
| `` w `` | Zatwierdź zmiany bez hooka pre-commit | |
|
||||
| `` C `` | Zatwierdź zmiany używając edytora git | |
|
||||
| `` <ctrl+f> `` | Znajdź bazowy commit do poprawki | Znajdź commit, na którym opierają się Twoje obecne zmiany, w celu poprawienia/zmiany commita. To pozwala Ci uniknąć przeglądania commitów w Twojej gałęzi jeden po drugim, aby zobaczyć, który commit powinien być poprawiony/zmieniony. Zobacz dokumentację: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | Szukaj w bieżącym widoku po tekście | |
|
||||
|
||||
## Panel potwierdzenia
|
||||
|
||||
@@ -257,22 +257,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Ir para o local anterior | |
|
||||
| `` <right>, l `` | Ir para o próximo trecho | |
|
||||
| `` v `` | Toggle range select | |
|
||||
| `` a `` | Toggle hunk selection | Ativa/desativa modo linha por linha vs. modo de seleção por partes. |
|
||||
| `` <ctrl+o> `` | Copiar texto selecionado para área de transferência | |
|
||||
| `` <space> `` | Etapa | Ativar/desativar seleção em staged/unstaged |
|
||||
| `` d `` | Descartar | Quando a mudança não desejada for selecionada, descarte a mudança usando `git reset`. Quando a mudança em fase é selecionada, despare a mudança. |
|
||||
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
|
||||
| `` e `` | Editar arquivo | Abrir arquivo no editor externo. |
|
||||
| `` <esc> `` | Retornar ao painel de arquivos | |
|
||||
| `` <tab> `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). |
|
||||
| `` E `` | Editar hunk | Editar o local selecionado no editor externo. |
|
||||
| `` c `` | Commit | Submeter mudanças em staging |
|
||||
| `` w `` | Fazer commit de alterações sem pré-commit | |
|
||||
| `` C `` | Enviar alteração usando um editor Git | |
|
||||
| `` <ctrl+f> `` | Encontrar commit da base para corrigir | Encontre o commit em que as suas mudanças atuais estão se baseando, para alterar/consertar o commit. Isso poupa-te você de ter que olhar pelos commits da sua branch um por um para ver qual commit deve ser alterado/consertado<br>Veja a documentação:<br><https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | Pesquisar na visualização atual por texto | |
|
||||
|
||||
## Painel de confirmação
|
||||
@@ -303,16 +287,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Ir para o local anterior | |
|
||||
| `` <right>, l `` | Ir para o próximo trecho | |
|
||||
| `` v `` | Toggle range select | |
|
||||
| `` a `` | Toggle hunk selection | Ativa/desativa modo linha por linha vs. modo de seleção por partes. |
|
||||
| `` <ctrl+o> `` | Copiar texto selecionado para área de transferência | |
|
||||
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
|
||||
| `` e `` | Editar arquivo | Abrir arquivo no editor externo. |
|
||||
| `` <space> `` | Alternar linhas no caminho | |
|
||||
| `` d `` | Remover linhas do commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Sair do construtor de patch personalizado | |
|
||||
| `` / `` | Pesquisar na visualização atual por texto | |
|
||||
|
||||
## Reflog
|
||||
|
||||
@@ -96,22 +96,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Выбрать предыдущую часть | |
|
||||
| `` <right>, l `` | Выбрать следующую часть | |
|
||||
| `` v `` | Переключить выборку перетаскивания | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Скопировать выделенный текст в буфер обмена | |
|
||||
| `` <space> `` | Переключить индекс | Переключить строку в проиндексированные / непроиндексированные |
|
||||
| `` d `` | Отменить изменение (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||
| `` o `` | Открыть файл | Open file in default application. |
|
||||
| `` e `` | Редактировать файл | Open file in external editor. |
|
||||
| `` <esc> `` | Вернуться к панели файлов | |
|
||||
| `` <tab> `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). |
|
||||
| `` E `` | Изменить эту часть | Edit selected hunk in external editor. |
|
||||
| `` c `` | Сохранить изменения | Commit staged changes. |
|
||||
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
|
||||
| `` C `` | Сохранить изменения с помощью редактора git | |
|
||||
| `` <ctrl+f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | Найти | |
|
||||
|
||||
## Главная панель (Обычный)
|
||||
@@ -159,16 +143,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | Выбрать предыдущую часть | |
|
||||
| `` <right>, l `` | Выбрать следующую часть | |
|
||||
| `` v `` | Переключить выборку перетаскивания | |
|
||||
| `` a `` | Toggle hunk selection | Toggle line-by-line vs. hunk selection mode. |
|
||||
| `` <ctrl+o> `` | Скопировать выделенный текст в буфер обмена | |
|
||||
| `` o `` | Открыть файл | Open file in default application. |
|
||||
| `` e `` | Редактировать файл | Open file in external editor. |
|
||||
| `` <space> `` | Добавить/удалить строку(и) для патча | |
|
||||
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
|
||||
| `` <esc> `` | Выйти из сборщика пользовательских патчей | |
|
||||
| `` / `` | Найти | |
|
||||
|
||||
## Журнал ссылок (Reflog)
|
||||
|
||||
@@ -253,16 +253,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 选择上一个区块 | |
|
||||
| `` <right>, l `` | 选择下一个区块 | |
|
||||
| `` v `` | 切换拖动选择 | |
|
||||
| `` a `` | 切换代码块选择 | 切换逐行选择与代码块选择模式。 |
|
||||
| `` <ctrl+o> `` | 复制选中文本到剪贴板 | |
|
||||
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
|
||||
| `` e `` | 编辑文件 | 使用外部编辑器打开文件 |
|
||||
| `` <space> `` | 添加/移除 行到补丁 | |
|
||||
| `` d `` | 从提交中移除行 | 从本次提交中移除所选行。此操作会在后台运行交互式变基,因此如果后续提交也修改了这些行,您可能会遇到合并冲突。 |
|
||||
| `` <esc> `` | 退出逐行模式 | |
|
||||
| `` / `` | 开始搜索 | |
|
||||
|
||||
## 标签
|
||||
@@ -324,22 +314,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 选择上一个区块 | |
|
||||
| `` <right>, l `` | 选择下一个区块 | |
|
||||
| `` v `` | 切换拖动选择 | |
|
||||
| `` a `` | 切换代码块选择 | 切换逐行选择与代码块选择模式。 |
|
||||
| `` <ctrl+o> `` | 复制选中文本到剪贴板 | |
|
||||
| `` <space> `` | 切换暂存状态 | 切换行暂存状态 |
|
||||
| `` d `` | 取消变更(git reset) | 当选择未暂存的变更时,使用git reset丢弃该变更。当选择已暂存的变更时,取消暂存该变更 |
|
||||
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
|
||||
| `` e `` | 编辑文件 | 使用外部编辑器打开文件 |
|
||||
| `` <esc> `` | 返回文件面板 | |
|
||||
| `` <tab> `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) |
|
||||
| `` E `` | 编辑代码块 | 在外部编辑器中编辑选中的代码块 |
|
||||
| `` c `` | 提交变更 | 提交暂存文件 |
|
||||
| `` w `` | 提交变更而无需预先提交钩子 | |
|
||||
| `` C `` | 使用 Git 编辑器提交变更 | |
|
||||
| `` <ctrl+f> `` | 找到用于修复的基准提交 | 找到您当前变更所基于的提交,以便于修正/改进该提交。这样做可以省去您逐一查看分支提交来确定应该修正/改进哪个提交的麻烦。请参阅文档: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | 开始搜索 | |
|
||||
|
||||
## 正常
|
||||
|
||||
@@ -56,16 +56,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 選擇上一段 | |
|
||||
| `` <right>, l `` | 選擇下一段 | |
|
||||
| `` v `` | 切換拖曳選擇 | |
|
||||
| `` a `` | 切換程式碼塊選擇 | 切換逐行選擇與程式碼塊選擇模式。 |
|
||||
| `` <ctrl+o> `` | 複製所選文本至剪貼簿 | |
|
||||
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
|
||||
| `` e `` | 編輯檔案 | 使用外部編輯器開啟 |
|
||||
| `` <space> `` | 向 (或從) 補丁中添加/刪除行 | |
|
||||
| `` d `` | 從提交中移除行 | 從本次提交中移除所選行。此操作會在背景執行互動式變基,因此如果後續提交也修改了這些行,您可能會遇到合併衝突。 |
|
||||
| `` <esc> `` | 退出自訂補丁建立器 | |
|
||||
| `` / `` | 搜尋 | |
|
||||
|
||||
## 主面板(一般)
|
||||
@@ -113,22 +103,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <left>, h `` | 選擇上一段 | |
|
||||
| `` <right>, l `` | 選擇下一段 | |
|
||||
| `` v `` | 切換拖曳選擇 | |
|
||||
| `` a `` | 切換程式碼塊選擇 | 切換逐行選擇與程式碼塊選擇模式。 |
|
||||
| `` <ctrl+o> `` | 複製所選文本至剪貼簿 | |
|
||||
| `` <space> `` | 切換預存 | 切換現有行的狀態 (已預存/未預存) |
|
||||
| `` d `` | 刪除變更 (git reset) | 選取未暫存的變更時,使用 `git reset` 捨棄變更。選取已暫存的變更時,取消暫存變更。 |
|
||||
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
|
||||
| `` e `` | 編輯檔案 | 使用外部編輯器開啟 |
|
||||
| `` <esc> `` | 返回檔案面板 | |
|
||||
| `` <tab> `` | 切換至另一個面板 (已預存/未預存更改) | 切換到其他檢視(已暫存/未暫存的變更)。 |
|
||||
| `` E `` | 編輯程式碼塊 | 在外部編輯器中編輯選中的程式碼塊。 |
|
||||
| `` c `` | 提交變更 | 提交暫存區變更 |
|
||||
| `` w `` | 沒有預提交 hook 就提交更改 | |
|
||||
| `` C `` | 使用 git 編輯器提交變更 | |
|
||||
| `` <ctrl+f> `` | 尋找 fixup 的基礎提交 | 找出目前變更所依據的提交,以便 amend/fixup。這樣不必逐一檢視分支中的提交來找出要 amend/fixup 的提交。請見文件:<https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||
| `` / `` | 搜尋 | |
|
||||
|
||||
## 功能表
|
||||
|
||||
+3
-33
@@ -52,8 +52,7 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
|
||||
gpgHelper := helpers.NewGpgHelper(helperCommon)
|
||||
viewHelper := helpers.NewViewHelper(helperCommon, gui.State.Contexts)
|
||||
patchBuildingHelper := helpers.NewPatchBuildingHelper(helperCommon)
|
||||
stagingHelper := helpers.NewStagingHelper(helperCommon)
|
||||
customPatchHelper := helpers.NewCustomPatchHelper(helperCommon)
|
||||
mergeConflictsHelper := helpers.NewMergeConflictsHelper(helperCommon)
|
||||
searchHelper := helpers.NewSearchHelper(helperCommon)
|
||||
|
||||
@@ -61,8 +60,6 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
helperCommon,
|
||||
refsHelper,
|
||||
rebaseHelper,
|
||||
patchBuildingHelper,
|
||||
stagingHelper,
|
||||
mergeConflictsHelper,
|
||||
worktreeHelper,
|
||||
searchHelper,
|
||||
@@ -78,7 +75,7 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
modeHelper := helpers.NewModeHelper(
|
||||
helperCommon,
|
||||
diffHelper,
|
||||
patchBuildingHelper,
|
||||
customPatchHelper,
|
||||
cherryPickHelper,
|
||||
rebaseHelper,
|
||||
bisectHelper,
|
||||
@@ -92,8 +89,7 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
gui.helpers = &helpers.Helpers{
|
||||
Refs: refsHelper,
|
||||
Host: helpers.NewHostHelper(helperCommon),
|
||||
PatchBuilding: patchBuildingHelper,
|
||||
Staging: stagingHelper,
|
||||
CustomPatch: customPatchHelper,
|
||||
Bisect: bisectHelper,
|
||||
Suggestions: suggestionsHelper,
|
||||
Files: helpers.NewFilesHelper(helperCommon),
|
||||
@@ -183,12 +179,8 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
gitFlowController := controllers.NewGitFlowController(common)
|
||||
stashController := controllers.NewStashController(common)
|
||||
commitFilesController := controllers.NewCommitFilesController(common)
|
||||
patchExplorerControllerFactory := controllers.NewPatchExplorerControllerFactory(common)
|
||||
stagingController := controllers.NewStagingController(common, gui.State.Contexts.Staging, gui.State.Contexts.StagingSecondary, false)
|
||||
stagingSecondaryController := controllers.NewStagingController(common, gui.State.Contexts.StagingSecondary, gui.State.Contexts.Staging, true)
|
||||
mainViewController := controllers.NewMainViewController(common, gui.State.Contexts.Normal, gui.State.Contexts.NormalSecondary)
|
||||
secondaryViewController := controllers.NewMainViewController(common, gui.State.Contexts.NormalSecondary, gui.State.Contexts.Normal)
|
||||
patchBuildingController := controllers.NewPatchBuildingController(common)
|
||||
snakeController := controllers.NewSnakeController(common)
|
||||
reflogCommitsController := controllers.NewReflogCommitsController(common)
|
||||
subCommitsController := controllers.NewSubCommitsController(common)
|
||||
@@ -285,28 +277,6 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
)
|
||||
|
||||
// TODO: add scroll controllers for main panels (need to bring some more functionality across for that e.g. reading more from the currently displayed git command)
|
||||
controllers.AttachControllers(gui.State.Contexts.Staging,
|
||||
stagingController,
|
||||
patchExplorerControllerFactory.Create(gui.State.Contexts.Staging),
|
||||
verticalScrollControllerFactory.Create(gui.State.Contexts.Staging),
|
||||
)
|
||||
|
||||
controllers.AttachControllers(gui.State.Contexts.StagingSecondary,
|
||||
stagingSecondaryController,
|
||||
patchExplorerControllerFactory.Create(gui.State.Contexts.StagingSecondary),
|
||||
verticalScrollControllerFactory.Create(gui.State.Contexts.StagingSecondary),
|
||||
)
|
||||
|
||||
controllers.AttachControllers(gui.State.Contexts.CustomPatchBuilder,
|
||||
patchBuildingController,
|
||||
patchExplorerControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder),
|
||||
verticalScrollControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder),
|
||||
)
|
||||
|
||||
controllers.AttachControllers(gui.State.Contexts.CustomPatchBuilderSecondary,
|
||||
verticalScrollControllerFactory.Create(gui.State.Contexts.CustomPatchBuilderSecondary),
|
||||
)
|
||||
|
||||
controllers.AttachControllers(gui.State.Contexts.MergeConflicts,
|
||||
mergeConflictsController,
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
@@ -76,20 +75,12 @@ func (self *ContextLinesController) applyChange() error {
|
||||
self.c.Toast(fmt.Sprintf(self.c.Tr.DiffContextSizeChanged, self.c.UserConfig().Git.DiffContextSize))
|
||||
|
||||
currentContext := self.c.Context().CurrentSide()
|
||||
switch currentContext.GetKey() {
|
||||
// we make an exception for our staging and patch building contexts because they actually need to refresh their state afterwards.
|
||||
case context.PATCH_BUILDING_MAIN_CONTEXT_KEY:
|
||||
self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.PATCH_BUILDING}})
|
||||
case context.STAGING_MAIN_CONTEXT_KEY, context.STAGING_SECONDARY_CONTEXT_KEY:
|
||||
self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STAGING}})
|
||||
default:
|
||||
// The diff is about to be rendered again with more or less context around
|
||||
// each change, which reads as the lines you were looking at moving up or down
|
||||
// the view; keep them where they are instead.
|
||||
self.c.Helpers().DiffLine.PreserveDiffPositionOnRerender(self.c.Contexts().Normal.GetView())
|
||||
self.c.Helpers().DiffLine.PreserveDiffPositionOnRerender(self.c.Contexts().NormalSecondary.GetView())
|
||||
currentContext.HandleRenderToMain()
|
||||
}
|
||||
// The diff is about to be rendered again with more or less context around
|
||||
// each change, which reads as the lines you were looking at moving up or down
|
||||
// the view; keep them where they are instead.
|
||||
self.c.Helpers().DiffLine.PreserveDiffPositionOnRerender(self.c.Contexts().Normal.GetView())
|
||||
self.c.Helpers().DiffLine.PreserveDiffPositionOnRerender(self.c.Contexts().NormalSecondary.GetView())
|
||||
currentContext.HandleRenderToMain()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
{
|
||||
Label: self.c.Tr.ResetPatch,
|
||||
Tooltip: self.c.Tr.ResetPatchTooltip,
|
||||
OnPress: self.c.Helpers().PatchBuilding.Reset,
|
||||
OnPress: self.c.Helpers().CustomPatch.Reset,
|
||||
Keys: menuKey('c'),
|
||||
},
|
||||
{
|
||||
@@ -123,15 +123,7 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int {
|
||||
return -1
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) returnFocusFromPatchExplorerIfNecessary() {
|
||||
if self.c.Context().Current().GetKey() == self.c.Contexts().CustomPatchBuilder.GetKey() {
|
||||
self.c.Helpers().PatchBuilding.Escape()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
commits := self.c.Model().Commits
|
||||
commitIndex := self.getPatchCommitIndex()
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
|
||||
@@ -142,8 +134,6 @@ func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error {
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handleMovePatchToSelectedCommit() error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
commits := self.c.Model().Commits
|
||||
commitIndex := self.getPatchCommitIndex()
|
||||
toCommitIndex := self.c.Contexts().LocalCommits.GetSelectedLineIdx()
|
||||
@@ -155,8 +145,6 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchToSelectedCommit() erro
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules()
|
||||
return self.c.ConfirmIf(mustStash, types.ConfirmOpts{
|
||||
Title: self.c.Tr.MustStashTitle,
|
||||
@@ -174,8 +162,6 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
commitIndex := self.getPatchCommitIndex()
|
||||
self.c.Helpers().Commits.OpenCommitMessagePanel(
|
||||
&helpers.OpenCommitMessagePanelOpts{
|
||||
@@ -209,8 +195,6 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommitBefore() error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
commitIndex := self.getPatchCommitIndex()
|
||||
self.c.Helpers().Commits.OpenCommitMessagePanel(
|
||||
&helpers.OpenCommitMessagePanelOpts{
|
||||
@@ -244,8 +228,6 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommitBefore() e
|
||||
}
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) handleApplyPatch(reverse bool) error {
|
||||
self.returnFocusFromPatchExplorerIfNecessary()
|
||||
|
||||
affectedUnstagedFiles := self.getAffectedUnstagedFiles()
|
||||
|
||||
mustStageFiles := len(affectedUnstagedFiles) > 0
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package helpers
|
||||
|
||||
import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
|
||||
type CustomPatchHelper struct {
|
||||
c *HelperCommon
|
||||
}
|
||||
|
||||
func NewCustomPatchHelper(c *HelperCommon) *CustomPatchHelper {
|
||||
return &CustomPatchHelper{c: c}
|
||||
}
|
||||
|
||||
func (self *CustomPatchHelper) Reset() error {
|
||||
self.c.Git().Patch.PatchBuilder.Reset()
|
||||
self.c.Refresh(types.RefreshOptions{
|
||||
Scope: []types.RefreshableView{types.COMMIT_FILES},
|
||||
})
|
||||
|
||||
// Render again so that the pane that was previewing the patch goes with it. The
|
||||
// panel asked to do that is the side panel rather than whichever context has the
|
||||
// focus. Both main panes are rendered by the panel beneath them, so a reset from
|
||||
// within the focused main view has to go through that panel too.
|
||||
self.c.PostRefreshUpdate(self.c.Context().CurrentSide())
|
||||
return nil
|
||||
}
|
||||
@@ -28,8 +28,7 @@ type Helpers struct {
|
||||
MergeConflicts *MergeConflictsHelper
|
||||
CherryPick *CherryPickHelper
|
||||
Host *HostHelper
|
||||
PatchBuilding *PatchBuildingHelper
|
||||
Staging *StagingHelper
|
||||
CustomPatch *CustomPatchHelper
|
||||
GPG *GpgHelper
|
||||
Upstream *UpstreamHelper
|
||||
AmendHelper *AmendHelper
|
||||
@@ -68,8 +67,7 @@ func NewStubHelpers() *Helpers {
|
||||
MergeConflicts: &MergeConflictsHelper{},
|
||||
CherryPick: &CherryPickHelper{},
|
||||
Host: &HostHelper{},
|
||||
PatchBuilding: &PatchBuildingHelper{},
|
||||
Staging: &StagingHelper{},
|
||||
CustomPatch: &CustomPatchHelper{},
|
||||
GPG: &GpgHelper{},
|
||||
Upstream: &UpstreamHelper{},
|
||||
AmendHelper: &AmendHelper{},
|
||||
|
||||
@@ -14,7 +14,7 @@ type ModeHelper struct {
|
||||
c *HelperCommon
|
||||
|
||||
diffHelper *DiffHelper
|
||||
patchBuildingHelper *PatchBuildingHelper
|
||||
customPatchHelper *CustomPatchHelper
|
||||
cherryPickHelper *CherryPickHelper
|
||||
mergeAndRebaseHelper *MergeAndRebaseHelper
|
||||
bisectHelper *BisectHelper
|
||||
@@ -24,7 +24,7 @@ type ModeHelper struct {
|
||||
func NewModeHelper(
|
||||
c *HelperCommon,
|
||||
diffHelper *DiffHelper,
|
||||
patchBuildingHelper *PatchBuildingHelper,
|
||||
customPatchHelper *CustomPatchHelper,
|
||||
cherryPickHelper *CherryPickHelper,
|
||||
mergeAndRebaseHelper *MergeAndRebaseHelper,
|
||||
bisectHelper *BisectHelper,
|
||||
@@ -32,7 +32,7 @@ func NewModeHelper(
|
||||
return &ModeHelper{
|
||||
c: c,
|
||||
diffHelper: diffHelper,
|
||||
patchBuildingHelper: patchBuildingHelper,
|
||||
customPatchHelper: customPatchHelper,
|
||||
cherryPickHelper: cherryPickHelper,
|
||||
mergeAndRebaseHelper: mergeAndRebaseHelper,
|
||||
bisectHelper: bisectHelper,
|
||||
@@ -73,7 +73,7 @@ func (self *ModeHelper) Statuses() []ModeStatus {
|
||||
CancelLabel: func() string {
|
||||
return self.c.Tr.ExitCustomPatchBuilder
|
||||
},
|
||||
Reset: self.patchBuildingHelper.Reset,
|
||||
Reset: self.customPatchHelper.Reset,
|
||||
},
|
||||
{
|
||||
IsActive: self.c.Modes().Filtering.Active,
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type PatchBuildingHelper struct {
|
||||
c *HelperCommon
|
||||
}
|
||||
|
||||
func NewPatchBuildingHelper(
|
||||
c *HelperCommon,
|
||||
) *PatchBuildingHelper {
|
||||
return &PatchBuildingHelper{
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
// takes us from the patch building panel back to the commit files panel
|
||||
func (self *PatchBuildingHelper) Escape() {
|
||||
self.c.Context().Pop()
|
||||
}
|
||||
|
||||
// kills the custom patch and returns us back to the commit files panel if needed
|
||||
func (self *PatchBuildingHelper) Reset() error {
|
||||
self.c.Git().Patch.PatchBuilder.Reset()
|
||||
|
||||
// The patch-building view is the one thing with nothing left to show once the patch is
|
||||
// gone, so it is the one thing left behind. Everywhere else the user is looking at
|
||||
// something of their own — a commit's diff, the working tree's — which is still there.
|
||||
if self.c.Context().CurrentStatic().GetKey() == self.c.Contexts().CustomPatchBuilder.GetKey() {
|
||||
self.Escape()
|
||||
}
|
||||
|
||||
self.c.Refresh(types.RefreshOptions{
|
||||
Scope: []types.RefreshableView{types.COMMIT_FILES},
|
||||
})
|
||||
|
||||
// Render again so that the pane that was previewing the patch goes with it. The
|
||||
// panel asked to do that is the side panel rather than whichever context has the
|
||||
// focus. Both main panes are rendered by the panel beneath them, so a reset from
|
||||
// within the focused main view has to go through that panel too.
|
||||
self.c.PostRefreshUpdate(self.c.Context().CurrentSide())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpts) {
|
||||
selectedLineIdx := -1
|
||||
if opts.ClickedWindowName == "main" {
|
||||
selectedLineIdx = opts.ClickedViewLineIdx
|
||||
}
|
||||
|
||||
if !self.c.Git().Patch.PatchBuilder.Active() {
|
||||
self.Escape()
|
||||
return
|
||||
}
|
||||
|
||||
// get diff from commit file that's currently selected
|
||||
file := self.c.Contexts().CommitFiles.GetSelectedFile()
|
||||
if file == nil {
|
||||
return
|
||||
}
|
||||
|
||||
from, to := self.c.Contexts().CommitFiles.GetFromAndToForDiff()
|
||||
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
|
||||
diff, err := self.c.Git().WorkingTree.ShowFileDiff(from, to, reverse, file.Path, file.PreviousPath, git_commands.DiffModePlain)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
secondaryDiff := self.c.Git().Patch.PatchBuilder.RenderPatchForFile(patch.RenderPatchForFileOpts{
|
||||
Filename: file.Path,
|
||||
PreviousPath: file.PreviousPath,
|
||||
Plain: false,
|
||||
Reverse: false,
|
||||
TurnAddedFilesIntoDiffAgainstEmptyFile: true,
|
||||
})
|
||||
|
||||
context := self.c.Contexts().CustomPatchBuilder
|
||||
|
||||
oldState := context.GetState()
|
||||
|
||||
state := patch_exploring.NewState(diff, selectedLineIdx, context.GetView(), oldState, self.c.UserConfig().Gui.UseHunkModeInStagingView)
|
||||
context.SetState(state)
|
||||
if state == nil {
|
||||
self.Escape()
|
||||
return
|
||||
}
|
||||
|
||||
mainContent := context.GetContentToRender()
|
||||
|
||||
self.c.Contexts().CustomPatchBuilder.FocusSelection()
|
||||
|
||||
self.c.RenderToMainViews(types.RefreshMainOpts{
|
||||
Pair: self.c.MainViewPairs().PatchBuilding,
|
||||
Main: &types.ViewUpdateOpts{
|
||||
Task: types.NewRenderStringWithoutScrollTask(mainContent),
|
||||
Title: self.c.Tr.Patch,
|
||||
},
|
||||
Secondary: &types.ViewUpdateOpts{
|
||||
Task: types.NewRenderStringWithoutScrollTask(secondaryDiff),
|
||||
Title: self.c.Tr.CustomPatch,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -30,8 +30,6 @@ type RefreshHelper struct {
|
||||
c *HelperCommon
|
||||
refsHelper *RefsHelper
|
||||
mergeAndRebaseHelper *MergeAndRebaseHelper
|
||||
patchBuildingHelper *PatchBuildingHelper
|
||||
stagingHelper *StagingHelper
|
||||
mergeConflictsHelper *MergeConflictsHelper
|
||||
worktreeHelper *WorktreeHelper
|
||||
searchHelper *SearchHelper
|
||||
@@ -62,8 +60,6 @@ func NewRefreshHelper(
|
||||
c *HelperCommon,
|
||||
refsHelper *RefsHelper,
|
||||
mergeAndRebaseHelper *MergeAndRebaseHelper,
|
||||
patchBuildingHelper *PatchBuildingHelper,
|
||||
stagingHelper *StagingHelper,
|
||||
mergeConflictsHelper *MergeConflictsHelper,
|
||||
worktreeHelper *WorktreeHelper,
|
||||
searchHelper *SearchHelper,
|
||||
@@ -72,8 +68,6 @@ func NewRefreshHelper(
|
||||
c: c,
|
||||
refsHelper: refsHelper,
|
||||
mergeAndRebaseHelper: mergeAndRebaseHelper,
|
||||
patchBuildingHelper: patchBuildingHelper,
|
||||
stagingHelper: stagingHelper,
|
||||
mergeConflictsHelper: mergeConflictsHelper,
|
||||
worktreeHelper: worktreeHelper,
|
||||
searchHelper: searchHelper,
|
||||
@@ -248,8 +242,6 @@ func (self *RefreshHelper) performRefresh(options types.RefreshOptions, calledFr
|
||||
|
||||
var scopeSet *set.Set[types.RefreshableView]
|
||||
if len(options.Scope) == 0 {
|
||||
// not refreshing staging/patch-building unless explicitly requested because we only need
|
||||
// to refresh those while focused.
|
||||
scopeSet = set.NewFromSlice([]types.RefreshableView{
|
||||
types.COMMITS,
|
||||
types.BRANCHES,
|
||||
@@ -261,7 +253,6 @@ func (self *RefreshHelper) performRefresh(options types.RefreshOptions, calledFr
|
||||
types.WORKTREES,
|
||||
types.STATUS,
|
||||
types.BISECT_INFO,
|
||||
types.STAGING,
|
||||
types.PULL_REQUESTS,
|
||||
})
|
||||
} else {
|
||||
@@ -516,37 +507,9 @@ func (self *RefreshHelper) performRefresh(options types.RefreshOptions, calledFr
|
||||
})
|
||||
}
|
||||
|
||||
if scopeSet.Includes(types.STAGING) {
|
||||
refresh("staging", func() {
|
||||
fileWg.Wait()
|
||||
// Bounce onto the UI thread so this runs after the files
|
||||
// scope's model-update bounce — RefreshStagingPanel reads
|
||||
// Model.Files (via Files.GetSelected) and would otherwise
|
||||
// see the pre-refresh model. Guard on the generation so a
|
||||
// repo switch mid-refresh drops it, like the model bounces.
|
||||
self.onUIThreadUnlessRepoChanged(env, func() {
|
||||
self.stagingHelper.RefreshStagingPanel(types.OnFocusOpts{})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if scopeSet.Includes(types.PATCH_BUILDING) {
|
||||
refresh("patch building", func() {
|
||||
// Bounce onto the UI thread, like the staging panel above:
|
||||
// RefreshPatchBuildingPanel reads the commit-files selection and
|
||||
// sets the patch view's origin, neither of which may run off the UI
|
||||
// thread. Guard on the generation so a repo switch mid-refresh drops
|
||||
// it, like the model bounces.
|
||||
self.onUIThreadUnlessRepoChanged(env, func() {
|
||||
self.patchBuildingHelper.RefreshPatchBuildingPanel(types.OnFocusOpts{})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if scopeSet.Includes(types.MERGE_CONFLICTS) {
|
||||
refresh("merge conflicts", func() {
|
||||
// Bounce onto the UI thread, like the staging and patch-building
|
||||
// panels above: RefreshMergeState reads the current context and
|
||||
// Bounce onto the UI thread: RefreshMergeState reads the current context and
|
||||
// renders (or escapes) the merge-conflicts view, none of which may
|
||||
// run off the UI thread.
|
||||
self.onUIThreadUnlessRepoChanged(env, func() {
|
||||
@@ -676,8 +639,6 @@ func getScopeNames(scopes []types.RefreshableView) []string {
|
||||
types.WORKTREES: "worktrees",
|
||||
types.STATUS: "status",
|
||||
types.BISECT_INFO: "bisect",
|
||||
types.STAGING: "staging",
|
||||
types.PATCH_BUILDING: "patchBuilding",
|
||||
types.MERGE_CONFLICTS: "mergeConflicts",
|
||||
types.COMMIT_FILES: "commitFiles",
|
||||
types.PULL_REQUESTS: "pullRequests",
|
||||
|
||||
@@ -50,7 +50,6 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
|
||||
types.REFLOG,
|
||||
types.WORKTREES,
|
||||
types.BISECT_INFO,
|
||||
types.STAGING,
|
||||
}
|
||||
if options.RefreshPullRequests {
|
||||
scope = append(scope, types.PULL_REQUESTS)
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type StagingHelper struct {
|
||||
c *HelperCommon
|
||||
}
|
||||
|
||||
func NewStagingHelper(
|
||||
c *HelperCommon,
|
||||
) *StagingHelper {
|
||||
return &StagingHelper{
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: used from outside this file
|
||||
func (self *StagingHelper) RefreshStagingPanel(focusOpts types.OnFocusOpts) {
|
||||
secondaryFocused := self.secondaryStagingFocused()
|
||||
mainFocused := self.mainStagingFocused()
|
||||
|
||||
// this method could be called when the staging panel is not being used,
|
||||
// in which case we don't want to do anything.
|
||||
if !mainFocused && !secondaryFocused {
|
||||
return
|
||||
}
|
||||
|
||||
mainSelectedLineIdx := -1
|
||||
secondarySelectedLineIdx := -1
|
||||
if focusOpts.ClickedViewLineIdx > 0 {
|
||||
if secondaryFocused {
|
||||
secondarySelectedLineIdx = focusOpts.ClickedViewLineIdx
|
||||
} else {
|
||||
mainSelectedLineIdx = focusOpts.ClickedViewLineIdx
|
||||
}
|
||||
}
|
||||
|
||||
mainContext := self.c.Contexts().Staging
|
||||
secondaryContext := self.c.Contexts().StagingSecondary
|
||||
|
||||
var file *models.File
|
||||
node := self.c.Contexts().Files.GetSelected()
|
||||
if node != nil {
|
||||
file = node.File
|
||||
}
|
||||
|
||||
if file == nil || (!file.HasUnstagedChanges && !file.HasStagedChanges) {
|
||||
self.handleStagingEscape()
|
||||
return
|
||||
}
|
||||
|
||||
mainDiff := self.c.Git().WorkingTree.WorktreeFileDiff(file, git_commands.DiffModePlain, false)
|
||||
secondaryDiff := self.c.Git().WorkingTree.WorktreeFileDiff(file, git_commands.DiffModePlain, true)
|
||||
|
||||
// grabbing locks here and releasing before we finish the function
|
||||
// because pushing say the secondary context could mean entering this function
|
||||
// again, and we don't want to have a deadlock
|
||||
mainContext.GetMutex().Lock()
|
||||
secondaryContext.GetMutex().Lock()
|
||||
|
||||
hunkMode := self.c.UserConfig().Gui.UseHunkModeInStagingView
|
||||
mainContext.SetState(
|
||||
patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainContext.GetView(), mainContext.GetState(), hunkMode),
|
||||
)
|
||||
|
||||
secondaryContext.SetState(
|
||||
patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondaryContext.GetView(), secondaryContext.GetState(), hunkMode),
|
||||
)
|
||||
|
||||
mainState := mainContext.GetState()
|
||||
secondaryState := secondaryContext.GetState()
|
||||
|
||||
mainContent := mainContext.GetContentToRender()
|
||||
secondaryContent := secondaryContext.GetContentToRender()
|
||||
|
||||
mainContext.GetMutex().Unlock()
|
||||
secondaryContext.GetMutex().Unlock()
|
||||
|
||||
if mainState == nil && secondaryState == nil {
|
||||
self.handleStagingEscape()
|
||||
return
|
||||
}
|
||||
|
||||
if mainState == nil && !secondaryFocused {
|
||||
self.c.Context().Push(secondaryContext, focusOpts)
|
||||
return
|
||||
}
|
||||
|
||||
if secondaryState == nil && secondaryFocused {
|
||||
self.c.Context().Push(mainContext, focusOpts)
|
||||
return
|
||||
}
|
||||
|
||||
if secondaryFocused {
|
||||
self.c.Contexts().StagingSecondary.FocusSelection()
|
||||
} else {
|
||||
self.c.Contexts().Staging.FocusSelection()
|
||||
}
|
||||
|
||||
self.c.RenderToMainViews(types.RefreshMainOpts{
|
||||
Pair: self.c.MainViewPairs().Staging,
|
||||
Main: &types.ViewUpdateOpts{
|
||||
Task: types.NewRenderStringWithoutScrollTask(mainContent),
|
||||
Title: self.c.Tr.UnstagedChanges,
|
||||
},
|
||||
Secondary: &types.ViewUpdateOpts{
|
||||
Task: types.NewRenderStringWithoutScrollTask(secondaryContent),
|
||||
Title: self.c.Tr.StagedChanges,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *StagingHelper) handleStagingEscape() {
|
||||
self.c.Context().Push(self.c.Contexts().Files, types.OnFocusOpts{})
|
||||
}
|
||||
|
||||
func (self *StagingHelper) secondaryStagingFocused() bool {
|
||||
return self.c.Context().CurrentStatic().GetKey() == self.c.Contexts().StagingSecondary.GetKey()
|
||||
}
|
||||
|
||||
func (self *StagingHelper) mainStagingFocused() bool {
|
||||
return self.c.Context().CurrentStatic().GetKey() == self.c.Contexts().Staging.GetKey()
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type PatchBuildingController struct {
|
||||
baseController
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &PatchBuildingController{}
|
||||
|
||||
func NewPatchBuildingController(
|
||||
c *ControllerCommon,
|
||||
) *PatchBuildingController {
|
||||
return &PatchBuildingController{
|
||||
baseController: baseController{},
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.OpenFile),
|
||||
Handler: self.OpenFile,
|
||||
Description: self.c.Tr.OpenFile,
|
||||
Tooltip: self.c.Tr.OpenFileTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Edit),
|
||||
Handler: self.EditFile,
|
||||
Description: self.c.Tr.EditFile,
|
||||
Tooltip: self.c.Tr.EditFileTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Select),
|
||||
Handler: self.ToggleSelectionAndRefresh,
|
||||
Description: self.c.Tr.ToggleSelectionForPatch,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Remove),
|
||||
Handler: self.discardSelection,
|
||||
GetDisabledReason: self.getDisabledReasonForDiscard,
|
||||
Description: self.c.Tr.RemoveSelectionFromPatch,
|
||||
Tooltip: self.c.Tr.RemoveSelectionFromPatchTooltip,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Return),
|
||||
Handler: self.Escape,
|
||||
Description: self.c.Tr.ExitCustomPatchBuilder,
|
||||
DescriptionFunc: self.EscapeDescription,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) Context() types.Context {
|
||||
return self.c.Contexts().CustomPatchBuilder
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) context() types.IPatchExplorerContext {
|
||||
return self.c.Contexts().CustomPatchBuilder
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
||||
return []*gocui.ViewMouseBinding{}
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) GetOnFocus() func(types.OnFocusOpts) {
|
||||
return func(opts types.OnFocusOpts) {
|
||||
// no need to change wrap on the secondary view because it can't be interacted with
|
||||
self.c.Views().PatchBuilding.Wrap = self.c.UserConfig().Gui.WrapLinesInStagingView
|
||||
|
||||
self.c.Helpers().PatchBuilding.RefreshPatchBuildingPanel(opts)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) GetOnFocusLost() func(types.OnFocusLostOpts) {
|
||||
return func(opts types.OnFocusLostOpts) {
|
||||
self.context().SetState(nil)
|
||||
|
||||
self.c.Views().PatchBuilding.Wrap = true
|
||||
|
||||
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
|
||||
self.c.Git().Patch.PatchBuilder.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) OpenFile() error {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
||||
path := self.c.Contexts().CommitFiles.GetSelectedPath()
|
||||
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.c.Helpers().Files.OpenFile(path)
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) EditFile() error {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
||||
path := self.c.Contexts().CommitFiles.GetSelectedPath()
|
||||
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
lineNumber := self.context().GetState().CurrentLineNumber()
|
||||
lineNumber = self.c.Helpers().Diff.AdjustLineNumber(path, lineNumber, self.context().GetViewName())
|
||||
return self.c.Helpers().Files.EditFileAtLine(path, lineNumber)
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) ToggleSelectionAndRefresh() error {
|
||||
if err := self.toggleSelection(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Refresh(types.RefreshOptions{
|
||||
Scope: []types.RefreshableView{types.PATCH_BUILDING, types.COMMIT_FILES},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) toggleSelection() error {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
||||
file := self.c.Contexts().CommitFiles.GetSelectedFile()
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
state := self.context().GetState()
|
||||
|
||||
// Get added/deleted lines in the selected patch range
|
||||
lineIndicesToToggle := state.LineIndicesOfAddedOrDeletedLinesInSelectedPatchRange()
|
||||
if len(lineIndicesToToggle) == 0 {
|
||||
// Only context lines or header lines selected, so nothing to do
|
||||
return nil
|
||||
}
|
||||
|
||||
includedLineIndices, err := self.c.Git().Patch.PatchBuilder.GetFileIncLineIndices(file.Path, file.PreviousPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toggleFunc := self.c.Git().Patch.PatchBuilder.AddFileLineRange
|
||||
firstSelectedChangeLineIsStaged := lo.Contains(includedLineIndices, lineIndicesToToggle[0])
|
||||
if firstSelectedChangeLineIsStaged {
|
||||
toggleFunc = self.c.Git().Patch.PatchBuilder.RemoveFileLineRange
|
||||
}
|
||||
|
||||
// add range of lines to those set for the file
|
||||
if err := toggleFunc(file.Path, file.PreviousPath, lineIndicesToToggle); err != nil {
|
||||
// might actually want to return an error here
|
||||
self.c.Log.Error(err)
|
||||
}
|
||||
|
||||
if state.SelectingRange() {
|
||||
state.SetLineSelectMode()
|
||||
}
|
||||
|
||||
state.SelectNextStageableLineOfSameIncludedState(self.context().GetIncludedLineIndices(), firstSelectedChangeLineIsStaged)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) getDisabledReasonForDiscard() *types.DisabledReason {
|
||||
if !self.c.Git().Patch.PatchBuilder.CanRebase {
|
||||
return &types.DisabledReason{Text: self.c.Tr.CanOnlyDiscardFromLocalCommits, ShowErrorInPanel: true}
|
||||
}
|
||||
if self.c.Git().Status.WorkingTreeState().Any() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.CantPatchWhileRebasingError, ShowErrorInPanel: true}
|
||||
}
|
||||
if self.c.UserConfig().Git.DiffContextSize == 0 {
|
||||
text := fmt.Sprintf(self.c.Tr.Actions.NotEnoughContextToRemoveLines,
|
||||
self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView)
|
||||
return &types.DisabledReason{Text: text, ShowErrorInPanel: true}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) discardSelection() error {
|
||||
prompt := lo.Ternary(self.c.Git().Patch.PatchBuilder.IsEmpty(),
|
||||
self.c.Tr.DiscardLinesFromCommitPrompt,
|
||||
self.c.Tr.DiscardLinesFromCommitPromptWithReset)
|
||||
|
||||
self.c.Confirm(types.ConfirmOpts{
|
||||
Title: self.c.Tr.DiscardLinesFromCommitTitle,
|
||||
Prompt: prompt,
|
||||
HandleConfirm: func() error {
|
||||
return self.discardSelectionFromCommit()
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) discardSelectionFromCommit() error {
|
||||
// Reset the current patch if there is one.
|
||||
if !self.c.Git().Patch.PatchBuilder.IsEmpty() {
|
||||
self.c.Git().Patch.PatchBuilder.Reset()
|
||||
}
|
||||
|
||||
if err := self.toggleSelection(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
|
||||
return nil
|
||||
}
|
||||
|
||||
commits := self.c.Model().Commits
|
||||
commitIndex := self.getPatchCommitIndex()
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RemovePatchFromCommit)
|
||||
err := self.c.Git().Patch.DeletePatchesFromCommit(commits, commitIndex)
|
||||
// Escape pops the patch-building context, so run it on the UI thread
|
||||
// before the refresh below.
|
||||
_ = self.c.GocuiGui().OnUIThreadAndWait(func() {
|
||||
self.c.Helpers().PatchBuilding.Escape()
|
||||
})
|
||||
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
|
||||
err, types.RefreshOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) getPatchCommitIndex() int {
|
||||
for index, commit := range self.c.Model().Commits {
|
||||
if commit.Hash() == self.c.Git().Patch.PatchBuilder.To {
|
||||
return index
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) Escape() error {
|
||||
context := self.c.Contexts().CustomPatchBuilder
|
||||
state := context.GetState()
|
||||
|
||||
if state.SelectingRange() || state.SelectingHunkEnabledByUser() {
|
||||
state.SetLineSelectMode()
|
||||
self.c.PostRefreshUpdate(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
self.c.Helpers().PatchBuilding.Escape()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchBuildingController) EscapeDescription() string {
|
||||
context := self.c.Contexts().CustomPatchBuilder
|
||||
if state := context.GetState(); state != nil {
|
||||
if state.SelectingRange() {
|
||||
return self.c.Tr.DismissRangeSelect
|
||||
}
|
||||
|
||||
if state.SelectingHunkEnabledByUser() {
|
||||
return self.c.Tr.SelectLineByLine
|
||||
}
|
||||
}
|
||||
|
||||
return self.c.Tr.ExitCustomPatchBuilder
|
||||
}
|
||||
@@ -1,377 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type PatchExplorerControllerFactory struct {
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
func NewPatchExplorerControllerFactory(c *ControllerCommon) *PatchExplorerControllerFactory {
|
||||
return &PatchExplorerControllerFactory{
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchExplorerControllerFactory) Create(context types.IPatchExplorerContext) *PatchExplorerController {
|
||||
controller := &PatchExplorerController{
|
||||
baseController: baseController{},
|
||||
c: self.c,
|
||||
context: context,
|
||||
}
|
||||
controller.dragAutoscroller = helpers.NewDragAutoscroller(
|
||||
self.c.HelperCommon,
|
||||
context,
|
||||
controller.canDragAutoscroll,
|
||||
controller.handleDragAutoscroll,
|
||||
)
|
||||
return controller
|
||||
}
|
||||
|
||||
type PatchExplorerController struct {
|
||||
baseController
|
||||
c *ControllerCommon
|
||||
|
||||
context types.IPatchExplorerContext
|
||||
dragAutoscroller *helpers.DragAutoscroller
|
||||
draggingWithMouse bool
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.PrevItem),
|
||||
Handler: self.withRenderAndFocus(self.HandlePrevLine),
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.NextItem),
|
||||
Handler: self.withRenderAndFocus(self.HandleNextLine),
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.RangeSelectUp),
|
||||
Handler: self.withRenderAndFocus(self.HandlePrevLineRange),
|
||||
Description: self.c.Tr.RangeSelectUp,
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.RangeSelectDown),
|
||||
Handler: self.withRenderAndFocus(self.HandleNextLineRange),
|
||||
Description: self.c.Tr.RangeSelectDown,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Main.PrevHunk),
|
||||
Handler: self.withRenderAndFocus(self.HandlePrevHunk),
|
||||
Description: self.c.Tr.PrevHunk,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Main.NextHunk),
|
||||
Handler: self.withRenderAndFocus(self.HandleNextHunk),
|
||||
Description: self.c.Tr.NextHunk,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.ToggleRangeSelect),
|
||||
Handler: self.withRenderAndFocus(self.HandleToggleSelectRange),
|
||||
Description: self.c.Tr.ToggleRangeSelect,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Main.ToggleSelectHunk),
|
||||
Handler: self.withRenderAndFocus(self.HandleToggleSelectHunk),
|
||||
Description: self.c.Tr.ToggleSelectHunk,
|
||||
DescriptionFunc: func() string {
|
||||
if state := self.context.GetState(); state != nil && state.SelectingHunk() {
|
||||
return self.c.Tr.SelectLineByLine
|
||||
}
|
||||
return self.c.Tr.SelectHunk
|
||||
},
|
||||
Tooltip: self.c.Tr.ToggleSelectHunkTooltip,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.PrevPage),
|
||||
Handler: self.withRenderAndFocus(self.HandlePrevPage),
|
||||
Description: self.c.Tr.PrevPage,
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.NextPage),
|
||||
Handler: self.withRenderAndFocus(self.HandleNextPage),
|
||||
Description: self.c.Tr.NextPage,
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.GotoTop),
|
||||
Handler: self.withRenderAndFocus(self.HandleGotoTop),
|
||||
Description: self.c.Tr.GotoTop,
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.GotoBottom),
|
||||
Description: self.c.Tr.GotoBottom,
|
||||
Handler: self.withRenderAndFocus(self.HandleGotoBottom),
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.ScrollLeft),
|
||||
Handler: self.withRenderAndFocus(self.HandleScrollLeft),
|
||||
},
|
||||
{
|
||||
Tag: "navigation",
|
||||
Keys: opts.GetKeys(opts.Config.Universal.ScrollRight),
|
||||
Handler: self.withRenderAndFocus(self.HandleScrollRight),
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.CopyToClipboard),
|
||||
Handler: self.withLock(self.CopySelectedToClipboard),
|
||||
Description: self.c.Tr.CopySelectedTextToClipboard,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
||||
return []*gocui.ViewMouseBinding{
|
||||
{
|
||||
ViewName: self.context.GetViewName(),
|
||||
Key: gocui.MouseLeft,
|
||||
Handler: func(opts gocui.ViewMouseBindingOpts) error {
|
||||
if self.isFocused() {
|
||||
return self.withRenderAndFocus(self.HandleMouseDown)()
|
||||
}
|
||||
|
||||
self.c.Context().Push(self.context, types.OnFocusOpts{
|
||||
ClickedWindowName: self.context.GetWindowName(),
|
||||
ClickedViewLineIdx: opts.Y,
|
||||
})
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
ViewName: self.context.GetViewName(),
|
||||
Key: gocui.MouseLeft,
|
||||
Modifier: gocui.ModMotion,
|
||||
Handler: self.handleMouseDrag,
|
||||
},
|
||||
{
|
||||
ViewName: self.context.GetViewName(),
|
||||
Key: gocui.MouseRelease,
|
||||
Handler: func(gocui.ViewMouseBindingOpts) error { return self.handleDragRelease() },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) handleMouseDrag(opts gocui.ViewMouseBindingOpts) error {
|
||||
if err := self.withLock(func() error {
|
||||
self.context.GetState().DragSelectLine(opts.Y)
|
||||
self.renderDragSelection()
|
||||
return nil
|
||||
})(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.draggingWithMouse = true
|
||||
originY, _ := self.context.GetViewTrait().ViewPortYBounds()
|
||||
self.dragAutoscroller.Update(opts.Y - originY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) canDragAutoscroll(int) bool {
|
||||
state := self.context.GetState()
|
||||
return state != nil && state.SelectingRange()
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) handleDragAutoscroll(viewIndex int) bool {
|
||||
if !self.canDragAutoscroll(0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if err := self.withLock(func() error {
|
||||
self.context.GetState().DragSelectLine(viewIndex)
|
||||
self.renderDragSelection()
|
||||
return nil
|
||||
})(); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) renderDragSelection() {
|
||||
view := self.context.GetView()
|
||||
state := self.context.GetState()
|
||||
originY := view.OriginY()
|
||||
startIndex, _ := state.SelectedViewRange()
|
||||
view.SetRangeSelectStart(startIndex)
|
||||
view.SetCursorY(state.GetSelectedViewLineIdx() - originY)
|
||||
self.context.Render()
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) handleDragRelease() error {
|
||||
self.draggingWithMouse = false
|
||||
self.dragAutoscroller.Cancel()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) GetOnFocusLost() func(types.OnFocusLostOpts) {
|
||||
return func(types.OnFocusLostOpts) {
|
||||
self.dragAutoscroller.Cancel()
|
||||
if self.draggingWithMouse {
|
||||
self.draggingWithMouse = false
|
||||
self.c.GocuiGui().CancelMouseCapture()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandlePrevLine() error {
|
||||
before := self.context.GetState().GetSelectedViewLineIdx()
|
||||
self.context.GetState().CycleSelection(false)
|
||||
after := self.context.GetState().GetSelectedViewLineIdx()
|
||||
|
||||
if self.context.GetState().SelectingLine() {
|
||||
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig(), before, after)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleNextLine() error {
|
||||
before := self.context.GetState().GetSelectedViewLineIdx()
|
||||
self.context.GetState().CycleSelection(true)
|
||||
after := self.context.GetState().GetSelectedViewLineIdx()
|
||||
|
||||
if self.context.GetState().SelectingLine() {
|
||||
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig(), before, after)
|
||||
}
|
||||
|
||||
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 {
|
||||
self.context.GetState().SelectPreviousHunk()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleNextHunk() error {
|
||||
self.context.GetState().SelectNextHunk()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleToggleSelectRange() error {
|
||||
self.context.GetState().ToggleStickySelectRange()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleToggleSelectHunk() error {
|
||||
self.context.GetState().ToggleSelectHunk()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleScrollLeft() error {
|
||||
self.context.GetViewTrait().ScrollLeft()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleScrollRight() error {
|
||||
self.context.GetViewTrait().ScrollRight()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandlePrevPage() error {
|
||||
self.context.GetState().AdjustSelectedLineIdx(-self.context.GetViewTrait().PageDelta())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleNextPage() error {
|
||||
self.context.GetState().AdjustSelectedLineIdx(self.context.GetViewTrait().PageDelta())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleGotoTop() error {
|
||||
self.context.GetState().SelectTop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleGotoBottom() error {
|
||||
self.context.GetState().SelectBottom()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) HandleMouseDown() error {
|
||||
self.context.GetState().SelectNewLineForRange(self.context.GetViewTrait().SelectedLineIdx())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) CopySelectedToClipboard() error {
|
||||
selected := self.context.GetState().PlainRenderSelected()
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopySelectedTextToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(dropDiffPrefix(selected)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) isFocused() bool {
|
||||
return self.c.Context().Current().GetKey() == self.context.GetKey()
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) withRenderAndFocus(f func() error) func() error {
|
||||
return self.withLock(func() error {
|
||||
if err := f(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.context.RenderAndFocus()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *PatchExplorerController) withLock(f func() error) func() error {
|
||||
return func() error {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
||||
if self.context.GetState() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return f()
|
||||
}
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type StagingController struct {
|
||||
baseController
|
||||
c *ControllerCommon
|
||||
|
||||
context types.IPatchExplorerContext
|
||||
otherContext types.IPatchExplorerContext
|
||||
|
||||
// if true, we're dealing with the secondary context i.e. dealing with staged file changes
|
||||
staged bool
|
||||
}
|
||||
|
||||
var _ types.IController = &StagingController{}
|
||||
|
||||
func NewStagingController(
|
||||
c *ControllerCommon,
|
||||
context types.IPatchExplorerContext,
|
||||
otherContext types.IPatchExplorerContext,
|
||||
staged bool,
|
||||
) *StagingController {
|
||||
return &StagingController{
|
||||
baseController: baseController{},
|
||||
c: c,
|
||||
context: context,
|
||||
otherContext: otherContext,
|
||||
staged: staged,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StagingController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Select),
|
||||
Handler: self.ToggleStaged,
|
||||
Description: self.c.Tr.Stage,
|
||||
Tooltip: self.c.Tr.StageSelectionTooltip,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Remove),
|
||||
Handler: self.DiscardSelection,
|
||||
Description: self.c.Tr.DiscardSelection,
|
||||
Tooltip: self.c.Tr.DiscardSelectionTooltip,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.OpenFile),
|
||||
Handler: self.OpenFile,
|
||||
Description: self.c.Tr.OpenFile,
|
||||
Tooltip: self.c.Tr.OpenFileTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Edit),
|
||||
Handler: self.EditFile,
|
||||
Description: self.c.Tr.EditFile,
|
||||
Tooltip: self.c.Tr.EditFileTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Return),
|
||||
Handler: self.Escape,
|
||||
Description: self.c.Tr.ReturnToFilesPanel,
|
||||
DescriptionFunc: self.EscapeDescription,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.TogglePanel),
|
||||
Handler: self.TogglePanel,
|
||||
Description: self.c.Tr.ToggleStagingView,
|
||||
Tooltip: self.c.Tr.ToggleStagingViewTooltip,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Main.EditSelectHunk),
|
||||
Handler: self.EditHunkAndRefresh,
|
||||
Description: self.c.Tr.EditHunk,
|
||||
Tooltip: self.c.Tr.EditHunkTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Files.CommitChanges),
|
||||
Handler: self.c.Helpers().WorkingTree.HandleCommitPress,
|
||||
Description: self.c.Tr.Commit,
|
||||
Tooltip: self.c.Tr.CommitTooltip,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Files.CommitChangesWithoutHook),
|
||||
Handler: self.c.Helpers().WorkingTree.HandleWIPCommitPress,
|
||||
Description: self.c.Tr.CommitChangesWithoutHook,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Files.CommitChangesWithEditor),
|
||||
Handler: self.c.Helpers().WorkingTree.HandleCommitEditorPress,
|
||||
Description: self.c.Tr.CommitChangesWithEditor,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Files.FindBaseCommitForFixup),
|
||||
Handler: self.c.Helpers().FixupHelper.HandleFindBaseCommitForFixupPress,
|
||||
Description: self.c.Tr.FindBaseCommitForFixup,
|
||||
Tooltip: self.c.Tr.FindBaseCommitForFixupTooltip,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StagingController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
||||
func (self *StagingController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
||||
return []*gocui.ViewMouseBinding{}
|
||||
}
|
||||
|
||||
func (self *StagingController) GetOnFocus() func(types.OnFocusOpts) {
|
||||
return func(opts types.OnFocusOpts) {
|
||||
wrap := self.c.UserConfig().Gui.WrapLinesInStagingView
|
||||
self.c.Views().Staging.Wrap = wrap
|
||||
self.c.Views().StagingSecondary.Wrap = wrap
|
||||
|
||||
self.c.Helpers().Staging.RefreshStagingPanel(opts)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StagingController) GetOnFocusLost() func(types.OnFocusLostOpts) {
|
||||
return func(opts types.OnFocusLostOpts) {
|
||||
self.context.SetState(nil)
|
||||
|
||||
if opts.NewContextKey != self.otherContext.GetKey() {
|
||||
self.c.Views().Staging.Wrap = true
|
||||
self.c.Views().StagingSecondary.Wrap = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StagingController) OpenFile() error {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
||||
path := self.FilePath()
|
||||
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.c.Helpers().Files.OpenFile(path)
|
||||
}
|
||||
|
||||
func (self *StagingController) EditFile() error {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
||||
path := self.FilePath()
|
||||
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
lineNumber := self.context.GetState().CurrentLineNumber()
|
||||
lineNumber = self.c.Helpers().Diff.AdjustLineNumber(path, lineNumber, self.context.GetViewName())
|
||||
return self.c.Helpers().Files.EditFileAtLine(path, lineNumber)
|
||||
}
|
||||
|
||||
func (self *StagingController) Escape() error {
|
||||
if self.context.GetState().SelectingRange() || self.context.GetState().SelectingHunkEnabledByUser() {
|
||||
self.context.GetState().SetLineSelectMode()
|
||||
self.c.PostRefreshUpdate(self.context)
|
||||
return nil
|
||||
}
|
||||
|
||||
self.c.Context().Pop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) EscapeDescription() string {
|
||||
if state := self.context.GetState(); state != nil {
|
||||
if state.SelectingRange() {
|
||||
return self.c.Tr.DismissRangeSelect
|
||||
}
|
||||
|
||||
if state.SelectingHunkEnabledByUser() {
|
||||
return self.c.Tr.SelectLineByLine
|
||||
}
|
||||
}
|
||||
|
||||
return self.c.Tr.ReturnToFilesPanel
|
||||
}
|
||||
|
||||
func (self *StagingController) TogglePanel() error {
|
||||
if self.otherContext.GetState() != nil {
|
||||
self.c.Context().Push(self.otherContext, types.OnFocusOpts{})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) ToggleStaged() error {
|
||||
if self.c.UserConfig().Git.DiffContextSize == 0 {
|
||||
return fmt.Errorf(self.c.Tr.Actions.NotEnoughContextToStage,
|
||||
self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView)
|
||||
}
|
||||
|
||||
return self.applySelectionAndRefresh(self.staged)
|
||||
}
|
||||
|
||||
func (self *StagingController) DiscardSelection() error {
|
||||
if self.c.UserConfig().Git.DiffContextSize == 0 {
|
||||
return fmt.Errorf(self.c.Tr.Actions.NotEnoughContextToDiscard,
|
||||
self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView)
|
||||
}
|
||||
|
||||
return self.c.ConfirmIf(!self.staged && !self.c.UserConfig().Gui.SkipDiscardChangeWarning,
|
||||
types.ConfirmOpts{
|
||||
Title: self.c.Tr.DiscardChangeTitle,
|
||||
Prompt: self.c.Tr.DiscardChangePrompt,
|
||||
HandleConfirm: func() error { return self.applySelectionAndRefresh(true) },
|
||||
})
|
||||
}
|
||||
|
||||
func (self *StagingController) applySelectionAndRefresh(reverse bool) error {
|
||||
if err := self.applySelection(reverse); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Block input until the refresh has landed: it rebuilds the staging panel
|
||||
// and moves the selection to the next stageable change, and a quick second
|
||||
// keypress must act on that, not on the stale pre-refresh diff.
|
||||
self.c.RefreshBlockingInput(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES, types.STAGING}})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) applySelection(reverse bool) error {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
||||
state := self.context.GetState()
|
||||
path := self.FilePath()
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
firstLineIdx, lastLineIdx := state.SelectedPatchRange()
|
||||
patchToApply := patch.
|
||||
Parse(state.GetDiff()).
|
||||
Transform(patch.TransformOpts{
|
||||
Reverse: reverse,
|
||||
IncludedLineIndices: patch.ExpandRange(firstLineIdx, lastLineIdx),
|
||||
FileNameOverride: path,
|
||||
}).
|
||||
FormatPlain()
|
||||
|
||||
if patchToApply == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// apply the patch then refresh this panel
|
||||
// create a new temp file with the patch, then call git apply with that patch
|
||||
self.c.LogAction(self.c.Tr.Actions.ApplyPatch)
|
||||
err := self.c.Git().Patch.ApplyPatch(
|
||||
patchToApply,
|
||||
git_commands.ApplyPatchOpts{
|
||||
Reverse: reverse,
|
||||
Cached: !reverse || self.staged,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if state.SelectingRange() {
|
||||
firstLine, _ := state.SelectedViewRange()
|
||||
state.SelectLine(firstLine)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) EditHunkAndRefresh() error {
|
||||
if err := self.editHunk(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Block input like applySelectionAndRefresh does; the refresh rebuilds the
|
||||
// staging panel from the post-edit diff.
|
||||
self.c.RefreshBlockingInput(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES, types.STAGING}})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) editHunk() error {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
||||
state := self.context.GetState()
|
||||
path := self.FilePath()
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
hunkStartIdx, hunkEndIdx := state.CurrentHunkBounds()
|
||||
patchText := patch.
|
||||
Parse(state.GetDiff()).
|
||||
Transform(patch.TransformOpts{
|
||||
Reverse: self.staged,
|
||||
IncludedLineIndices: patch.ExpandRange(hunkStartIdx, hunkEndIdx),
|
||||
FileNameOverride: path,
|
||||
}).
|
||||
FormatPlain()
|
||||
|
||||
patchFilepath, err := self.c.Git().Patch.SaveTemporaryPatch(patchText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lineOffset := 3
|
||||
lineIdxInHunk := state.GetSelectedPatchLineIdx() - hunkStartIdx
|
||||
if err := self.c.Helpers().Files.EditFileAtLineAndWait(patchFilepath, lineIdxInHunk+lineOffset); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
editedPatchText, err := self.c.Git().File.Cat(patchFilepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.ApplyPatch)
|
||||
|
||||
lineCount := strings.Count(editedPatchText, "\n") + 1
|
||||
newPatchText := patch.
|
||||
Parse(editedPatchText).
|
||||
Transform(patch.TransformOpts{
|
||||
IncludedLineIndices: patch.ExpandRange(0, lineCount),
|
||||
FileNameOverride: path,
|
||||
}).
|
||||
FormatPlain()
|
||||
|
||||
if err := self.c.Git().Patch.ApplyPatch(
|
||||
newPatchText,
|
||||
git_commands.ApplyPatchOpts{
|
||||
Reverse: self.staged,
|
||||
Cached: true,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *StagingController) FilePath() string {
|
||||
return self.c.Contexts().Files.GetSelectedPath()
|
||||
}
|
||||
@@ -16,8 +16,6 @@ const (
|
||||
WORKTREES
|
||||
STATUS
|
||||
SUBMODULES
|
||||
STAGING
|
||||
PATCH_BUILDING
|
||||
MERGE_CONFLICTS
|
||||
COMMIT_FILES
|
||||
// not actually views. Will refactor this later
|
||||
|
||||
Reference in New Issue
Block a user