Fold legacy quit-alt1 into the multi-key quit binding

Now that quit accepts multiple keys, the historical quit-alt1 field is
redundant: existing configs that set it should keep working without the user
having to migrate, but the lazygit code shouldn't have to register the alt
binding separately.

Add a merge step that runs after the user config is loaded (and from
NewDummyAppConfig, which the cheatsheet generator and integration tests go
through) folding the alt value into the main key list. Mark QuitAlt1 deprecated
so it disappears from the generated Config.md example, while staying in the JSON
schema with a description so editors can still steer users toward the new form.
Note that instead of marking the alt config as deprecated, we could have added a
migrator that changes users' config files and gets rid of the alt config for
good. I decided not to do that, because this would render the config file
invalid for older versions of lazygit, which would then refuse to start; and
that's annoying when bisecting bugs. We'll keep the deprecated configs in the
code for a year or so, and then add the migrator.

The next commit will fold the remaining ~15 -alt-style fields the same way; the
helper is shaped to keep that mechanical.
This commit is contained in:
Stefan Haller 2026-05-04 09:03:15 +02:00
parent fbcf562e29
commit 022d24cb79
18 changed files with 89 additions and 18 deletions

View file

@ -597,8 +597,7 @@ promptToReturnFromSubprocess: true
# for the syntax.
keybinding:
universal:
quit: q
quit-alt1: <ctrl+c>
quit: [q, <ctrl+c>]
suspendApp: <ctrl+z>
return: <esc>
quitWithoutChangingDirectory: Q

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` 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. |
| `` <ctrl+e> `` | 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 | |
| `` q, <ctrl+c> `` | Quit | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.<br><br>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. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | フィルターオプションを表示 | コミットログのフィルタリングオプションを表示し、フィルタに一致するコミットのみを表示します。 |
| `` W `` | 差分オプションを表示 | つのrefの差分に関連するオプションを表示します選択したrefとの差分表示、差分を取るrefの入力、差分方向の反転など。 |
| `` <ctrl+e> `` | 差分オプションを表示 | つのrefの差分に関連するオプションを表示します選択したrefとの差分表示、差分を取るrefの入力、差分方向の反転など。 |
| `` q `` | 終了 | |
| `` q, <ctrl+c> `` | 終了 | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | 空白表示の切り替え | Toggle whether or not whitespace changes are shown in the diff view.<br><br>The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. |
| `` z `` | 元に戻す | 最後のgitコマンドを元に戻すために実行するgitコマンドを決定するためにreflogが使用されます。これにはワーキングツリーへの変更は含まれません。コミットのみが考慮されます。 |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | View filter-by-path options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` 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. |
| `` <ctrl+e> `` | 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 `` | 종료 | |
| `` q, <ctrl+c> `` | 종료 | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | 공백문자를 Diff 뷰에서 표시 여부 전환 | Toggle whether or not whitespace changes are shown in the diff view.<br><br>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. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | Bekijk scoping opties | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` 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. |
| `` <ctrl+e> `` | 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 | |
| `` q, <ctrl+c> `` | Quit | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.<br><br>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. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | Pokaż opcje filtrowania | Pokaż opcje filtrowania dziennika commitów, tak aby pokazywane były tylko commity pasujące do filtra. |
| `` 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. |
| `` <ctrl+e> `` | 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ź | |
| `` q, <ctrl+c> `` | Wyjdź | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | Przełącz białe znaki | Toggle whether or not whitespace changes are shown in the diff view.<br><br>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. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | Ver opções de filtro | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` 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. |
| `` <ctrl+e> `` | 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 | |
| `` q, <ctrl+c> `` | Sair | |
| `` <ctrl+z> `` | Suspender a aplicação | |
| `` <ctrl+w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view.<br><br>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. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <ctrl+e> `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Выйти | |
| `` q, <ctrl+c> `` | Выйти | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | Переключить отображение изменении пробелов в просмотрщике сравнении | Toggle whether or not whitespace changes are shown in the diff view.<br><br>The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. |
| `` z `` | Отменить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git запустить, чтобы отменить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | 查看按路径过滤选项 | 查看用于过滤提交日志的选项,以便仅显示与过滤器匹配的提交。 |
| `` W `` | 打开 diff 菜单 | 查看与比较两个引用相关的选项,例如与选定的 ref 进行比较,输入要比较的 ref然后反转比较方向。 |
| `` <ctrl+e> `` | 打开 diff 菜单 | 查看与比较两个引用相关的选项,例如与选定的 ref 进行比较,输入要比较的 ref然后反转比较方向。 |
| `` q `` | 退出 | |
| `` q, <ctrl+c> `` | 退出 | |
| `` <ctrl+z> `` | 挂起应用程序 | |
| `` <ctrl+w> `` | 切换是否在差异视图中显示空白字符差异 | 切换是否在差异视图中显示空白字符更改。<br><br>默认值可在配置文件中通过键 'git.ignoreWhitespaceInDiffView' 更改。 |
| `` z `` | 撤销 | Reflog将用于确定运行哪个git命令来撤消最后一个git命令。这并不包括对工作树的更改只考虑提交。 |

View file

@ -28,7 +28,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <ctrl+s> `` | 檢視篩選路徑選項 | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <ctrl+e> `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 結束 | |
| `` q, <ctrl+c> `` | 結束 | |
| `` <ctrl+z> `` | Suspend the application | |
| `` <ctrl+w> `` | 切換是否在差異檢視中顯示空格變更 | Toggle whether or not whitespace changes are shown in the diff view.<br><br>The default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'. |
| `` z `` | 復原 | 將使用 reflog 確任 git 指令以復原。這不包括工作區更改;只考慮提交。 |

View file

@ -203,6 +203,7 @@ func loadUserConfig(configFiles []*ConfigFile, base *UserConfig, isGuiInitialize
}
}
base.Keybinding.MergeLegacyAltKeybindings()
return base, nil
}

View file

@ -6,11 +6,13 @@ import (
// NewDummyAppConfig creates a new dummy AppConfig for testing
func NewDummyAppConfig() *AppConfig {
userConfig := GetDefaultConfig()
userConfig.Keybinding.MergeLegacyAltKeybindings()
appConfig := &AppConfig{
name: "lazygit",
version: "unversioned",
debug: false,
userConfig: GetDefaultConfig(),
userConfig: userConfig,
appState: &AppState{},
}
_ = yaml.Unmarshal([]byte{}, appConfig.appState)

View file

@ -84,3 +84,9 @@ func (Keybinding) JSONSchema() *jsonschema.Schema {
},
}
}
// mergeLegacyAlt folds a deprecated `*Alt*` field into the corresponding
// multi-key main field.
func mergeLegacyAlt(main *Keybinding, alt Keybinding) {
*main = lo.Union(*main, alt)
}

View file

@ -135,6 +135,59 @@ func TestKeybindingMarshalJSON(t *testing.T) {
}
}
func TestMergeLegacyAltKeybindings(t *testing.T) {
scenarios := []struct {
name string
quit Keybinding
quitAlt1 Keybinding
expected Keybinding
}{
{
name: "alt is folded into main",
quit: Keybinding{"q"},
quitAlt1: Keybinding{"<ctrl+c>"},
expected: Keybinding{"q", "<ctrl+c>"},
},
{
name: "alt is not appended if already present",
quit: Keybinding{"q", "<ctrl+c>"},
quitAlt1: Keybinding{"<ctrl+c>"},
expected: Keybinding{"q", "<ctrl+c>"},
},
{
name: "empty alt is ignored",
quit: Keybinding{"q"},
quitAlt1: nil,
expected: Keybinding{"q"},
},
{
name: "user-supplied multi-key main is preserved",
quit: Keybinding{"q", "<esc>"},
quitAlt1: Keybinding{"<ctrl+c>"},
expected: Keybinding{"q", "<esc>", "<ctrl+c>"},
},
{
name: "multi-key alt is folded element by element",
quit: Keybinding{"q"},
quitAlt1: Keybinding{"<ctrl+c>", "<esc>"},
expected: Keybinding{"q", "<ctrl+c>", "<esc>"},
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
cfg := KeybindingConfig{
Universal: KeybindingUniversalConfig{
Quit: s.quit,
QuitAlt1: s.quitAlt1,
},
}
cfg.MergeLegacyAltKeybindings()
assert.Equal(t, s.expected, cfg.Universal.Quit)
})
}
}
func TestKeybindingYAMLRoundTrip(t *testing.T) {
scenarios := []Keybinding{
{"q"},

View file

@ -423,7 +423,8 @@ type KeybindingConfig struct {
// damn looks like we have some inconsistencies here with -alt and -alt1
type KeybindingUniversalConfig struct {
Quit Keybinding `yaml:"quit"`
Quit Keybinding `yaml:"quit"`
// Deprecated: add the key to `quit` instead.
QuitAlt1 Keybinding `yaml:"quit-alt1"`
SuspendApp Keybinding `yaml:"suspendApp"`
Return Keybinding `yaml:"return"`
@ -769,6 +770,14 @@ type IconProperties struct {
Color string `yaml:"color"`
}
// MergeLegacyAltKeybindings folds deprecated `*Alt*` fields into their
// corresponding multi-key main field. New code should treat the main field
// as the single source of truth; the alt fields will be removed in a future
// release.
func (c *KeybindingConfig) MergeLegacyAltKeybindings() {
mergeLegacyAlt(&c.Universal.Quit, c.Universal.QuitAlt1)
}
func GetDefaultConfig() *UserConfig {
// This is only for tests; we don't want to use the test runner's host platform in that case,
// but always use the fallback bindings

View file

@ -111,10 +111,6 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type
Description: self.c.Tr.Quit,
Handler: self.quit,
},
{
Keys: opts.GetKeys(opts.Config.Universal.QuitAlt1),
Handler: self.quit,
},
{
Keys: opts.GetKeys(opts.Config.Universal.QuitWithoutChangingDirectory),
Handler: self.quitWithoutChangingDirectory,

View file

@ -60,6 +60,7 @@ func customReflect(v *config.UserConfig) *jsonschema.Schema {
schema := r.Reflect(v)
inlineKeybindingRefs(schema)
defaultConfig := config.GetDefaultConfig()
defaultConfig.Keybinding.MergeLegacyAltKeybindings()
userConfigSchema := schema.Definitions["UserConfig"]
defaultValue := reflect.ValueOf(defaultConfig).Elem()

View file

@ -2125,7 +2125,10 @@
"type": "array"
}
],
"default": "q"
"default": [
"q",
"\u003cctrl+c\u003e"
]
},
"quit-alt1": {
"oneOf": [
@ -2139,6 +2142,7 @@
"type": "array"
}
],
"description": "Deprecated: add the key to `quit` instead.",
"default": "\u003cctrl+c\u003e"
},
"suspendApp": {