module System.Console.Haskeline.Prefs(
Prefs(..),
defaultPrefs,
readPrefs,
CompletionType(..),
BellStyle(..),
EditMode(..),
HistoryDuplicates(..),
lookupKeyBinding
) where
import Control.Monad.Catch (handle)
import Control.Exception (IOException)
import Data.Char(isSpace,toLower)
import Data.List(foldl')
import qualified Data.Map as Map
import System.Console.Haskeline.Key
data Prefs = Prefs { Prefs -> BellStyle
bellStyle :: !BellStyle,
Prefs -> EditMode
editMode :: !EditMode,
Prefs -> Maybe Int
maxHistorySize :: !(Maybe Int),
Prefs -> HistoryDuplicates
historyDuplicates :: HistoryDuplicates,
Prefs -> CompletionType
completionType :: !CompletionType,
Prefs -> Bool
completionPaging :: !Bool,
Prefs -> Maybe Int
completionPromptLimit :: !(Maybe Int),
Prefs -> Bool
listCompletionsImmediately :: !Bool,
Prefs -> Map Key [Key]
customBindings :: Map.Map Key [Key],
Prefs -> [(Maybe String, String, Key)]
customKeySequences :: [(Maybe String, String,Key)]
}
deriving Int -> Prefs -> ShowS
[Prefs] -> ShowS
Prefs -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Prefs] -> ShowS
$cshowList :: [Prefs] -> ShowS
show :: Prefs -> String
$cshow :: Prefs -> String
showsPrec :: Int -> Prefs -> ShowS
$cshowsPrec :: Int -> Prefs -> ShowS
Show
data CompletionType = ListCompletion |
deriving (ReadPrec [CompletionType]
ReadPrec CompletionType
Int -> ReadS CompletionType
ReadS [CompletionType]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CompletionType]
$creadListPrec :: ReadPrec [CompletionType]
readPrec :: ReadPrec CompletionType
$creadPrec :: ReadPrec CompletionType
readList :: ReadS [CompletionType]
$creadList :: ReadS [CompletionType]
readsPrec :: Int -> ReadS CompletionType
$creadsPrec :: Int -> ReadS CompletionType
Read,Int -> CompletionType -> ShowS
[CompletionType] -> ShowS
CompletionType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CompletionType] -> ShowS
$cshowList :: [CompletionType] -> ShowS
show :: CompletionType -> String
$cshow :: CompletionType -> String
showsPrec :: Int -> CompletionType -> ShowS
$cshowsPrec :: Int -> CompletionType -> ShowS
Show)
data BellStyle = NoBell | VisualBell | AudibleBell
deriving (Int -> BellStyle -> ShowS
[BellStyle] -> ShowS
BellStyle -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BellStyle] -> ShowS
$cshowList :: [BellStyle] -> ShowS
show :: BellStyle -> String
$cshow :: BellStyle -> String
showsPrec :: Int -> BellStyle -> ShowS
$cshowsPrec :: Int -> BellStyle -> ShowS
Show, ReadPrec [BellStyle]
ReadPrec BellStyle
Int -> ReadS BellStyle
ReadS [BellStyle]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BellStyle]
$creadListPrec :: ReadPrec [BellStyle]
readPrec :: ReadPrec BellStyle
$creadPrec :: ReadPrec BellStyle
readList :: ReadS [BellStyle]
$creadList :: ReadS [BellStyle]
readsPrec :: Int -> ReadS BellStyle
$creadsPrec :: Int -> ReadS BellStyle
Read)
data EditMode = Vi | Emacs
deriving (Int -> EditMode -> ShowS
[EditMode] -> ShowS
EditMode -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EditMode] -> ShowS
$cshowList :: [EditMode] -> ShowS
show :: EditMode -> String
$cshow :: EditMode -> String
showsPrec :: Int -> EditMode -> ShowS
$cshowsPrec :: Int -> EditMode -> ShowS
Show,ReadPrec [EditMode]
ReadPrec EditMode
Int -> ReadS EditMode
ReadS [EditMode]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [EditMode]
$creadListPrec :: ReadPrec [EditMode]
readPrec :: ReadPrec EditMode
$creadPrec :: ReadPrec EditMode
readList :: ReadS [EditMode]
$creadList :: ReadS [EditMode]
readsPrec :: Int -> ReadS EditMode
$creadsPrec :: Int -> ReadS EditMode
Read)
data HistoryDuplicates = AlwaysAdd | IgnoreConsecutive | IgnoreAll
deriving (Int -> HistoryDuplicates -> ShowS
[HistoryDuplicates] -> ShowS
HistoryDuplicates -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HistoryDuplicates] -> ShowS
$cshowList :: [HistoryDuplicates] -> ShowS
show :: HistoryDuplicates -> String
$cshow :: HistoryDuplicates -> String
showsPrec :: Int -> HistoryDuplicates -> ShowS
$cshowsPrec :: Int -> HistoryDuplicates -> ShowS
Show,ReadPrec [HistoryDuplicates]
ReadPrec HistoryDuplicates
Int -> ReadS HistoryDuplicates
ReadS [HistoryDuplicates]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [HistoryDuplicates]
$creadListPrec :: ReadPrec [HistoryDuplicates]
readPrec :: ReadPrec HistoryDuplicates
$creadPrec :: ReadPrec HistoryDuplicates
readList :: ReadS [HistoryDuplicates]
$creadList :: ReadS [HistoryDuplicates]
readsPrec :: Int -> ReadS HistoryDuplicates
$creadsPrec :: Int -> ReadS HistoryDuplicates
Read)
defaultPrefs :: Prefs
defaultPrefs :: Prefs
defaultPrefs = Prefs {bellStyle :: BellStyle
bellStyle = BellStyle
AudibleBell,
maxHistorySize :: Maybe Int
maxHistorySize = forall a. a -> Maybe a
Just Int
100,
editMode :: EditMode
editMode = EditMode
Emacs,
completionType :: CompletionType
completionType = CompletionType
ListCompletion,
completionPaging :: Bool
completionPaging = Bool
True,
completionPromptLimit :: Maybe Int
completionPromptLimit = forall a. a -> Maybe a
Just Int
100,
listCompletionsImmediately :: Bool
listCompletionsImmediately = Bool
True,
historyDuplicates :: HistoryDuplicates
historyDuplicates = HistoryDuplicates
AlwaysAdd,
customBindings :: Map Key [Key]
customBindings = forall k a. Map k a
Map.empty,
customKeySequences :: [(Maybe String, String, Key)]
customKeySequences = []
}
mkSettor :: Read a => (a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor :: forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor a -> Prefs -> Prefs
f String
str = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. a -> a
id a -> Prefs -> Prefs
f (forall a. Read a => String -> Maybe a
readMaybe String
str)
readMaybe :: Read a => String -> Maybe a
readMaybe :: forall a. Read a => String -> Maybe a
readMaybe String
str = case forall a. Read a => ReadS a
reads String
str of
[(a
x,String
_)] -> forall a. a -> Maybe a
Just a
x
[(a, String)]
_ -> forall a. Maybe a
Nothing
settors :: [(String, String -> Prefs -> Prefs)]
settors :: [(String, String -> Prefs -> Prefs)]
settors = [(String
"bellstyle", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \BellStyle
x Prefs
p -> Prefs
p {bellStyle :: BellStyle
bellStyle = BellStyle
x})
,(String
"editmode", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \EditMode
x Prefs
p -> Prefs
p {editMode :: EditMode
editMode = EditMode
x})
,(String
"maxhistorysize", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \Maybe Int
x Prefs
p -> Prefs
p {maxHistorySize :: Maybe Int
maxHistorySize = Maybe Int
x})
,(String
"completiontype", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \CompletionType
x Prefs
p -> Prefs
p {completionType :: CompletionType
completionType = CompletionType
x})
,(String
"completionpaging", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \Bool
x Prefs
p -> Prefs
p {completionPaging :: Bool
completionPaging = Bool
x})
,(String
"completionpromptlimit", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \Maybe Int
x Prefs
p -> Prefs
p {completionPromptLimit :: Maybe Int
completionPromptLimit = Maybe Int
x})
,(String
"listcompletionsimmediately", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \Bool
x Prefs
p -> Prefs
p {listCompletionsImmediately :: Bool
listCompletionsImmediately = Bool
x})
,(String
"historyduplicates", forall a.
Read a =>
(a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
mkSettor forall a b. (a -> b) -> a -> b
$ \HistoryDuplicates
x Prefs
p -> Prefs
p {historyDuplicates :: HistoryDuplicates
historyDuplicates = HistoryDuplicates
x})
,(String
"bind", String -> Prefs -> Prefs
addCustomBinding)
,(String
"keyseq", String -> Prefs -> Prefs
addCustomKeySequence)
]
addCustomBinding :: String -> Prefs -> Prefs
addCustomBinding :: String -> Prefs -> Prefs
addCustomBinding String
str Prefs
p = case forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM String -> Maybe Key
parseKey (String -> [String]
words String
str) of
Just (Key
k:[Key]
ks) -> Prefs
p {customBindings :: Map Key [Key]
customBindings = forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Key
k [Key]
ks (Prefs -> Map Key [Key]
customBindings Prefs
p)}
Maybe [Key]
_ -> Prefs
p
addCustomKeySequence :: String -> Prefs -> Prefs
addCustomKeySequence :: String -> Prefs -> Prefs
addCustomKeySequence String
str = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. a -> a
id (Maybe String, String, Key) -> Prefs -> Prefs
addKS Maybe (Maybe String, String, Key)
maybeParse
where
maybeParse :: Maybe (Maybe String, String,Key)
maybeParse :: Maybe (Maybe String, String, Key)
maybeParse = case String -> [String]
words String
str of
[String
cstr,String
kstr] -> forall {b} {a}.
Read b =>
a -> String -> String -> Maybe (a, b, Key)
parseWords forall a. Maybe a
Nothing String
cstr String
kstr
[String
term,String
cstr,String
kstr] -> forall {b} {a}.
Read b =>
a -> String -> String -> Maybe (a, b, Key)
parseWords (forall a. a -> Maybe a
Just String
term) String
cstr String
kstr
[String]
_ -> forall a. Maybe a
Nothing
parseWords :: a -> String -> String -> Maybe (a, b, Key)
parseWords a
mterm String
cstr String
kstr = do
Key
k <- String -> Maybe Key
parseKey String
kstr
b
cs <- forall a. Read a => String -> Maybe a
readMaybe String
cstr
forall (m :: * -> *) a. Monad m => a -> m a
return (a
mterm,b
cs,Key
k)
addKS :: (Maybe String, String, Key) -> Prefs -> Prefs
addKS (Maybe String, String, Key)
ks Prefs
p = Prefs
p {customKeySequences :: [(Maybe String, String, Key)]
customKeySequences = (Maybe String, String, Key)
ksforall a. a -> [a] -> [a]
:Prefs -> [(Maybe String, String, Key)]
customKeySequences Prefs
p}
lookupKeyBinding :: Key -> Prefs -> [Key]
lookupKeyBinding :: Key -> Prefs -> [Key]
lookupKeyBinding Key
k = forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault [Key
k] Key
k forall b c a. (b -> c) -> (a -> b) -> a -> c
. Prefs -> Map Key [Key]
customBindings
readPrefs :: FilePath -> IO Prefs
readPrefs :: String -> IO Prefs
readPrefs String
file = forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
(e -> m a) -> m a -> m a
handle (\(IOException
_::IOException) -> forall (m :: * -> *) a. Monad m => a -> m a
return Prefs
defaultPrefs) forall a b. (a -> b) -> a -> b
$ do
[String]
ls <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> [String]
lines forall a b. (a -> b) -> a -> b
$ String -> IO String
readFile String
file
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Prefs -> String -> Prefs
applyField Prefs
defaultPrefs [String]
ls
where
applyField :: Prefs -> String -> Prefs
applyField Prefs
p String
l = case forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
==Char
':') String
l of
(String
name,String
val) -> case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower forall a b. (a -> b) -> a -> b
$ ShowS
trimSpaces String
name) [(String, String -> Prefs -> Prefs)]
settors of
Maybe (String -> Prefs -> Prefs)
Nothing -> Prefs
p
Just String -> Prefs -> Prefs
set -> String -> Prefs -> Prefs
set (forall a. Int -> [a] -> [a]
drop Int
1 String
val) Prefs
p
trimSpaces :: ShowS
trimSpaces = forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse