on master help sign in
Improve auto-completion a bit more
2ec15dfEvan Czaplicki
builder/src/Generate/Output.hs+2−2
@@ -38,7 +38,7 @@ import qualified Reporting.Exit as Exit
38import qualified Reporting.Exit.Make as E
38import qualified Reporting.Exit.Make as E
39import qualified Reporting.Task as Task
39import qualified Reporting.Task as Task
40import qualified Stuff.Paths as Paths
40import qualified Stuff.Paths as Paths
41−import Terminal.Args (Parser(..), suggestFiles)
41+import Terminal.Args (Parser(..))
42
42
43
43
44
44
@@ -206,7 +206,7 @@ output =
206 { _singular = "output file"
206 { _singular = "output file"
207 , _plural = "output files"
207 , _plural = "output files"
208 , _parser = parseOutput
208 , _parser = parseOutput
209− , _suggest = suggestFiles ["js","html"]
209+ , _suggest = \_ -> return []
210 , _examples = exampleOutput
210 , _examples = exampleOutput
211 }
211 }
212
212
ui/terminal/src/Make.hs+2−2
@@ -20,7 +20,7 @@ import qualified Reporting.Task as Task
20import qualified Reporting.Progress as Progress
20import qualified Reporting.Progress as Progress
21import qualified Reporting.Progress.Json as Json
21import qualified Reporting.Progress.Json as Json
22import qualified Reporting.Progress.Terminal as Terminal
22import qualified Reporting.Progress.Terminal as Terminal
23−import Terminal.Args (Parser(..), suggestFiles)
23+import Terminal.Args (Parser(..))
24
24
25
25
26
26
@@ -92,6 +92,6 @@ docsFile =
92 { _singular = "json file"
92 { _singular = "json file"
93 , _plural = "json files"
93 , _plural = "json files"
94 , _parser = \string -> if FP.takeExtension string == ".json" then Just string else Nothing
94 , _parser = \string -> if FP.takeExtension string == ".json" then Just string else Nothing
95− , _suggest = suggestFiles ["json"]
95+ , _suggest = \_ -> return []
96 , _examples = \_ -> return ["docs.json","documentation.json"]
96 , _examples = \_ -> return ["docs.json","documentation.json"]
97 }
97 }
ui/terminal/src/Terminal/Args.hs+78−40
@@ -5,7 +5,7 @@ module Terminal.Args
5 , complex
5 , complex
6 , Flags, noFlags, flags, (|--)
6 , Flags, noFlags, flags, (|--)
7 , Flag, flag, onOff
7 , Flag, flag, onOff
8− , Parser(..), suggestFiles
8+ , Parser(..)
9 , Args, noArgs, required, optional, zeroOrMore, oneOrMore, oneOf
9 , Args, noArgs, required, optional, zeroOrMore, oneOrMore, oneOf
10 , require0, require1, require2, require3, require4, require5
10 , require0, require1, require2, require3, require4, require5
11 , RequiredArgs, args, exactly, (!), (?), (...)
11 , RequiredArgs, args, exactly, (!), (?), (...)
@@ -13,7 +13,7 @@ module Terminal.Args
13 where
13 where
14
14
15
15
16−import Control.Monad (filterM)
16+import Control.Monad (filterM, when)
17import qualified Data.Char as Char
17import qualified Data.Char as Char
18import qualified Data.List as List
18import qualified Data.List as List
19import qualified Data.Maybe as Maybe
19import qualified Data.Maybe as Maybe
@@ -22,8 +22,9 @@ import qualified System.Environment as Env
22import qualified System.Exit as Exit
22import qualified System.Exit as Exit
23import qualified System.FilePath as FP
23import qualified System.FilePath as FP
24import System.FilePath ((</>))
24import System.FilePath ((</>))
25−import System.IO (hPutStrLn, stdout)
25+import System.IO (hPutStr, hPutStrLn, stdout)
26import qualified Text.PrettyPrint.ANSI.Leijen as P
26import qualified Text.PrettyPrint.ANSI.Leijen as P
27+import qualified Text.Read as Read
27
28
28import qualified Elm.Compiler as Compiler
29import qualified Elm.Compiler as Compiler
29import qualified Elm.Package as Pkg
30import qualified Elm.Package as Pkg
@@ -40,10 +41,6 @@ simple :: String -> P.Doc -> Args args -> Flags flags -> (args -> flags -> IO ()
40simple details example args_ flags_ callback =
41simple details example args_ flags_ callback =
41 do argStrings <- Env.getArgs
42 do argStrings <- Env.getArgs
42 case argStrings of
43 case argStrings of
43− "autocomplete" : number : chunks ->
44− attemptAutoComplete number $ \index ->
45− fst $ Chomp.chomp (Just index) chunks args_ flags_
46−
47 ["--version"] ->
44 ["--version"] ->
48 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
45 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
49 Exit.exitSuccess
46 Exit.exitSuccess
@@ -53,12 +50,15 @@ simple details example args_ flags_ callback =
53 Error.exitWithHelp Nothing details example args_ flags_
50 Error.exitWithHelp Nothing details example args_ flags_
54
51
55 else
52 else
53+ do maybeAutoComplete chunks $ \index cs ->
54+ fst $ Chomp.chomp (Just index) cs args_ flags_
55+
56− case snd $ Chomp.chomp Nothing chunks args_ flags_ of
56+ case snd $ Chomp.chomp Nothing chunks args_ flags_ of
57− Right (argsValue, flagValue) ->
57+ Right (argsValue, flagValue) ->
58− callback argsValue flagValue
58+ callback argsValue flagValue
59
59
60− Left err ->
60+ Left err ->
61− Error.exitWithError err
61+ Error.exitWithError err
62
62
63
63
64complex :: P.Doc -> P.Doc -> [Interface] -> IO ()
64complex :: P.Doc -> P.Doc -> [Interface] -> IO ()
@@ -75,44 +75,79 @@ complex intro outro interfaces =
75 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
75 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
76 Exit.exitSuccess
76 Exit.exitSuccess
77
77
78− "autocomplete" : number : chunks ->
79− attemptAutoComplete number $ \index ->
80− complexSuggest index chunks interfaces
81−
82 command : chunks ->
78 command : chunks ->
79+ do maybeAutoComplete argStrings (complexSuggest interfaces)
83− case List.find (\iface -> toName iface == command) interfaces of
80+ case List.find (\iface -> toName iface == command) interfaces of
84− Nothing ->
81+ Nothing ->
85− Error.exitWithUnknown command (map toName interfaces)
82+ Error.exitWithUnknown command (map toName interfaces)
86
83
87− Just (Interface _ _ details example args_ flags_ callback) ->
84+ Just (Interface _ _ details example args_ flags_ callback) ->
88− if elem "--help" chunks then
85+ if elem "--help" chunks then
89− Error.exitWithHelp (Just command) details example args_ flags_
86+ Error.exitWithHelp (Just command) details example args_ flags_
90
87
91− else
88+ else
92− case snd $ Chomp.chomp Nothing chunks args_ flags_ of
89+ case snd $ Chomp.chomp Nothing chunks args_ flags_ of
93− Right (argsValue, flagValue) ->
90+ Right (argsValue, flagValue) ->
94− callback argsValue flagValue
91+ callback argsValue flagValue
95
92
96− Left err ->
93+ Left err ->
97− Error.exitWithError err
94+ Error.exitWithError err
98
95
99
96
100
97
101-- AUTO-COMPLETE
98-- AUTO-COMPLETE
102
99
103
100
104−attemptAutoComplete :: String -> (Int -> IO [String]) -> IO a
101+maybeAutoComplete :: [String] -> (Int -> [String] -> IO [String]) -> IO ()
105−attemptAutoComplete number getSuggestions =
102+maybeAutoComplete args getSuggestions =
106− if all Char.isDigit number then
103+ if length args /= 3 then
107− do suggestions <- getSuggestions (read number)
104+ return ()
108− hPutStrLn stdout (List.intercalate " " suggestions)
109− Exit.exitSuccess
110 else
105 else
106+ do maybeLine <- Env.lookupEnv "COMP_LINE"
107+ case maybeLine of
108+ Nothing ->
109+ return ()
110+
111+ Just line ->
112+ do (index, chunks) <- getCompIndex line
113+ suggestions <- getSuggestions index chunks
114+ hPutStr stdout (unlines suggestions)
111− Exit.exitFailure
115+ Exit.exitFailure
116+
117+
118+getCompIndex :: String -> IO (Int, [String])
119+getCompIndex line =
120+ do maybePoint <- Env.lookupEnv "COMP_POINT"
121+ case Read.readMaybe =<< maybePoint :: Maybe Int of
122+ Nothing ->
123+ do let chunks = words line
124+ return (length chunks, chunks)
125+
126+ Just point ->
127+ let
128+ isPoint (_,i) = i == point
129+ groups = List.groupBy grouper (zip line [0..])
130+ rawChunks = drop 1 (filter (all (not . isSpace . fst)) groups)
131+ maybeIndex = List.findIndex (any isPoint) rawChunks
132+ in
133+ return
134+ ( maybe (length rawChunks) id maybeIndex
135+ , map (map fst) rawChunks
136+ )
112
137
113
138
139+grouper :: (Char, Int) -> (Char, Int) -> Bool
140+grouper (c1, _) (c2, _) =
141+ isSpace c1 == isSpace c2
142+
143+
144+isSpace :: Char -> Bool
145+isSpace char =
146+ char == ' ' || char == '\t' || char == '\n'
147+
148+
114−complexSuggest :: Int -> [String] -> [Interface] -> IO [String]
149+complexSuggest :: [Interface] -> Int -> [String] -> IO [String]
115−complexSuggest index strings interfaces =
150+complexSuggest interfaces index strings =
116 case strings of
151 case strings of
117 [] ->
152 [] ->
118 return (map toName interfaces)
153 return (map toName interfaces)
@@ -120,7 +155,10 @@ complexSuggest index strings interfaces =
120 command : chunks ->
155 command : chunks ->
121 case List.find (\iface -> toName iface == command) interfaces of
156 case List.find (\iface -> toName iface == command) interfaces of
122 Nothing ->
157 Nothing ->
158+ if index == 1 then
123− return (map toName interfaces)
159+ return (filter (List.isPrefixOf command) (map toName interfaces))
160+ else
161+ return []
124
162
125 Just (Interface _ _ _ _ args_ flags_ _) ->
163 Just (Interface _ _ _ _ args_ flags_ _) ->
126 fst $ Chomp.chomp (Just (index-1)) chunks args_ flags_
164 fst $ Chomp.chomp (Just (index-1)) chunks args_ flags_
@@ -289,8 +327,8 @@ Notice that you can limit the suggestion by the file extension! If you need
289something more elaborate, you can implement a function like this yourself that
327something more elaborate, you can implement a function like this yourself that
290does whatever you need!
328does whatever you need!
291-}
329-}
292−suggestFiles :: [String] -> String -> IO [String]
330+_suggestFiles :: [String] -> String -> IO [String]
293−suggestFiles extensions string =
331+_suggestFiles extensions string =
294 let
332 let
295 (dir, start) =
333 (dir, start) =
296 FP.splitFileName string
334 FP.splitFileName string
ui/terminal/src/Terminal/Args/Chomp.hs+1−1
@@ -464,7 +464,7 @@ getFlagName :: Flag a -> String
464getFlagName flag =
464getFlagName flag =
465 case flag of
465 case flag of
466 Flag name _ _ ->
466 Flag name _ _ ->
467− "--" ++ name ++ "="
467+ "--" ++ name
468
468
469 OnOff name _ ->
469 OnOff name _ ->
470 "--" ++ name
470 "--" ++ name
ui/terminal/src/Terminal/Args/Helpers.hs+2−2
@@ -11,7 +11,7 @@ import qualified Data.Char as Char
11import qualified Data.Text as Text
11import qualified Data.Text as Text
12import qualified System.FilePath as FP
12import qualified System.FilePath as FP
13
13
14−import Terminal.Args (Parser(..), suggestFiles)
14+import Terminal.Args (Parser(..))
15import qualified Elm.Package as Pkg
15import qualified Elm.Package as Pkg
16
16
17
17
@@ -67,7 +67,7 @@ elmFile =
67 { _singular = "elm file"
67 { _singular = "elm file"
68 , _plural = "elm files"
68 , _plural = "elm files"
69 , _parser = parseElmFile
69 , _parser = parseElmFile
70− , _suggest = suggestFiles ["elm"]
70+ , _suggest = \_ -> return []
71 , _examples = exampleElmFiles
71 , _examples = exampleElmFiles
72 }
72 }
73
73