From 6b9b25243e8885fc4a282c55dfff6ac76da3f8d2 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 4 Jun 2026 07:53:01 +0200 Subject: [PATCH] Allow overriding the platform used for default keybindings A handful of default keybindings differ by platform (e.g. word-wise cursor movement in text inputs uses alt on macOS but ctrl elsewhere). Lazygit chooses these based on the OS it runs on, but that's the wrong signal when the OS isn't where the user is actually typing: someone running lazygit in a Linux container that they access over ssh from a Mac gets the Linux bindings, when they'd rather have the Mac ones. Remapping each binding by hand via config is tedious, so add a single LAZYGIT_KEYBINDING_PLATFORM override. An unrecognized value falls back to the real OS rather than to the non-darwin default bindings, since the latter would be an arbitrary choice. --- docs-master/Config.md | 6 +++++ pkg/app/entry_point.go | 2 +- pkg/config/app_config.go | 17 +++++++++++++- pkg/config/app_config_test.go | 42 +++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/docs-master/Config.md b/docs-master/Config.md index 9f79218217f..ef26e852a4c 100644 --- a/docs-master/Config.md +++ b/docs-master/Config.md @@ -1059,6 +1059,12 @@ keybinding: edit: # disable 'edit file' ``` +### Overriding the platform for default keybindings + +A few keybindings have different defaults on macOS than on Linux and Windows (e.g. word-wise cursor movement in text inputs uses `alt` on macOS but `ctrl` elsewhere). Lazygit picks these based on the OS it's running on, but you can override that with the `LAZYGIT_KEYBINDING_PLATFORM` environment variable. Set it to `darwin`, `linux`, or `windows`; any other value is ignored and the actual OS is used. + +This is useful when running lazygit in a Linux container that you access over ssh from a Mac, where you'd rather use the macOS keybindings. + ### Example Keybindings For Colemak Users ```yaml diff --git a/pkg/app/entry_point.go b/pkg/app/entry_point.go index 8b1a2a040eb..a3225e31121 100644 --- a/pkg/app/entry_point.go +++ b/pkg/app/entry_point.go @@ -102,7 +102,7 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes if cliArgs.PrintDefaultConfig { var buf bytes.Buffer encoder := yaml.NewEncoder(&buf) - err := encoder.Encode(config.GetDefaultConfigForPlatform(runtime.GOOS)) + err := encoder.Encode(config.GetDefaultConfigForPlatform(config.KeybindingPlatform())) if err != nil { log.Fatal(err.Error()) } diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index e7267158a6f..c70197eed88 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -136,8 +136,23 @@ func findOrCreateConfigDir() (string, error) { return folder, os.MkdirAll(folder, 0o755) } +// KeybindingPlatform returns the platform whose default keybindings should be +// used. Normally this is the OS we're running on, but it can be overridden with +// the LAZYGIT_KEYBINDING_PLATFORM environment variable; this is useful e.g. when +// running lazygit in a Linux container that you access over ssh from a Mac, and +// you'd rather use the Mac keybindings. An unrecognized value falls back to the +// real OS, which gives meaningful bindings, rather than to the (arbitrary) +// non-darwin defaults. +func KeybindingPlatform() string { + platform := os.Getenv("LAZYGIT_KEYBINDING_PLATFORM") + if lo.Contains([]string{"darwin", "linux", "windows"}, platform) { + return platform + } + return runtime.GOOS +} + func loadUserConfigWithDefaults(configFiles []*ConfigFile, isGuiInitialized bool) (*UserConfig, error) { - return loadUserConfig(configFiles, GetDefaultConfigForPlatform(runtime.GOOS), isGuiInitialized) + return loadUserConfig(configFiles, GetDefaultConfigForPlatform(KeybindingPlatform()), isGuiInitialized) } func loadUserConfig(configFiles []*ConfigFile, base *UserConfig, isGuiInitialized bool) (*UserConfig, error) { diff --git a/pkg/config/app_config_test.go b/pkg/config/app_config_test.go index 1109256a9d3..8c060d7eecf 100644 --- a/pkg/config/app_config_test.go +++ b/pkg/config/app_config_test.go @@ -1,11 +1,53 @@ package config import ( + "runtime" "testing" "github.com/stretchr/testify/assert" ) +func TestKeybindingPlatform(t *testing.T) { + scenarios := []struct { + name string + envValue string + expected string + }{ + { + name: "Not set falls back to the host OS", + envValue: "", + expected: runtime.GOOS, + }, + { + name: "darwin is honored", + envValue: "darwin", + expected: "darwin", + }, + { + name: "linux is honored", + envValue: "linux", + expected: "linux", + }, + { + name: "windows is honored", + envValue: "windows", + expected: "windows", + }, + { + name: "An unrecognized value falls back to the host OS", + envValue: "mac", + expected: runtime.GOOS, + }, + } + + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + t.Setenv("LAZYGIT_KEYBINDING_PLATFORM", s.envValue) + assert.Equal(t, s.expected, KeybindingPlatform()) + }) + } +} + func TestMigrationOfRenamedKeys(t *testing.T) { scenarios := []struct { name string