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

Conversation

oxinabox
Copy link
Contributor

@oxinabox oxinabox commented Jan 3, 2021

This adds completions to the REPL, both of language keywords and of currently defined top level names;
as well as restricting filename completions to only happen within a quoted string.

Shown is me pressing tab at the end of each line.

image

A follow up PR would add globally inscope variables to this. I think it would not be too hard, though I don't think I will work out out anytime soon. There is discussion in [this Reddit thread](https://www.reddit.com/r/haskell/comments/1os0yq/haskeline_woes/) about how to dynamically update the list of completions for Haskline

It also would be good to add other things like :p and :html filtered to only be allowed occur at line start

@google-cla google-cla bot added the cla: yes label Jan 3, 2021
@oxinabox
Copy link
Contributor Author

oxinabox commented Jan 3, 2021

I added :p, :t etc, though they think they can occur anywhere in the line right now,
and %bench " though that inserts an extra space afterwards that it shouldn't.
I think still better to have than not, though I am going to play around to see if i can do them right.

@oxinabox
Copy link
Contributor Author

oxinabox commented Jan 3, 2021

Apparently it is impossible not to inser the after %bench "
haskell/haskeline#151

but I did sort out :p etc needing to be at start of line.

@oxinabox oxinabox changed the title Add keyword completions Add completions to REPL Jan 3, 2021
@oxinabox
Copy link
Contributor Author

oxinabox commented Jan 3, 2021

I worked out how to make global names work in general
I am so satistified.
I mean this is probably the worst haskell ever but still its by far the most complex i ever wrote.

Screenshot 2021-01-03 at 21 10 01

I guess there are some names we want to somehow filter out, like showInt32

src/dex.hs Outdated
else []
return (rest, filteredCompletions candidates $ reverse word)

dexCompletions = completeQuotedWord (Just '\\') "\"'" listFiles completions
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably all of the above should be in another file. idk where though

src/dex.hs Outdated
env <- get
let varNames = map (show . pretty) $ envNames env
-- note: line and thus word and rest have character order reversed
let (word, rest) = break (== ' ') line
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Possibly other whitespace should be allowed

Copy link
Collaborator

@apaszke apaszke left a comment

Choose a reason for hiding this comment

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

Nice, this looks sweet!

src/dex.hs Outdated
dexCompletions = completeQuotedWord (Just '\\') "\"'" listFiles completions

hasklineSettings :: Settings (StateT TopEnv IO)
hasklineSettings = setComplete dexCompletions defaultSettings
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: small local definitions like this one (or dexCompletions) are usually better placed in the where clauses of the functions that use them (in this caserunMode).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems like if i do that it is too far away from where it is used.
So I have put it side that ReplMode case

@apaszke
Copy link
Collaborator

apaszke commented Jan 4, 2021

Let's just clean up the formatting a little and this is going to be good to merge!

src/dex.hs Outdated
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).

@apaszke apaszke merged commit 66d225f into google-research:main Jan 4, 2021
@oxinabox oxinabox deleted the ox/complete branch January 4, 2021 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants