@@ -5,7 +5,7 @@ module Terminal.Args
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
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
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_
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_
53+ do maybeAutoComplete chunks $ \index cs ->
54+ fst $ Chomp.chomp (Just index) cs args_ flags_
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
60− Left err ->
60+ Left err ->
61− Error.exitWithError err
61+ Error.exitWithError err
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
78− "autocomplete" : number : chunks ->
79− attemptAutoComplete number $ \index ->
80− complexSuggest index chunks interfaces
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)
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_
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
96− Left err ->
93+ Left err ->
97− Error.exitWithError err
94+ Error.exitWithError err
101-- AUTO-COMPLETE
98-- AUTO-COMPLETE
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)
106+ do maybeLine <- Env.lookupEnv "COMP_LINE"
112+ do (index, chunks) <- getCompIndex line
113+ suggestions <- getSuggestions index chunks
114+ hPutStr stdout (unlines suggestions)
111− Exit.exitFailure
115+ Exit.exitFailure
118+getCompIndex :: String -> IO (Int, [String])
120+ do maybePoint <- Env.lookupEnv "COMP_POINT"
121+ case Read.readMaybe =<< maybePoint :: Maybe Int of
123+ do let chunks = words line
124+ return (length chunks, chunks)
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
134+ ( maybe (length rawChunks) id maybeIndex
135+ , map (map fst) rawChunks
139+grouper :: (Char, Int) -> (Char, Int) -> Bool
140+grouper (c1, _) (c2, _) =
141+ isSpace c1 == isSpace c2
144+isSpace :: Char -> Bool
146+ char == ' ' || char == '\t' || char == '\n'
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
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 ->
123− return (map toName interfaces)
159+ return (filter (List.isPrefixOf command) (map toName interfaces))
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!
292−suggestFiles :: [String] -> String -> IO [String]
330+_suggestFiles :: [String] -> String -> IO [String]
293−suggestFiles extensions string =
331+_suggestFiles extensions string =
295 (dir, start) =
333 (dir, start) =
296 FP.splitFileName string
334 FP.splitFileName string