-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathExample.hs
140 lines (105 loc) · 3.5 KB
/
Example.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Main where
import Control.Monad.State.Strict
import Data.List (isPrefixOf)
import qualified Data.Set as Set
import System.Console.Repline
-------------------------------------------------------------------------------
-- Stateful Completion
-------------------------------------------------------------------------------
type IState = Set.Set String
type Repl1 a = HaskelineT (StateT IState IO) a
-- Evaluation
cmd1 :: String -> Repl1 ()
cmd1 input = modify $ Set.insert input
-- Completion
completer1 :: (Monad m, MonadState IState m) => WordCompleter m
completer1 n = do
ns <- get
return $ filter (isPrefixOf n) (Set.toList ns)
-- Commands
help1 :: [String] -> Repl1 ()
help1 args = liftIO $ print $ "Help!" ++ show args
puts1 :: [String] -> Repl1 ()
puts1 args = modify $ Set.union (Set.fromList args)
opts1 :: [(String, String -> Repl1 ())]
opts1 =
[ ("help", help1 . words), -- :help
("puts", puts1 . words) -- :puts
]
init1 :: Repl1 ()
init1 = return ()
final1 :: Repl1 ExitDecision
final1 = return Exit
-- Tab completion inside of StateT
repl1 :: IO ()
repl1 =
flip evalStateT Set.empty $
evalRepl (const $ pure "_proto> ") cmd1 opts1 (Just ':') Nothing (Word completer1) init1 final1
-------------------------------------------------------------------------------
-- Command options
-------------------------------------------------------------------------------
type Repl2 a = HaskelineT IO a
-- Evaluation
cmd2 :: String -> Repl2 ()
cmd2 input = liftIO $ print input
-- Completion
comp2 :: Monad m => WordCompleter m
comp2 = listWordCompleter ["kirk", "spock", "mccoy"]
-- Commands
help2 :: [String] -> Repl2 ()
help2 args = liftIO $ print $ "Help!" ++ show args
opts2 :: [(String, String -> Repl2 ())]
opts2 =
[ ("help", help2 . words)
]
init2 :: Repl2 ()
init2 = liftIO $ putStrLn "Welcome!"
final2 :: Repl2 ExitDecision
final2 = do
liftIO $ putStrLn "Goodbye!"
return Exit
repl2 :: IO ()
repl2 = evalRepl (const $ pure "example2> ") cmd2 opts2 (Just ':') Nothing (Word comp2) init2 final2
-------------------------------------------------------------------------------
-- Mixed Completion
-------------------------------------------------------------------------------
type Repl3 a = HaskelineT IO a
-- Evaluation
cmd3 :: String -> Repl3 ()
cmd3 input = liftIO $ print input
defaultMatcher :: MonadIO m => [(String, CompletionFunc m)]
defaultMatcher =
[ (":file", fileCompleter),
(":holiday", listCompleter ["christmas", "thanksgiving", "festivus"])
]
byWord :: Monad m => WordCompleter m
byWord n = do
let names = ["picard", "riker", "data", ":file", ":holiday"]
return $ filter (isPrefixOf n) names
files :: String -> Repl3 ()
files args = liftIO $ do
contents <- readFile args
putStrLn contents
holidays :: String -> Repl3 ()
holidays "" = liftIO $ putStrLn "Enter a holiday."
holidays xs = liftIO $ do
putStrLn $ "Happy " ++ xs ++ "!"
opts3 :: [(String, String -> Repl3 ())]
opts3 =
[ ("file", files),
("holiday", holidays)
]
init3 :: Repl3 ()
init3 = return ()
final3 :: Repl3 ExitDecision
final3 = return Exit
repl3 :: IO ()
repl3 = evalRepl (const $ pure "example3> ") cmd3 opts3 (Just ':') Nothing (Prefix (wordCompleter byWord) defaultMatcher) init3 final3
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
main :: IO ()
main = repl1 >> repl2 >> repl3