README: more examples of common use
I wanted to use ghcid for a long time, tried it a few times, but gave up. Couldn't make it work.
With help of @roberth I've managed to get it working today with stack and long-running daemon:
ghcid --command 'stack repl --no-nix-pure cachix-server:exe:cachix-server' --restart package.yaml --reload src --reload exe/cachix-server --test Main.main
I think having such examples for different tools would help someone get started.
Great you got it working, and I agree this example would be good. But first, I'd like to understand the pieces in that example, and see what's required and what is going what.
Restarting on package.yaml is something I'll add generally. See #205
Why do you need to --reload src? What's that doing? Shouldn't ghcid automatically reload on src changes, assuming they are .hs files?
What does no-nix-pure do? Will anyone ever want the reverse? Should I add it by default?
Specifying the name of the exe is needed if you have clashing module names. Not much I can do about that, so yep, that should be in an example.
Why do you need to --reload src? What's that doing? Shouldn't ghcid automatically reload on src changes, assuming they are .hs files?
That's what I thought, but it doesn't work for me. Can you explain (or point me to code/docs) how ghcid detects what files shall be monitored?
What does no-nix-pure do? Will anyone ever want the reverse? Should I add it by default?
In stack+nix integration, an environment is provided with nix-shell --pure, which gives you a shell with only libraries and binaries defined in stack.yaml. This is often not what one wants, so I'm using it here as precaution, but I'm not sure it should be enforced.
Specifying the name of the exe is needed if you have clashing module names. Not much I can do about that, so yep, that should be in an example.
An example and a few words why this is needed would help :)
Ghcid detects what to monitor by watching lines go past in ghci, e.g.
C:\Neil\hlint>ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
[ 1 of 54] Compiling HSE.Type ( src\HSE\Type.hs, interpreted )
[ 2 of 54] Compiling HSE.Util ( src\HSE\Util.hs, interpreted )
[ 3 of 54] Compiling HSE.Scope ( src\HSE\Scope.hs, interpreted )
It sees the src\HSE\Type.hs. When you load stack repl ... do you see those lines? If you run ghcid with --verbose it will tell you what it's watching.
The name of the exe is needed if Stack repl doesn't get the right binary, particularly if you have a test binary defining Main and an exe defining Main. I'll do the research to remember the details and included it in the manual.
That could be the issue, stack repl reuses compiled cache so it doesn't recompile the package from the beginning.
$ stack repl --no-nix-pure cachix-server:exe:cachix-server
The following GHC options are incompatible with GHCi and have not been passed to it: -threaded -O2
Configuring GHCi with the following packages: cachix-server
Using main module: 1. Package `cachix-server' component exe:cachix-server with main-is file: /home/ielectric/dev/cachix/cachix-server/exe/cachix-server/Main.hs
GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/ielectric/.ghci
[1 of 1] Compiling Main ( /home/ielectric/dev/cachix/cachix-server/exe/cachix-server/Main.hs, interpreted )
Ok, one module loaded.
Loaded GHCi configuration from /run/user/499/haskell-stack-ghci/61601d24/ghci-script
λ
Yep, if there is a way at that repl to list the modules loaded that would be good - what does :show modules or similar give? But ultimately if ghci only knows about one module, that's all ghcid knows about.
λ :show modules
Main ( /home/ielectric/dev/cachix/cachix-server/exe/cachix-server/Main.hs, interpreted )
Following does the trick: --main-is cachix-server:exe:cachix-server, but I need to figure out how to then invoke --test Main.main.
Another example of a "common use" is the following:
- Multiple package project: common, backend, frontend
- in common, use
ghcid --run=":!touch ghcid.success" - in backend and frontend, user
ghcid --restart="../common/ghcid.success"
Is a bit hacky of a solution, but works.
Also, the invocation for use with cabal new-build in multiple-package projects might be of interest:
ghcid -c"cabal new-repl $CABALPKGNAME" --restart "./$CABALPKGNAME.cabal"- might need
lib:orexe:prefix for the component specifier, or perhaps use.instead (all of those work, but hard to decide on best default..)
both use-cases assume that ghcid is in the package subfolder of the project.
Do you think this is worth documenting in the README?
stack repl --ghci-options=-fbyte-code works around the module detection problem. That problem can probably be reproduced in plain ghci with -fobject-code.
@lspitzner Does new-repl support loading multiple reloadable packages at once now? I am using stack repl now, which can do this. You can specify multiple package libs to load in a single ghci session, as long as the default-extensions of those packages are compatible.
ghcid --command "stack repl --load --ghci-options=-fbyte-code --no-nix-pure app-server:exe:app-server app-server:lib app-api:lib" \
--restart package.yaml \
--restart ../api/package.yaml \
--test Main.main \
;
- [x] multi-package
- [x] quick reloading
- [x] restarts when dependency is changed
- [x] single terminal window
- [x] no hacks (except what
stack repldoes internally to support this) - [ ] load arbitrary packages as reloadable (not supported by ghci, because of default-extensions etc)
- [ ] run more than one test suite at a time
I don't really need the latter two that much, so I'm quite happy with my setup.
I don't want to discuss/argue "correct/better setup" here. I think there are sufficiently many cabal new-build users to warrant having corresponding documentation.
(And as a general note, I think an opaque, internal hack is way worse than a transparent, self-imposed "hack", like the one I proposed above.)
@lspitzner I'm not here to argue either. Just contributing my setup. Looking back at my comment, the checkboxes my come across a bit weird. It's not a contest :). Your setup is more general; it works for all packages.
judging from https://github.com/haskell/cabal/issues/3659, I think the answer to "Does new-repl support loading multiple reloadable packages at once now?" is no.
Note that for the example above by @roberth you need to pass -W if you want the server to be ran. --test won't run if you have some warnings - and there's no warning about this :)
Actually this default in ghcid deserves credit for keeping warnings out of my code. A message on screen about this behavior would be great though. It confused me as well at first.