diff --git a/brick.cabal b/brick.cabal index 176fc95..01ebe8f 100644 --- a/brick.cabal +++ b/brick.cabal @@ -77,6 +77,7 @@ library Brick.Keybindings.KeyConfig Brick.Keybindings.KeyEvents Brick.Keybindings.KeyDispatcher + Brick.Keybindings.Normalize Brick.Keybindings.Parse Brick.Keybindings.Pretty Brick.Focus diff --git a/src/Brick/Keybindings/KeyConfig.hs b/src/Brick/Keybindings/KeyConfig.hs index c0daba4..35966b1 100644 --- a/src/Brick/Keybindings/KeyConfig.hs +++ b/src/Brick/Keybindings/KeyConfig.hs @@ -47,6 +47,7 @@ import Data.Maybe (fromMaybe, listToMaybe, catMaybes) import qualified Graphics.Vty as Vty import Brick.Keybindings.KeyEvents +import Brick.Keybindings.Normalize -- | A key binding. -- @@ -67,10 +68,12 @@ data Binding = -- ^ The set of modifiers. } deriving (Eq, Show, Ord) --- | Construct a 'Binding'. Modifier order is ignored. +-- | Construct a 'Binding'. Modifier order is ignored. If modifiers +-- are given and the binding is for a character key, it is forced to +-- lowercase. binding :: Vty.Key -> [Vty.Modifier] -> Binding binding k mods = - Binding { kbKey = k + Binding { kbKey = normalizeKey mods k , kbMods = S.fromList mods } @@ -230,17 +233,23 @@ instance ToBinding Binding where addModifier :: (ToBinding a) => Vty.Modifier -> a -> Binding addModifier m val = let b = bind val - in b { kbMods = S.insert m (kbMods b) } + newMods = S.insert m $ kbMods b + in b { kbMods = newMods + , kbKey = normalizeKey (S.toList newMods) $ kbKey b + } --- | Add Meta to a binding. +-- | Add Meta to a binding. If the binding is for a character key, force +-- it to lowercase. meta :: (ToBinding a) => a -> Binding meta = addModifier Vty.MMeta --- | Add Ctrl to a binding. +-- | Add Ctrl to a binding. If the binding is for a character key, force +-- it to lowercase. ctrl :: (ToBinding a) => a -> Binding ctrl = addModifier Vty.MCtrl --- | Add Shift to a binding. +-- | Add Shift to a binding. If the binding is for a character key, force +-- it to lowercase. shift :: (ToBinding a) => a -> Binding shift = addModifier Vty.MShift diff --git a/src/Brick/Keybindings/Normalize.hs b/src/Brick/Keybindings/Normalize.hs new file mode 100644 index 0000000..6711a64 --- /dev/null +++ b/src/Brick/Keybindings/Normalize.hs @@ -0,0 +1,14 @@ +module Brick.Keybindings.Normalize + ( normalizeKey + ) +where + +import Data.Char (toLower) +import qualified Graphics.Vty as Vty + +-- | A keybinding involving modifiers should have its key character +-- normalized to lowercase since it's impossible to get uppercase keys +-- from the terminal when modifiers are present. +normalizeKey :: [Vty.Modifier] -> Vty.Key -> Vty.Key +normalizeKey (_:_) (Vty.KChar c) = Vty.KChar $ toLower c +normalizeKey _ k = k diff --git a/src/Brick/Keybindings/Parse.hs b/src/Brick/Keybindings/Parse.hs index ac2370e..b3e8908 100644 --- a/src/Brick/Keybindings/Parse.hs +++ b/src/Brick/Keybindings/Parse.hs @@ -5,6 +5,7 @@ module Brick.Keybindings.Parse ( parseBinding , parseBindingList + , normalizeKey , keybindingsFromIni , keybindingsFromFile @@ -14,7 +15,6 @@ where import Control.Monad (forM) import Data.Maybe (catMaybes) -import qualified Data.Set as S import qualified Data.Text as T import qualified Data.Text.IO as T import qualified Graphics.Vty as Vty @@ -23,6 +23,7 @@ import qualified Data.Ini.Config as Ini import Brick.Keybindings.KeyEvents import Brick.Keybindings.KeyConfig +import Brick.Keybindings.Normalize -- | Parse a key binding list into a 'BindingState'. -- @@ -83,7 +84,7 @@ parseBinding :: T.Text -> Either String Binding parseBinding s = go (T.splitOn "-" $ T.toLower s) [] where go [k] mods = do k' <- pKey k - return Binding { kbMods = S.fromList mods, kbKey = k' } + return $ binding k' mods go (k:ks) mods = do m <- case k of "s" -> return Vty.MShift