Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add completions to REPL #407

Merged
merged 7 commits into from
Jan 4, 2021
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/dex.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import System.Posix.Terminal (queryTerminal)
import System.Posix.IO (stdOutput)
import System.Exit
import System.Directory
import Data.List

import Syntax
import PPrint
Expand All @@ -25,6 +26,7 @@ import Resources
import TopLevel
import Parser hiding (Parser)
import LiveOutput
import Env (envNames)
import Export

data ErrorHandling = HaltOnErr | ContinueOnErr
Expand All @@ -45,8 +47,10 @@ runMode evalMode preludeFile opts = do
env <- cached "prelude" key $ evalPrelude opts preludeFile
let runEnv m = evalStateT m env
case evalMode of
ReplMode prompt ->
runEnv $ runInputT defaultSettings $ forever (replLoop prompt opts)
ReplMode prompt -> do
let filenameAndDexCompletions = completeQuotedWord (Just '\\') "\"'" listFiles dexCompletions
let hasklineSettings = setComplete filenameAndDexCompletions defaultSettings
runEnv $ runInputT hasklineSettings $ forever (replLoop prompt opts)
ScriptMode fname fmt _ -> do
results <- runEnv $ evalFile opts fname
printLitProg fmt results
Expand Down Expand Up @@ -81,6 +85,19 @@ replLoop prompt opts = do
_ -> return ()
liftIO $ putStrLn $ pprint result

dexCompletions :: CompletionFunc (StateT TopEnv IO)
dexCompletions (line, _) = do
env <- get
let varNames = map pprint $ envNames env
-- note: line and thus word and rest have character order reversed
let (word, rest) = break (== ' ') line
let anywhereKeywords = ["def", "for", "rof", "case", "data", "where", "of", "if", "then", "else", "interface", "instance", "do", "view"]
let startoflineKeywords = ["%bench \"", ":p", ":t", ":html", ":export"]
let candidates = varNames ++ anywhereKeywords ++
if null rest then startoflineKeywords else []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite minor, but ++ has complexity proportional to the size of the lhs, so it is usually better to sort the concatenated lists according to increasing length. This concatenates them in the complete reverse order, which is the worst case scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL, it's an actual linked list i guess

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, Haskell lists are linked lists. If you want a contiguous arrays you have to use Data.Vector (which is a packed array of boxed values; if you want to go unboxed there are Data.Vector.Unboxed types).

let completions = map simpleCompletion $ filter ((reverse word) `isPrefixOf`) candidates
return (rest, completions)

liftErrIO :: MonadIO m => Except a -> m a
liftErrIO (Left err) = liftIO $ putStrLn (pprint err) >> exitFailure
liftErrIO (Right x) = return x
Expand Down