Ghcitty: a fast, friendly GHCi ... Syntax highlighting, tab+ghost completions, easy multiline, Vi-mode, Hoogle integration, etc (Looking for feedback!)

Hello all - been tinkering on ghcitty (a small Rust wrapper around GHCi)

It should be about ready for sea-trials by others.

Would love your veteran feedback (any commands that feel off when wrapped? … any multiline weirdness?)

r/haskell - ghcitty: a fast, friendly GHCi 🐈⚡ Syntax highlighting, tab+ghost completions, easy multiline, Vi-mode, Hoogle integration, etc (Looking for feedback!)

15 Likes

This looks like a cutesy little utility, thanks for sharing! I’m installing it as I type, and will provide feedback in time.

I’ll ask the expected question: Is there a reason (other than familiarity or ecosystem, which is perfectly valid!) that the project is in Rust as opposed to Haskell?

3 Likes

Hello hello! Thanks for taking a peek :man_bowing:

for why Rust, honestly ease of :

  1. standing up a v1 (its built on top of nushell’s reedline)
  2. having a easy to distribute binary

in the background am whittling away on implementing some of the reedline niceties in raw Haskell… but will take some more time

2 Likes

What problems have you faced with distributing Haskell binaries? I’ve been doing this with my own projects for some time and I’m interested in your experience.

4 Likes

Hello! Problems is maybe not the word I’d use … but definitely have had to do some incantations with musl GHC, alpine and static-nix

tbf … #1 above / the reedline niceties were definitely the main consideration here for v1)

2 Likes

My requests:
I’d like support for Option+tab/Command+tab/Ctrl+tab for navigating the command line. As far as I can tell, only normal arrow keys are supported. This is probably one of the only things keeping me from using this fully.

When GHC suggests enabling an extension/flag, having an option to just auto enable it would be cool. e.g.

Proxy :: Proxy [2,3]

GHC will error and suggest enabling DataKinds. It would be nice if I had the option of saying :set -XDataKinds or :seti -XDataKinds.

When there’s only one option for auto-complete, and it’s getting ghost-completed, tab maybe should auto complete. e.g. -XAllowAmb\t should become -XAllowAmbiguousTypes.

It would be nice if λ> fib :: Int would prompt for the definition of fib. I could see a command, :fun or something allowing for this. e.g. λ>:fun fib :: Int, or :sig would just mean prompt for more text, and wait until two newlines were finished. I like this more than :{ }: because it’s two less lines, and also feels more like writing Haskell in a .hs file.

Less opinionated notes/issues:
:! has some problems. Firstly :! ls will try and do syntax highlighting on the files. I’m not sure what to do about that. On one hand, cat X.hs maybe should be highlighted, but :! ls shouldn’t be. A graver issue though is that when I did :! cat app/Main.hs, it just hung. Is :! fully supported for large strings? (:! less app/Main.hs) hung as well.

I think ^C should stop the subprocess first, then ghctty. e.g.

λ> :{
   fib 0 = 0
   fib 1 = 1
   fib n = fib (n-1) + fib (n-2)
   :}
fib :: (Eq t1, Num t1, Num t2) => t1 -> t2
λ> fib 1000
^C

Should only end the inner process, not the outer one. Also, if you want to model GHCI , then ^Z should quit ghcitty.

As far as I can tell, when the process ends with ^C currently, history isn’t saved. e.g.

λ> <complex expr>
λ> <hanging expr>
^C 

<complex expr> never gets added to history.

:set editor only lasts one session, but I think people usually only use 1 editor. Maybe it should be persistent?

Thank you so much for this tool, it’s really quite amazing and I really appreciate it! Don’t feel pressured by this.

3 Likes

beauty - tysm for taking a peek! love this auto suggest of missing extension flags and this :fun style syntax for function definition (gonna mull over the latter but chef’s kiss directionally)

Think I got everything captured in the issues (but feel free to add)

2 Likes

I think you missed the history bug. (It doesn’t save when exited with ^C) Also ^Z maybe should quit to be like GHCI. There’s also auto enabling of GHC flags.
I think you have everything else, but its fine if you don’t implement most of them. If even only #7 and #4 were fixed, I think I’d always use it instead of GHCI. Even without that, I’ll probably still use this a lot.

1 Like

Related to navigation there’s also ctrl+backspace/option+delete, for deleting words. If you got full compatibility with GHCI in those, I think ghcitty would be undoubtedly superior.

1 Like

Circling back on tab completion behaviour I see 3 options

  1. Option 1 (disambiguate by candidate count) … 1 candidate accepts … >2 candidates opens menu like today
  2. Option 2 (split keys) … always opens menu… at end-of-line accepts the ghost
  3. Option 3 (double tap) accepts ghost… opens menu

Leaning towards and Option 1 + Option 2 hybrid..

  • SINGLE cadidate accepts (multiple candidate opens menu)
  • accepts ghost as an always available alternative

But lmk what you think :man_bowing:

scooped these fixes up in 0.2.0

fresh ghcitty binary is on crates (link)

Tysm for the eagle eye and taking this for a spin!

3 Likes

@mattlianje How to pass cabal options and stack options, like --allow-newer?

1 Like

Added support for this just now w/ 0.3.0 ! ty for all the good catches and suggestions

We can now just do:

ghcitty -- --allow-newer
3 Likes