From dcb0a0ffcc88f602d7d3e29c1aad15f37b6ec335 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 3 Aug 2025 12:28:23 +0200 Subject: [PATCH 1/7] Clean up build tags - Remove old-style build tags (the +build syntax has become obsolete with 1.17) - Remove redundant build tags from '*_windows.go' files --- pkg/commands/oscommands/cmd_obj_runner_default.go | 1 - .../{cmd_obj_runner_win.go => cmd_obj_runner_windows.go} | 3 --- pkg/commands/oscommands/os_default_platform.go | 1 - pkg/commands/oscommands/os_default_test.go | 1 - pkg/commands/oscommands/os_windows_test.go | 3 --- pkg/config/config_default_platform.go | 1 - pkg/gui/pty.go | 1 - pkg/gui/pty_windows.go | 3 --- pkg/integration/clients/go_test.go | 1 - pkg/logs/tail/logs_default.go | 1 - pkg/logs/tail/logs_windows.go | 3 --- 11 files changed, 19 deletions(-) rename pkg/commands/oscommands/{cmd_obj_runner_win.go => cmd_obj_runner_windows.go} (86%) diff --git a/pkg/commands/oscommands/cmd_obj_runner_default.go b/pkg/commands/oscommands/cmd_obj_runner_default.go index 891b4c4eef8..72cbc26c66c 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_default.go +++ b/pkg/commands/oscommands/cmd_obj_runner_default.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package oscommands diff --git a/pkg/commands/oscommands/cmd_obj_runner_win.go b/pkg/commands/oscommands/cmd_obj_runner_windows.go similarity index 86% rename from pkg/commands/oscommands/cmd_obj_runner_win.go rename to pkg/commands/oscommands/cmd_obj_runner_windows.go index 2189da2e6cc..f92e36c69e4 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_win.go +++ b/pkg/commands/oscommands/cmd_obj_runner_windows.go @@ -1,6 +1,3 @@ -//go:build windows -// +build windows - package oscommands import ( diff --git a/pkg/commands/oscommands/os_default_platform.go b/pkg/commands/oscommands/os_default_platform.go index 11e1dc9aac4..c21a5b0a239 100644 --- a/pkg/commands/oscommands/os_default_platform.go +++ b/pkg/commands/oscommands/os_default_platform.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package oscommands diff --git a/pkg/commands/oscommands/os_default_test.go b/pkg/commands/oscommands/os_default_test.go index 94da4b07814..ff8c59cd2ac 100644 --- a/pkg/commands/oscommands/os_default_test.go +++ b/pkg/commands/oscommands/os_default_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package oscommands diff --git a/pkg/commands/oscommands/os_windows_test.go b/pkg/commands/oscommands/os_windows_test.go index fcf6a95772b..60ba495bf4e 100644 --- a/pkg/commands/oscommands/os_windows_test.go +++ b/pkg/commands/oscommands/os_windows_test.go @@ -1,6 +1,3 @@ -//go:build windows -// +build windows - package oscommands import ( diff --git a/pkg/config/config_default_platform.go b/pkg/config/config_default_platform.go index d052014541f..9375e18512d 100644 --- a/pkg/config/config_default_platform.go +++ b/pkg/config/config_default_platform.go @@ -1,5 +1,4 @@ //go:build !windows && !linux -// +build !windows,!linux package config diff --git a/pkg/gui/pty.go b/pkg/gui/pty.go index 84c9e6da8a2..4253438bb8e 100644 --- a/pkg/gui/pty.go +++ b/pkg/gui/pty.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package gui diff --git a/pkg/gui/pty_windows.go b/pkg/gui/pty_windows.go index dfb2fb3079b..3324fa87d68 100644 --- a/pkg/gui/pty_windows.go +++ b/pkg/gui/pty_windows.go @@ -1,6 +1,3 @@ -//go:build windows -// +build windows - package gui import ( diff --git a/pkg/integration/clients/go_test.go b/pkg/integration/clients/go_test.go index 26f092a81cd..8984c759a5e 100644 --- a/pkg/integration/clients/go_test.go +++ b/pkg/integration/clients/go_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package clients diff --git a/pkg/logs/tail/logs_default.go b/pkg/logs/tail/logs_default.go index 1b866500f9b..3daa6c4b14e 100644 --- a/pkg/logs/tail/logs_default.go +++ b/pkg/logs/tail/logs_default.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package tail diff --git a/pkg/logs/tail/logs_windows.go b/pkg/logs/tail/logs_windows.go index 88bf8581edc..3c45d70af53 100644 --- a/pkg/logs/tail/logs_windows.go +++ b/pkg/logs/tail/logs_windows.go @@ -1,6 +1,3 @@ -//go:build windows -// +build windows - package tail import ( From 03bca5a14c5e09275fa5e323dd14fd07c07c8ddd Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 3 Aug 2025 08:24:32 +0200 Subject: [PATCH 2/7] Cleanup: remove stale comment This should have been removed in 8c574f888c0, where I renamed it back to 'gui' to fix a linter warning. --- pkg/gui/keybindings.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 98850cf2d81..c966b148a51 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -75,7 +75,6 @@ func (gui *Gui) keybindingOpts() types.KeybindingsOpts { } } -// renaming receiver to 'self' to aid refactoring. Will probably end up moving all Gui handlers to this pattern eventually. func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) { opts := gui.c.KeybindingsOpts() From 26d8cb34e13aa3323e5583928e31589865e23bbb Mon Sep 17 00:00:00 2001 From: cowboy8625 Date: Sat, 19 Jul 2025 14:30:01 -0500 Subject: [PATCH 3/7] Rebind redo from to Z This frees up ctrl-z for suspend. Hopefully, redo is not such a frequently used operation that the change annoys people. Co-authored-by: Stefan Haller --- docs/Config.md | 2 +- docs/keybindings/Keybindings_en.md | 2 +- docs/keybindings/Keybindings_ja.md | 2 +- docs/keybindings/Keybindings_ko.md | 2 +- docs/keybindings/Keybindings_nl.md | 2 +- docs/keybindings/Keybindings_pl.md | 2 +- docs/keybindings/Keybindings_pt.md | 2 +- docs/keybindings/Keybindings_ru.md | 2 +- docs/keybindings/Keybindings_zh-CN.md | 2 +- docs/keybindings/Keybindings_zh-TW.md | 2 +- pkg/config/app_config_test.go | 2 +- pkg/config/user_config.go | 2 +- schema/config.json | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/Config.md b/docs/Config.md index 9b48a32d832..b7c36798494 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -583,7 +583,7 @@ keybinding: nextScreenMode: + prevScreenMode: _ undo: z - redo: + redo: Z filteringMenu: diffingMenu: W diffingMenu-alt: diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index ab1a8684268..69d2fb52ba7 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -32,7 +32,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Cancel | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Undo | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | -| `` `` | Redo | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | +| `` Z `` | Redo | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | ## List panel navigation diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md index ec536b302f3..56eabb62c98 100644 --- a/docs/keybindings/Keybindings_ja.md +++ b/docs/keybindings/Keybindings_ja.md @@ -32,7 +32,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味 | `` `` | キャンセル | | | `` `` | 空白表示の切り替え | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 元に戻す | 最後のgitコマンドを元に戻すために実行するgitコマンドを決定するためにreflogが使用されます。これにはワーキングツリーへの変更は含まれません。コミットのみが考慮されます。 | -| `` `` | やり直す | 最後のgitコマンドをやり直すために実行するgitコマンドを決定するためにreflogが使用されます。これにはワーキングツリーへの変更は含まれません。コミットのみが考慮されます。 | +| `` Z `` | やり直す | 最後のgitコマンドをやり直すために実行するgitコマンドを決定するためにreflogが使用されます。これにはワーキングツリーへの変更は含まれません。コミットのみが考慮されます。 | ## リストパネルのナビゲーション diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md index de2c6c71964..db2e4329bc4 100644 --- a/docs/keybindings/Keybindings_ko.md +++ b/docs/keybindings/Keybindings_ko.md @@ -32,7 +32,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | 취소 | | | `` `` | 공백문자를 Diff 뷰에서 표시 여부 전환 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 되돌리기 (reflog) (실험적) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | -| `` `` | 다시 실행 (reflog) (실험적) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | +| `` Z `` | 다시 실행 (reflog) (실험적) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | ## List panel navigation diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index cda93faee6d..4c752969a89 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -32,7 +32,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Annuleren | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Ongedaan maken (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | -| `` `` | Redo (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | +| `` Z `` | Redo (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | ## Lijstpaneel navigatie diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index 311194a0f76..cd3902284f2 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -32,7 +32,7 @@ _Legenda: `` oznacza ctrl+b, `` oznacza alt+b, `B` oznacza shift+b_ | `` `` | Anuluj | | | `` `` | Przełącz białe znaki | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Cofnij | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby cofnąć ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. | -| `` `` | Ponów | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby ponowić ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. | +| `` Z `` | Ponów | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby ponowić ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. | ## Nawigacja panelu listy diff --git a/docs/keybindings/Keybindings_pt.md b/docs/keybindings/Keybindings_pt.md index 096be874dc1..a55abdd99a0 100644 --- a/docs/keybindings/Keybindings_pt.md +++ b/docs/keybindings/Keybindings_pt.md @@ -32,7 +32,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Cancelar | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Desfazer | O reflog será usado para determinar qual comando git para executar para desfazer o último comando git. Isto não inclui mudanças na árvore de trabalho; apenas compromissos são tidos em consideração. | -| `` `` | Refazer | O reflog será usado para determinar qual comando git para executar para refazer o último comando git. Isto não inclui mudanças na árvore de trabalho; apenas compromissos são tidos em consideração. | +| `` Z `` | Refazer | O reflog será usado para determinar qual comando git para executar para refazer o último comando git. Isto não inclui mudanças na árvore de trabalho; apenas compromissos são tidos em consideração. | ## List panel navigation diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md index 48af4b35f76..be965c27588 100644 --- a/docs/keybindings/Keybindings_ru.md +++ b/docs/keybindings/Keybindings_ru.md @@ -32,7 +32,7 @@ _Связки клавиш_ | `` `` | Отменить | | | `` `` | Переключить отображение изменении пробелов в просмотрщике сравнении | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Отменить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git запустить, чтобы отменить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. | -| `` `` | Повторить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git нужно запустить, чтобы повторить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. | +| `` Z `` | Повторить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git нужно запустить, чтобы повторить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. | ## Навигация по панели списка diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md index c85be039b2f..06ce4cb67a7 100644 --- a/docs/keybindings/Keybindings_zh-CN.md +++ b/docs/keybindings/Keybindings_zh-CN.md @@ -32,7 +32,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` `` | 取消 | | | `` `` | 切换是否在差异视图中显示空白字符差异 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 撤销 | Reflog将用于确定运行哪个git命令来撤消最后一个git命令。这并不包括对工作树的更改,只考虑提交。 | -| `` `` | 重做 | Reflog将用于确定运行哪个git命令来重做上一个git命令。这并不包括对工作树的更改,只考虑提交。 | +| `` Z `` | 重做 | Reflog将用于确定运行哪个git命令来重做上一个git命令。这并不包括对工作树的更改,只考虑提交。 | ## 列表面板导航 diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md index 5f980089ba6..e72321b9e33 100644 --- a/docs/keybindings/Keybindings_zh-TW.md +++ b/docs/keybindings/Keybindings_zh-TW.md @@ -32,7 +32,7 @@ _說明:`` 表示 Ctrl+B、`` 表示 Alt+B,`B`表示 Shift+B | `` `` | 取消 | | | `` `` | 切換是否在差異檢視中顯示空格變更 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 復原 | 將使用 reflog 確任 git 指令以復原。這不包括工作區更改;只考慮提交。 | -| `` `` | 取消復原 | 將使用 reflog 確任 git 指令以重作。這不包括工作區更改;只考慮提交。 | +| `` Z `` | 取消復原 | 將使用 reflog 確任 git 指令以重作。這不包括工作區更改;只考慮提交。 | ## 移動 diff --git a/pkg/config/app_config_test.go b/pkg/config/app_config_test.go index c8c7d1d11d7..faba2e4e848 100644 --- a/pkg/config/app_config_test.go +++ b/pkg/config/app_config_test.go @@ -865,7 +865,7 @@ keybinding: nextScreenMode: + prevScreenMode: _ undo: z - redo: + redo: Z filteringMenu: diffingMenu: W diffingMenu-alt: diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index fc702d6da44..e43ec749ccd 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -912,7 +912,7 @@ func GetDefaultConfig() *UserConfig { NextScreenMode: "+", PrevScreenMode: "_", Undo: "z", - Redo: "", + Redo: "Z", FilteringMenu: "", DiffingMenu: "W", DiffingMenuAlt: "", diff --git a/schema/config.json b/schema/config.json index d2d00e4b887..78d8148b781 100644 --- a/schema/config.json +++ b/schema/config.json @@ -1458,7 +1458,7 @@ }, "redo": { "type": "string", - "default": "\u003cc-z\u003e" + "default": "Z" }, "filteringMenu": { "type": "string", From dbd8687f483c95e8c419872d72eb744d7ba5b0c0 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 3 Aug 2025 08:11:52 +0200 Subject: [PATCH 4/7] Extract methods suspend/resume on Gui struct These suspend/resume the gocui layer and pause/unpause background refreshes. --- pkg/gui/gui.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index c02221c04dc..bfa0a392ca1 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -899,21 +899,36 @@ func (gui *Gui) runSubprocessWithSuspenseAndRefresh(subprocess *oscommands.CmdOb return nil } +func (gui *Gui) suspend() error { + if err := gui.g.Suspend(); err != nil { + return err + } + + gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(true) + return nil +} + +func (gui *Gui) resume() error { + if err := gui.g.Resume(); err != nil { + return err + } + + gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(false) + return nil +} + // returns whether command exited without error or not func (gui *Gui) runSubprocessWithSuspense(subprocess *oscommands.CmdObj) (bool, error) { gui.Mutexes.SubprocessMutex.Lock() defer gui.Mutexes.SubprocessMutex.Unlock() - if err := gui.g.Suspend(); err != nil { + if err := gui.suspend(); err != nil { return false, err } - gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(true) - defer gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(false) - cmdErr := gui.runSubprocess(subprocess) - if err := gui.g.Resume(); err != nil { + if err := gui.resume(); err != nil { return false, err } From 4ede0b8cd0ebdf997e06299ddfdeb8528ccb48c4 Mon Sep 17 00:00:00 2001 From: cowboy8625 Date: Sat, 19 Jul 2025 07:17:30 -0500 Subject: [PATCH 5/7] Implement suspending the app using ctrl-z Co-authored-by: Stefan Haller --- go.mod | 2 +- pkg/config/user_config.go | 2 + pkg/gui/controllers.go | 1 + pkg/gui/controllers/global_controller.go | 14 +++++ pkg/gui/controllers/helpers/helpers.go | 1 + .../controllers/helpers/signal_handling.go | 59 +++++++++++++++++++ .../helpers/signal_handling_windows.go | 16 +++++ .../helpers/suspend_resume_helper.go | 31 ++++++++++ pkg/gui/gui.go | 2 + pkg/gui/gui_common.go | 8 +++ pkg/gui/types/common.go | 3 + pkg/i18n/english.go | 4 ++ 12 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 pkg/gui/controllers/helpers/signal_handling.go create mode 100644 pkg/gui/controllers/helpers/signal_handling_windows.go create mode 100644 pkg/gui/controllers/helpers/suspend_resume_helper.go diff --git a/go.mod b/go.mod index 801681c92a6..01ac2c36999 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.16.0 + golang.org/x/sys v0.34.0 gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -77,7 +78,6 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.34.0 // indirect golang.org/x/term v0.33.0 // indirect golang.org/x/text v0.27.0 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index e43ec749ccd..0fa706bb242 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -390,6 +390,7 @@ type KeybindingConfig struct { type KeybindingUniversalConfig struct { Quit string `yaml:"quit"` QuitAlt1 string `yaml:"quit-alt1"` + SuspendApp string `yaml:"suspendApp"` Return string `yaml:"return"` QuitWithoutChangingDirectory string `yaml:"quitWithoutChangingDirectory"` TogglePanel string `yaml:"togglePanel"` @@ -854,6 +855,7 @@ func GetDefaultConfig() *UserConfig { Universal: KeybindingUniversalConfig{ Quit: "q", QuitAlt1: "", + SuspendApp: "", Return: "", QuitWithoutChangingDirectory: "Q", TogglePanel: "", diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index f83a3f8e90d..20b52b2cb16 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -109,6 +109,7 @@ func (gui *Gui) resetHelpersAndControllers() { AmendHelper: helpers.NewAmendHelper(helperCommon, gpgHelper), FixupHelper: helpers.NewFixupHelper(helperCommon), Commits: commitsHelper, + SuspendResume: helpers.NewSuspendResumeHelper(helperCommon), Snake: helpers.NewSnakeHelper(helperCommon), Diff: diffHelper, Repos: reposHelper, diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index 9dfbeb4546f..cd11d5de558 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -114,6 +114,20 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type Modifier: gocui.ModNone, Handler: self.quitWithoutChangingDirectory, }, + { + Key: opts.GetKey(opts.Config.Universal.SuspendApp), + Modifier: gocui.ModNone, + Handler: self.c.Helpers().SuspendResume.SuspendApp, + Description: self.c.Tr.SuspendApp, + GetDisabledReason: func() *types.DisabledReason { + if !self.c.Helpers().SuspendResume.CanSuspendApp() { + return &types.DisabledReason{ + Text: self.c.Tr.CannotSuspendApp, + } + } + return nil + }, + }, { Key: opts.GetKey(opts.Config.Universal.Return), Modifier: gocui.ModNone, diff --git a/pkg/gui/controllers/helpers/helpers.go b/pkg/gui/controllers/helpers/helpers.go index 1f1050dc974..4c9c79f3d81 100644 --- a/pkg/gui/controllers/helpers/helpers.go +++ b/pkg/gui/controllers/helpers/helpers.go @@ -35,6 +35,7 @@ type Helpers struct { AmendHelper *AmendHelper FixupHelper *FixupHelper Commits *CommitsHelper + SuspendResume *SuspendResumeHelper Snake *SnakeHelper // lives in context package because our contexts need it to render to main Diff *DiffHelper diff --git a/pkg/gui/controllers/helpers/signal_handling.go b/pkg/gui/controllers/helpers/signal_handling.go new file mode 100644 index 00000000000..40d04f6895d --- /dev/null +++ b/pkg/gui/controllers/helpers/signal_handling.go @@ -0,0 +1,59 @@ +//go:build !windows + +package helpers + +import ( + "os" + "os/signal" + "syscall" + + "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" +) + +func canSuspendApp() bool { + return true +} + +func sendStopSignal() error { + return syscall.Kill(0, syscall.SIGSTOP) +} + +// setForegroundPgrp sets the current process group as the foreground process group +// for the terminal, allowing the program to read input after resuming from suspension. +func setForegroundPgrp() error { + fd, err := unix.Open("/dev/tty", unix.O_RDWR, 0) + if err != nil { + return err + } + defer unix.Close(fd) + + pgid := syscall.Getpgrp() + + return unix.IoctlSetPointerInt(fd, unix.TIOCSPGRP, pgid) +} + +func handleResumeSignal(log *logrus.Entry, onResume func() error) { + if err := setForegroundPgrp(); err != nil { + log.Warning(err) + return + } + + if err := onResume(); err != nil { + log.Warning(err) + } +} + +func installResumeSignalHandler(log *logrus.Entry, onResume func() error) { + go func() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGCONT) + + for sig := range sigs { + switch sig { + case syscall.SIGCONT: + handleResumeSignal(log, onResume) + } + } + }() +} diff --git a/pkg/gui/controllers/helpers/signal_handling_windows.go b/pkg/gui/controllers/helpers/signal_handling_windows.go new file mode 100644 index 00000000000..8517e775d61 --- /dev/null +++ b/pkg/gui/controllers/helpers/signal_handling_windows.go @@ -0,0 +1,16 @@ +package helpers + +import ( + "github.com/sirupsen/logrus" +) + +func canSuspendApp() bool { + return false +} + +func sendStopSignal() error { + return nil +} + +func installResumeSignalHandler(log *logrus.Entry, onResume func() error) { +} diff --git a/pkg/gui/controllers/helpers/suspend_resume_helper.go b/pkg/gui/controllers/helpers/suspend_resume_helper.go new file mode 100644 index 00000000000..cc63af495f5 --- /dev/null +++ b/pkg/gui/controllers/helpers/suspend_resume_helper.go @@ -0,0 +1,31 @@ +package helpers + +type SuspendResumeHelper struct { + c *HelperCommon +} + +func NewSuspendResumeHelper(c *HelperCommon) *SuspendResumeHelper { + return &SuspendResumeHelper{ + c: c, + } +} + +func (s *SuspendResumeHelper) CanSuspendApp() bool { + return canSuspendApp() +} + +func (s *SuspendResumeHelper) SuspendApp() error { + if !canSuspendApp() { + return nil + } + + if err := s.c.Suspend(); err != nil { + return err + } + + return sendStopSignal() +} + +func (s *SuspendResumeHelper) InstallResumeSignalHandler() { + installResumeSignalHandler(s.c.Log, s.c.Resume) +} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index bfa0a392ca1..1bd5788f20b 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -848,6 +848,8 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error { gui.BackgroundRoutineMgr.startBackgroundRoutines() + gui.Helpers().SuspendResume.InstallResumeSignalHandler() + gui.c.Log.Info("starting main loop") // setting here so we can use it in layout.go diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index c77c81e793a..d946659d166 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -42,6 +42,14 @@ func (self *guiCommon) RunSubprocess(cmdObj *oscommands.CmdObj) (bool, error) { return self.gui.runSubprocessWithSuspense(cmdObj) } +func (self *guiCommon) Suspend() error { + return self.gui.suspend() +} + +func (self *guiCommon) Resume() error { + return self.gui.resume() +} + func (self *guiCommon) Context() types.IContextMgr { return self.gui.State.ContextMgr } diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 7d8528ee86d..789eb52e1a4 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -56,6 +56,9 @@ type IGuiCommon interface { RunSubprocess(cmdObj *oscommands.CmdObj) (bool, error) RunSubprocessAndRefresh(*oscommands.CmdObj) error + Suspend() error + Resume() error + Context() IContextMgr ContextForKey(key ContextKey) Context diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 09d29887359..9855aa88df6 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -382,6 +382,8 @@ type TranslationSet struct { ScrollUp string ScrollUpMainWindow string ScrollDownMainWindow string + SuspendApp string + CannotSuspendApp string AmendCommitTitle string AmendCommitPrompt string AmendCommitWithConflictsMenuPrompt string @@ -1448,6 +1450,8 @@ func EnglishTranslationSet() *TranslationSet { ScrollUp: "Scroll up", ScrollUpMainWindow: "Scroll up main window", ScrollDownMainWindow: "Scroll down main window", + SuspendApp: "Suspend the application", + CannotSuspendApp: "Suspending the application is not supported on Windows", AmendCommitTitle: "Amend commit", AmendCommitPrompt: "Are you sure you want to amend this commit with your staged files?", AmendCommitWithConflictsMenuPrompt: "WARNING: you are about to amend the last finished commit with your resolved conflicts. This is very unlikely to be what you want at this point. More likely, you simply want to continue the rebase instead.\n\nDo you still want to amend the previous commit?", From cdd40eb86c88cb5974fd8a8e216efd4f54d507f8 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 4 Aug 2025 13:51:50 +0200 Subject: [PATCH 6/7] Update cheatsheets, config docs, and schema --- docs/Config.md | 1 + docs/keybindings/Keybindings_en.md | 1 + docs/keybindings/Keybindings_ja.md | 1 + docs/keybindings/Keybindings_ko.md | 1 + docs/keybindings/Keybindings_nl.md | 1 + docs/keybindings/Keybindings_pl.md | 1 + docs/keybindings/Keybindings_pt.md | 1 + docs/keybindings/Keybindings_ru.md | 1 + docs/keybindings/Keybindings_zh-CN.md | 1 + docs/keybindings/Keybindings_zh-TW.md | 1 + schema/config.json | 4 ++++ 11 files changed, 14 insertions(+) diff --git a/docs/Config.md b/docs/Config.md index b7c36798494..079ff5ce9af 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -517,6 +517,7 @@ keybinding: universal: quit: q quit-alt1: + suspendApp: return: quitWithoutChangingDirectory: Q togglePanel: diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index 69d2fb52ba7..3cd39d3b78e 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -29,6 +29,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | Quit | | +| `` `` | Suspend the application | | | `` `` | Cancel | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Undo | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md index 56eabb62c98..eb9697d1d64 100644 --- a/docs/keybindings/Keybindings_ja.md +++ b/docs/keybindings/Keybindings_ja.md @@ -29,6 +29,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味 | `` W `` | 差分オプションを表示 | 2つのrefの差分に関連するオプションを表示します(例:選択したrefとの差分表示、差分を取るrefの入力、差分方向の反転など)。 | | `` `` | 差分オプションを表示 | 2つのrefの差分に関連するオプションを表示します(例:選択したrefとの差分表示、差分を取るrefの入力、差分方向の反転など)。 | | `` q `` | 終了 | | +| `` `` | Suspend the application | | | `` `` | キャンセル | | | `` `` | 空白表示の切り替え | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 元に戻す | 最後のgitコマンドを元に戻すために実行するgitコマンドを決定するためにreflogが使用されます。これにはワーキングツリーへの変更は含まれません。コミットのみが考慮されます。 | diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md index db2e4329bc4..23112a32e81 100644 --- a/docs/keybindings/Keybindings_ko.md +++ b/docs/keybindings/Keybindings_ko.md @@ -29,6 +29,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` W `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | 종료 | | +| `` `` | Suspend the application | | | `` `` | 취소 | | | `` `` | 공백문자를 Diff 뷰에서 표시 여부 전환 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 되돌리기 (reflog) (실험적) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index 4c752969a89..2b6d7a7e719 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -29,6 +29,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` W `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | Quit | | +| `` `` | Suspend the application | | | `` `` | Annuleren | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Ongedaan maken (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. | diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index cd3902284f2..0b4763642a6 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -29,6 +29,7 @@ _Legenda: `` oznacza ctrl+b, `` oznacza alt+b, `B` oznacza shift+b_ | `` W `` | Pokaż opcje różnicowania | Pokaż opcje dotyczące różnicowania dwóch refów, np. różnicowanie względem wybranego refa, wprowadzanie refa do różnicowania i odwracanie kierunku różnic. | | `` `` | Pokaż opcje różnicowania | Pokaż opcje dotyczące różnicowania dwóch refów, np. różnicowanie względem wybranego refa, wprowadzanie refa do różnicowania i odwracanie kierunku różnic. | | `` q `` | Wyjdź | | +| `` `` | Suspend the application | | | `` `` | Anuluj | | | `` `` | Przełącz białe znaki | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Cofnij | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby cofnąć ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. | diff --git a/docs/keybindings/Keybindings_pt.md b/docs/keybindings/Keybindings_pt.md index a55abdd99a0..ddfa027dbd8 100644 --- a/docs/keybindings/Keybindings_pt.md +++ b/docs/keybindings/Keybindings_pt.md @@ -29,6 +29,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | Sair | | +| `` `` | Suspend the application | | | `` `` | Cancelar | | | `` `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Desfazer | O reflog será usado para determinar qual comando git para executar para desfazer o último comando git. Isto não inclui mudanças na árvore de trabalho; apenas compromissos são tidos em consideração. | diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md index be965c27588..6ec5d7760ad 100644 --- a/docs/keybindings/Keybindings_ru.md +++ b/docs/keybindings/Keybindings_ru.md @@ -29,6 +29,7 @@ _Связки клавиш_ | `` W `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | Выйти | | +| `` `` | Suspend the application | | | `` `` | Отменить | | | `` `` | Переключить отображение изменении пробелов в просмотрщике сравнении | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | Отменить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git запустить, чтобы отменить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. | diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md index 06ce4cb67a7..3ab1f008ee5 100644 --- a/docs/keybindings/Keybindings_zh-CN.md +++ b/docs/keybindings/Keybindings_zh-CN.md @@ -29,6 +29,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` W `` | 打开 diff 菜单 | 查看与比较两个引用相关的选项,例如与选定的 ref 进行比较,输入要比较的 ref,然后反转比较方向。 | | `` `` | 打开 diff 菜单 | 查看与比较两个引用相关的选项,例如与选定的 ref 进行比较,输入要比较的 ref,然后反转比较方向。 | | `` q `` | 退出 | | +| `` `` | Suspend the application | | | `` `` | 取消 | | | `` `` | 切换是否在差异视图中显示空白字符差异 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 撤销 | Reflog将用于确定运行哪个git命令来撤消最后一个git命令。这并不包括对工作树的更改,只考虑提交。 | diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md index e72321b9e33..6d4735ca1e1 100644 --- a/docs/keybindings/Keybindings_zh-TW.md +++ b/docs/keybindings/Keybindings_zh-TW.md @@ -29,6 +29,7 @@ _說明:`` 表示 Ctrl+B、`` 表示 Alt+B,`B`表示 Shift+B | `` W `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. | | `` q `` | 結束 | | +| `` `` | Suspend the application | | | `` `` | 取消 | | | `` `` | 切換是否在差異檢視中顯示空格變更 | Toggle whether or not whitespace changes are shown in the diff view.

The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. | | `` z `` | 復原 | 將使用 reflog 確任 git 指令以復原。這不包括工作區更改;只考慮提交。 | diff --git a/schema/config.json b/schema/config.json index 78d8148b781..db9c796386a 100644 --- a/schema/config.json +++ b/schema/config.json @@ -1217,6 +1217,10 @@ "type": "string", "default": "\u003cc-c\u003e" }, + "suspendApp": { + "type": "string", + "default": "\u003cc-z\u003e" + }, "return": { "type": "string", "default": "\u003cesc\u003e" From 0900a3718f58d80502bdbb2c88363cc4caa6a79e Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 3 Aug 2025 12:38:57 +0200 Subject: [PATCH 7/7] Add a breaking changes notice for the changed keybinding --- pkg/i18n/english.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 9855aa88df6..54980caa102 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -2144,6 +2144,13 @@ git: gui: useHunkSelectionMode: false +`, + "0.55.0": `- The 'redo' command, which used to be bound to ctrl-z, is now bound to shift-Z instead. This is because ctrl-z is now used for suspending the application; it is a commonly known keybinding for that in the Linux world. If you want to revert this change, you can do so by adding the following to your config: + +keybinding: + universal: + suspendApp: + redo: `, }, }