Stack: `stack ghcid` command

Created on 24 Mar 2016  Â·  19Comments  Â·  Source: commercialhaskell/stack

Seeing #1939 now I kind of want to do the same for ghcid (it's so good)

There has to be more convenience things we can wrap around, but first what comes to mind is something like:

$ STACK_YAML="foo/stack.yaml" stack ghcid stack:exe:stack --exec ':main --numeric-version'
# should be the same as
# ghcid --restart="foo/stack.yaml" \
#       --restart="stack.cabal" \
#       --restart="some-other-implicit-local?.cabal" \ # imagine multi-package project
#       --commad="stack ghci stack:exe:stack" \
#       --test=":main --numeric-version"

I find the name "ghcid" not so intuitive so most likely have an alias with a clear/friendly name, but it's benefits are worth it:
pretty much _dev workflow_ on steroids :muscle: and _close_ to "light speed" :zap:

I also really want to simplify stack's --help output and this is not contributing, but that is talk for another issue :joy: and..

I should really get around to getting the multi-package story sorted for #1364 to make this even faster for packages that require presence of autogen files

people not familiar with ghcid here are few short clips I show off what it can do

  • clip 1 servant server that restarts with new code loaded on valid file change:
  • clip 2 hspec + ghcid : rerun only tests that fail on valid file change:
  • another thing that I like doing during dev is ghcid --command="stack ghci" --test=":!stack build" (ghcid give me fast error feedback and only tell stack to build once it's "all good"[in ex. typechecks] :raised_hands: ) [great alternative to stack build --file-watch :ok_hand: ]

great work by @ndmitchell aka haskell tooling ninja and @reiddraper for showing this is possible in ordeal

Also, cljs/js we are coming! :turtle: :rocket:
First, I would :green_heart: it if @luite makes ghcjsi behave similarly to ghci :pray: (don't steal stderr :stuck_out_tongue: )

ghci enhancement

Most helpful comment

I've wanted stack ghcid enough times now that I'm fully in favor of adding it. Ideally the code would be pretty simple.

Would it be sensible to have stack ghcid do the monitoring of stack.yaml and kill + restart ghcid when it changes?

All 19 comments

sounds great to me!

also chuck in a --restart=package.yaml for those projects that have one :)

Cool idea! Perhaps it makes sense to do the integration fully within ghcid, though?

The reason is that if we want ghcid to handle adding / removing packages from the list, then it should also update its file watch. Perhaps stack should have a command to yield a list of files to watch?

I'm keen on whatever integration people want, and agree that shoving in ghcid could work too. I'm not against a special restart flag that uses a command or similar to figure out the restart files.

Yeah, I can imagine adding that as stack query local-cabal-files or something. So it'd be

    --restart=$STACK_YAML
    --restart-paths-command="stack --stack-yaml=$STACK_YAML query local-cabal-files" 
    --command="stack--stack-yaml=$STACK_YAML ghci stack:exe:stack"
    --test=":main --numeric-version"

Perhaps it makes sense to do the integration fully within ghcid, though?

Yes, and myself I'm more of a custom script tailored to my project (hello shake another tool that deserves more love)

but... here I go!â„¢

My "secret" reason I didn't explicitly mention was exposure/discovery strategy. Stack has more reach and I want to introduce to people how much better development experience can be. I'm gonna pick on ghcid a bit, but this is something I see in other haskell libs/tools in general and it just happens that most of the ones I use come from the same tooling ninja. Search results for ghcid are not revealing and the post on first page of results requires familiarity with ghci and actually using it to truly value it, which repulses a good chunk of the audience.

Ghcid has got to have more users than just the author. My sample size away-from-keyboard and online is small, and even though I follow some "popular folks"(based of follower reach), ghcid plug is null. The few that know, link me to/or where is the cool blog post or nice & short attractive video? (I take blame on this one too :joy:)

Other langs are great at selling their stuff and imo ghcid and haskell are undervalued. Case in point, text only content is not sexy/engaging for everyone. It can be better :)

I have a goal dream!

I envision stack as a tool with great integration to other awesome tools(ghcid, hoogle, etc.) making stack look even more powerful :muscle:, but with clear commands that hide the underlying actions taken until I need to dive in.

I want to delay having to think what is going on under the hood as much as I can or not even have to. If we use this lang it has to be in part because we value writing at a higher level so lets do the same in tooling

For example:
$ stack doc --search "t a -> a"
Just :: a -> Maybe a
head :: [a] -> a
last :: [a] -> a

# Install hoogle or any missing tool and run any command you need
# - I don't want to think about what is going on!
#   Just give me search results from the start!
#     If I really want to know and tweak something 
#       - I look at documentation
#       - also be able to run in verbose mode and take it from there
#         in case default is not enough


$ stack doc --source Stack.Build.Execute.printPlan
# opens my browser to the source location of `printPlan`

# - I don't want to think that I have to do
#   or install haddock from git + recent cabal to get --hyperlinked-source 
#   or run some command scattered across reddit/stack-overflow/irc/twitter/tinder?
# - notice `doc` instead of `haddocks` as an alias
#     let's make intention clear and hide the details
# - did I say how much I love _choose_your_name_=[eyecandy:ux:ui], yet?


$ stack repl --awesome-dev-feedback   
# boom no --help pollution - name suggestions? 
# point being, I don't want to think that it is actually using ghcid.
# I just want a great experience from scratch


### so much more, but for other issues.

Hey why does hoogle receive first class upgrade? #1939 :eyes:
Let's not get coach and aisle - equality! _jk_
At least let's get extra leg room - plugin interface?
Keep in mind, it's about maintaining a wrapper rather than specific functionality

Speculation of adoption

I don't have numbers but similar to how goog/instagram/fb add some delays and loose a big chunk of users I feel like missing eyecandy and engaging material on beast tools we have got to be loosing potential users that can contribute something back!

It's easier to sell to people install x and run x y than install x y z and run x; y; x --hey; x --y # oh and make sure you don't trigger z's heuristics by rm'in dir/
At that point, I already lost someone to convince how much they can gain

Perhaps, I should use more buzzwords in the title to reach more people.
Something like hot module loading, reloadeble code, time travel
Keep in mind, this is all just meant for dev and funs
jokes aside, I want to explore more of this but ping @luite :stuck_out_tongue: and show you're interested (because I want to target browsers too)

Who is pumped? _crickets_
We have some pretty cool tools. Let's start captivating :+1:

how much do I value eyecandy/ui/ux?

Also, cljs/js we are coming! :turtle: :rocket:
First, I would :green_heart: it if @luite makes ghcjsi behave similarly to ghci :pray: (don't steal stderr :stuck_out_tongue: )

Oh the current behaviour is a bit of a temp hack, since it lets GHCJSi use the existing pipes to the node.js interpreter. I'll change this at some point (or accept pull reqs!)

@luigy Good ideas! I've enjoyed using ghcid a bit lately. I agree that it makes sense to have stack be a general swiss army knife of Haskell. However, at once, we've got to be careful about not jamming in too many features and making things complicated. This is why I didn't want to implement something like ghcid inside stack itself.

If someone wants to champion an idea like this (such as yourself!), and implement and maintain it, then I'm all for it!

I would like to keep the complexity in ghcid as much as possible, ideally the stack bit would just be knowing how to install it and how to invoke it. We definitely need more thought on how to run ghci-like tools - I'd have liked to have merged something like https://github.com/commercialhaskell/stack/pull/1737 but it didn't seem like the right change.

I agree with @mgsloan - as much inside ghcid makes sense, and then use stack for just the final integration that ghcid couldn't figure out on its own plus advertising.

One note @luigy - I suggest by default you don't pass anything as --test. If you avoid having a --test then you aren't making the assumption the tool has command line arguments of the typical form, and then ghcid can use -fno-code, which makes loading faster. If you can find a useful and productive --test default it would be a different matter.

I've wanted stack ghcid enough times now that I'm fully in favor of adding it. Ideally the code would be pretty simple.

Would it be sensible to have stack ghcid do the monitoring of stack.yaml and kill + restart ghcid when it changes?

I'd rather that Stack wasn't monitoring anything. So the reason that we need Stack involved is because a different stack.yaml might induce a different set of --restart flags. I think an easier way to solve that would be for ghcid to watch stack.yaml with --restart and when it reruns stack ghci you could imagine stack printing out as it started GHCID-RESTART=filename lines which ghcid could watch for add add to a dynamic --restart list. That way only ghcid is doing file watching, and stack doesn't have to try killing it.

Note that if stack had a mode where it printed those lines, and ghcid knew the flag to ask it to do so, I would expect stack ghcid and ghcid to do approximately the same thing (although perhaps with stack ghcid installing ghcid first).

@ndmitchell Cool, sounds good! In that case, the code in stack to invoke ghcid should have very little complexity. So it could either be builtin or added as some stack-ghcid plugin which invokes ghcid correctly.

Ok, I'll fix the existing Stack/Ghcid bugs (there are 2) and we can see what more is required.

So there are two features that would be very useful to get better Stack/Ghcid integration before going as far as stack ghcid:

  • A flag to avoid asking "which project do you want to load" when running stack ghci - discussed at https://github.com/ndmitchell/ghcid/issues/57. There are workarounds, but they are horrible, and potentially fragile.
  • A flag to make stack print out some identifiable prefix and the extra files to watch, e.g. .cabal files. Something like HEY GHCID I GOT A FILE FOR YOU: a.cabal.

Opened https://github.com/commercialhaskell/stack/issues/2069

A flag to make stack print out some identifiable prefix and the extra files to watch, e.g. .cabal files. Something like HEY GHCID I GOT A FILE FOR YOU: a.cabal.

Not sure how straightforward this would be. Currently we pass full control over to the ghci process. Maybe it would be possible to do this in a separate process? Could get tricky to integrate with the stuff that parses out ddump-hi info to catch the cases where there are deps not mentioned in the cabal file. Feel free to open a discussion issue about it.

No news on this? 😢

@ChrisPenner - I just type ghcid and it generally does the right thing, since it can already detect stack projects, and it's fairly easy to tweak if you need more. If you think there's something just typing ghcid doesn't do right, perhaps raise that on the ghcid bug tracker? https://github.com/ndmitchell/ghcid/issues

  • A flag to avoid asking "which project do you want to load" when running stack ghci - discussed at ndmitchell/ghcid#57. There are workarounds, but they are horrible, and potentially fragile.

Should that issue be reopened? Having to make a manual selection each time your start GHCi in project with multiple executables is very jarring.

I'm quite pleased with ghcid+stack setup, but there's one thing bugging me. If I'm developing also a dependency on my main project, ghcid doesn't reload it.

My command line is ghcid --command 'stack repl --load --ghci-options=-fbyte-code --no-nix-pure cachix-server:lib cachix-server:exe:cachix-server' --restart cachix-server.cabal --restart stack.yaml -W --test Main.main

I can add --load-local-deps but then I hit the problem where ghci loads all dependencies without implicit prelude and thus fails. Is there a good known workaround for this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

symbiont-joseph-kachmar picture symbiont-joseph-kachmar  Â·  3Comments

mgsloan picture mgsloan  Â·  3Comments

domenkozar picture domenkozar  Â·  3Comments

abhinav picture abhinav  Â·  4Comments

srghma picture srghma  Â·  3Comments