{-# LANGUAGE TupleSections #-}
{-# LANGUAGE OverloadedStrings #-}
module Brick.Keybindings.Parse
( parseBinding
, parseBindingList
, keybindingsFromIni
, keybindingsFromFile
, keybindingIniParser
)
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
import Text.Read (readMaybe)
import qualified Data.Ini.Config as Ini
import Brick.Keybindings.KeyEvents
import Brick.Keybindings.KeyConfig
parseBindingList :: T.Text -> Either String BindingState
parseBindingList :: Text -> Either String BindingState
parseBindingList Text
t =
if Text -> Text
T.toLower Text
t forall a. Eq a => a -> a -> Bool
== Text
"unbound"
then forall (m :: * -> *) a. Monad m => a -> m a
return BindingState
Unbound
else [Binding] -> BindingState
BindingList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Text -> Either String Binding
parseBinding forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip) (Text -> Text -> [Text]
T.splitOn Text
"," forall a b. (a -> b) -> a -> b
$ Text -> Text
T.strip Text
t)
parseBinding :: T.Text -> Either String Binding
parseBinding :: Text -> Either String Binding
parseBinding Text
s = [Text] -> [Modifier] -> Either String Binding
go (Text -> Text -> [Text]
T.splitOn Text
"-" forall a b. (a -> b) -> a -> b
$ Text -> Text
T.toLower Text
s) []
where go :: [Text] -> [Modifier] -> Either String Binding
go [Text
k] [Modifier]
mods = do
Key
k' <- Text -> Either String Key
pKey Text
k
forall (m :: * -> *) a. Monad m => a -> m a
return Binding { kbMods :: Set Modifier
kbMods = forall a. Ord a => [a] -> Set a
S.fromList [Modifier]
mods, kbKey :: Key
kbKey = Key
k' }
go (Text
k:[Text]
ks) [Modifier]
mods = do
Modifier
m <- case Text
k of
Text
"s" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MShift
Text
"shift" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MShift
Text
"m" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MMeta
Text
"meta" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MMeta
Text
"a" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MAlt
Text
"alt" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MAlt
Text
"c" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MCtrl
Text
"ctrl" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MCtrl
Text
"control" -> forall (m :: * -> *) a. Monad m => a -> m a
return Modifier
Vty.MCtrl
Text
_ -> forall a b. a -> Either a b
Left (String
"Unknown modifier prefix: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
k)
[Text] -> [Modifier] -> Either String Binding
go [Text]
ks (Modifier
mforall a. a -> [a] -> [a]
:[Modifier]
mods)
go [] [Modifier]
_ = forall a b. a -> Either a b
Left String
"Empty keybinding not allowed"
pKey :: Text -> Either String Key
pKey Text
"esc" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KEsc
pKey Text
"backspace" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KBS
pKey Text
"enter" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KEnter
pKey Text
"left" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KLeft
pKey Text
"right" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KRight
pKey Text
"up" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KUp
pKey Text
"down" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KDown
pKey Text
"upleft" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KUpLeft
pKey Text
"upright" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KUpRight
pKey Text
"downleft" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KDownLeft
pKey Text
"downright" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KDownRight
pKey Text
"center" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KCenter
pKey Text
"backtab" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KBackTab
pKey Text
"printscreen" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KPrtScr
pKey Text
"pause" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KPause
pKey Text
"insert" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KIns
pKey Text
"home" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KHome
pKey Text
"pgup" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KPageUp
pKey Text
"del" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KDel
pKey Text
"end" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KEnd
pKey Text
"pgdown" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KPageDown
pKey Text
"begin" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KBegin
pKey Text
"menu" = forall (m :: * -> *) a. Monad m => a -> m a
return Key
Vty.KMenu
pKey Text
"space" = forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> Key
Vty.KChar Char
' ')
pKey Text
"tab" = forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> Key
Vty.KChar Char
'\t')
pKey Text
t
| Text -> Int
T.length Text
t forall a. Eq a => a -> a -> Bool
== Int
1 =
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> Key
Vty.KChar forall a b. (a -> b) -> a -> b
$ Text -> Char
T.last Text
s)
| Just Text
n <- Text -> Text -> Maybe Text
T.stripPrefix Text
"f" Text
t =
case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
n) of
Maybe Int
Nothing -> forall a b. a -> Either a b
Left (String
"Unknown keybinding: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
t)
Just Int
i -> forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Key
Vty.KFun Int
i)
| Bool
otherwise = forall a b. a -> Either a b
Left (String
"Unknown keybinding: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
t)
keybindingsFromIni :: KeyEvents k
-> T.Text
-> T.Text
-> Either String (Maybe [(k, BindingState)])
keybindingsFromIni :: forall k.
KeyEvents k
-> Text -> Text -> Either String (Maybe [(k, BindingState)])
keybindingsFromIni KeyEvents k
evs Text
section Text
doc =
forall a. Text -> IniParser a -> Either String a
Ini.parseIniFile Text
doc (forall k.
KeyEvents k -> Text -> IniParser (Maybe [(k, BindingState)])
keybindingIniParser KeyEvents k
evs Text
section)
keybindingsFromFile :: KeyEvents k
-> T.Text
-> FilePath
-> IO (Either String (Maybe [(k, BindingState)]))
keybindingsFromFile :: forall k.
KeyEvents k
-> Text -> String -> IO (Either String (Maybe [(k, BindingState)]))
keybindingsFromFile KeyEvents k
evs Text
section String
path =
forall k.
KeyEvents k
-> Text -> Text -> Either String (Maybe [(k, BindingState)])
keybindingsFromIni KeyEvents k
evs Text
section forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
T.readFile String
path
keybindingIniParser :: KeyEvents k -> T.Text -> Ini.IniParser (Maybe [(k, BindingState)])
keybindingIniParser :: forall k.
KeyEvents k -> Text -> IniParser (Maybe [(k, BindingState)])
keybindingIniParser KeyEvents k
evs Text
section =
forall a. Text -> SectionParser a -> IniParser (Maybe a)
Ini.sectionMb Text
section forall a b. (a -> b) -> a -> b
$ do
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (forall k. KeyEvents k -> [(Text, k)]
keyEventsList KeyEvents k
evs) forall a b. (a -> b) -> a -> b
$ \(Text
name, k
e) -> do
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (k
e,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a.
Text -> (Text -> Either String a) -> SectionParser (Maybe a)
Ini.fieldMbOf Text
name Text -> Either String BindingState
parseBindingList