diff --git a/macos/Sources/Ghostty/Ghostty.Input.swift b/macos/Sources/Ghostty/Ghostty.Input.swift index fc0224b3e..d90fb987e 100644 --- a/macos/Sources/Ghostty/Ghostty.Input.swift +++ b/macos/Sources/Ghostty/Ghostty.Input.swift @@ -29,8 +29,11 @@ extension Ghostty { } case GHOSTTY_TRIGGER_UNICODE: - guard let scalar = UnicodeScalar(trigger.key.unicode) else { return nil } - key = KeyEquivalent(Character(scalar)) + guard + let scalar = UnicodeScalar(trigger.key.unicode), + let normalized = Character(scalar).lowercased().first + else { return nil } + key = KeyEquivalent(normalized) case GHOSTTY_TRIGGER_CATCH_ALL: // catch_all matches any key, so it can't be represented as a KeyboardShortcut diff --git a/macos/Tests/Ghostty/ConfigTests.swift b/macos/Tests/Ghostty/ConfigTests.swift index fa2199537..9581efd56 100644 --- a/macos/Tests/Ghostty/ConfigTests.swift +++ b/macos/Tests/Ghostty/ConfigTests.swift @@ -220,4 +220,19 @@ struct ConfigTests { #expect(config.maximize == true) #expect(config.focusFollowsMouse == true) } + + @Test + func uppercasedLetterShouldBeNormalized() async throws { + let config = try TemporaryConfig(""" + keybind=cmd+L=goto_split:left + """) + let shortcut = try #require(config.keyboardShortcut(for: "goto_split:left")) + #expect(shortcut == .init("l", modifiers: [.command])) + + let config2 = try TemporaryConfig(""" + keybind=cmd+Ä=goto_split:left + """) + let shortcut2 = try #require(config2.keyboardShortcut(for: "goto_split:left")) + #expect(shortcut2 == .init("ä", modifiers: [.command])) + } }