@@ -5,7 +5,7 @@ module Terminal.Args
55 , complex
66 , Flags, noFlags, flags, (|--)
77 , Flag, flag, onOff
8− , Parser(..), suggestFiles
8+ , Parser(..)
99 , Args, noArgs, required, optional, zeroOrMore, oneOrMore, oneOf
1010 , require0, require1, require2, require3, require4, require5
1111 , RequiredArgs, args, exactly, (!), (?), (...)
@@ -13,7 +13,7 @@ module Terminal.Args
1313 where
1414
1515
16−import Control.Monad (filterM)
16+import Control.Monad (filterM, when)
1717import qualified Data.Char as Char
1818import qualified Data.List as List
1919import qualified Data.Maybe as Maybe
@@ -22,8 +22,9 @@ import qualified System.Environment as Env
2222import qualified System.Exit as Exit
2323import qualified System.FilePath as FP
2424import System.FilePath ((</>))
25−import System.IO (hPutStrLn, stdout)
25+import System.IO (hPutStr, hPutStrLn, stdout)
2626import qualified Text.PrettyPrint.ANSI.Leijen as P
27+import qualified Text.Read as Read
2728
2829import qualified Elm.Compiler as Compiler
2930import qualified Elm.Package as Pkg
@@ -40,10 +41,6 @@ simple :: String -> P.Doc -> Args args -> Flags flags -> (args -> flags -> IO ()
4041simple details example args_ flags_ callback =
4142 do argStrings <- Env.getArgs
4243 case argStrings of
43− "autocomplete" : number : chunks ->
44− attemptAutoComplete number $ \index ->
45− fst $ Chomp.chomp (Just index) chunks args_ flags_
46−
4744 ["--version"] ->
4845 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
4946 Exit.exitSuccess
@@ -53,12 +50,15 @@ simple details example args_ flags_ callback =
5350 Error.exitWithHelp Nothing details example args_ flags_
5451
5552 else
56− case snd $ Chomp.chomp Nothing chunks args_ flags_ of
57− Right (argsValue, flagValue) ->
58− callback argsValue flagValue
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
57+ Right (argsValue, flagValue) ->
58+ callback argsValue flagValue
5959
60− Left err ->
61− Error.exitWithError err
60+ Left err ->
61+ Error.exitWithError err
6262
6363
6464complex :: P.Doc -> P.Doc -> [Interface] -> IO ()
@@ -75,44 +75,79 @@ complex intro outro interfaces =
7575 do hPutStrLn stdout (Pkg.versionToString Compiler.version)
7676 Exit.exitSuccess
7777
78− "autocomplete" : number : chunks ->
79− attemptAutoComplete number $ \index ->
80− complexSuggest index chunks interfaces
81−
8278 command : chunks ->
83− case List.find (\iface -> toName iface == command) interfaces of
84− Nothing ->
85− Error.exitWithUnknown command (map toName interfaces)
79+ do maybeAutoComplete argStrings (complexSuggest interfaces)
80+ case List.find (\iface -> toName iface == command) interfaces of
81+ Nothing ->
82+ Error.exitWithUnknown command (map toName interfaces)
8683
87− Just (Interface _ _ details example args_ flags_ callback) ->
88− if elem "--help" chunks then
89− Error.exitWithHelp (Just command) details example args_ flags_
84+ Just (Interface _ _ details example args_ flags_ callback) ->
85+ if elem "--help" chunks then
86+ Error.exitWithHelp (Just command) details example args_ flags_
9087
91− else
92− case snd $ Chomp.chomp Nothing chunks args_ flags_ of
93− Right (argsValue, flagValue) ->
94− callback argsValue flagValue
88+ else
89+ case snd $ Chomp.chomp Nothing chunks args_ flags_ of
90+ Right (argsValue, flagValue) ->
91+ callback argsValue flagValue
9592
96− Left err ->
97− Error.exitWithError err
93+ Left err ->
94+ Error.exitWithError err
9895
9996
10097
10198-- AUTO-COMPLETE
10299
103100
104−attemptAutoComplete :: String -> (Int -> IO [String]) -> IO a
105−attemptAutoComplete number getSuggestions =
106− if all Char.isDigit number then
107− do suggestions <- getSuggestions (read number)
108− hPutStrLn stdout (List.intercalate " " suggestions)
109− Exit.exitSuccess
101+maybeAutoComplete :: [String] -> (Int -> [String] -> IO [String]) -> IO ()
102+maybeAutoComplete args getSuggestions =
103+ if length args /= 3 then
104+ return ()
110105 else
111− Exit.exitFailure
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)
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+ )
112137
113138
114−complexSuggest :: Int -> [String] -> [Interface] -> IO [String]
115−complexSuggest index strings interfaces =
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+
149+complexSuggest :: [Interface] -> Int -> [String] -> IO [String]
150+complexSuggest interfaces index strings =
116151 case strings of
117152 [] ->
118153 return (map toName interfaces)
@@ -120,7 +155,10 @@ complexSuggest index strings interfaces =
120155 command : chunks ->
121156 case List.find (\iface -> toName iface == command) interfaces of
122157 Nothing ->
123− return (map toName interfaces)
158+ if index == 1 then
159+ return (filter (List.isPrefixOf command) (map toName interfaces))
160+ else
161+ return []
124162
125163 Just (Interface _ _ _ _ args_ flags_ _) ->
126164 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
289327something more elaborate, you can implement a function like this yourself that
290328does whatever you need!
291329-}
292−suggestFiles :: [String] -> String -> IO [String]
293−suggestFiles extensions string =
330+_suggestFiles :: [String] -> String -> IO [String]
331+_suggestFiles extensions string =
294332 let
295333 (dir, start) =
296334 FP.splitFileName string