module System.Console.Haskeline.Prefs where
import Language.Haskell.TH
import Data.Char(isSpace,toLower)
import Data.List(foldl')
import Control.Exception(handle)
data Prefs = Prefs { bellStyle :: !BellStyle,
editMode :: !EditMode,
maxHistorySize :: !(Maybe Int),
completionType :: !CompletionType,
completionPaging :: !Bool,
completionPromptLimit :: !(Maybe Int),
listCompletionsImmediately :: !Bool
}
deriving (Read,Show)
data CompletionType = ListCompletion | MenuCompletion
deriving (Read,Show)
data BellStyle = NoBell | VisualBell | AudibleBell
deriving (Show, Read)
data EditMode = Vi | Emacs
deriving (Show,Read)
defaultPrefs :: Prefs
defaultPrefs = Prefs {bellStyle = AudibleBell,
maxHistorySize = Nothing,
editMode = Emacs,
completionType = ListCompletion,
completionPaging = True,
completionPromptLimit = Just 100,
listCompletionsImmediately = True
}
mkSettor :: Read a => (a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor f str = case reads str of
[(x,_)] -> f x
_ -> id
settors :: [(String,String -> Prefs -> Prefs)]
settors = $(do
DataConI _ _ prefsType _ <- reify 'Prefs
TyConI (DataD _ _ _ [RecC _ fields] _) <- reify prefsType
x <- newName "x"
p <- newName "p"
let settor (f,_,_) = TupE [LitE (StringL (map toLower $ nameBase f)),
AppE (VarE 'mkSettor) $ LamE [VarP x,VarP p]
$ RecUpdE (VarE p) [(f,VarE x)]]
return $ ListE $ map settor fields)
readPrefs :: FilePath -> IO Prefs
readPrefs file = handle (\_ -> return defaultPrefs) $ do
ls <- fmap lines $ readFile file
return $ foldl' applyField defaultPrefs ls
where
applyField p l = case break (==':') l of
(name,val) -> case lookup (map toLower $ trimSpaces name) settors of
Nothing -> p
Just set -> set (drop 1 val) p
trimSpaces = dropWhile isSpace . reverse . dropWhile isSpace . reverse