Closed chris-martin closed 7 years ago
Workaround for other Nix users hitting this problem: I added this script which I've called ghc-mod-nix-shell
to my PATH
, then configured Atom to use ghc-mod-nix-shell
instead of ghc-mod
as the ghc-mod command.
#!/usr/bin/env bash
# Source .bashrc because this script is intended to be
# used by editors, e.g. Atom which doesn't source .bashrc,
# and we need NIX_PATH to be set correctly.
source ~/.bashrc
# Walk up the FS hierarchy until we find a shell.nix
while [ "$PWD" != "/" ] && [ ! -f shell.nix ]; do
cd .. echo "$PWD"
done
# If we didn't find a shell.nix, give up.
if [ "$PWD" = "/" ]; then
(>&2 echo "No shell.nix found")
exit 1
fi
# Arg list trick:
# https://stackoverflow.com/questions/3104209
ARGS=$(printf "%q"" " "$@")
# Run ghc-mod inside nix-shell
nix-shell --run "ghc-mod $ARGS"
The drawback to the approach I've taken so far is that it requires polluting PATH
with a wrapper for every program that might need to be run inside nix-shell (things other than ghc-mod
). I'd rather have a more generic wrapper, but this requires a little more flexibility in the way haskell-ghc-mod is configured.
Long story short, it's not that simple. There's a lot of commands, and those can be used in dfferent contexts (e.g. interactive/non-interactive). Adding customization to all of those is an overhead I'm personally not prepared to cope with, and I suspect most users aren't either.
What you could do in terms of simplification is create a directory e.g. ~/bin/nix-wrappers
, create a single script like this (say, nix-wrap
):
#!/usr/bin/env bash
# Source .bashrc because this script is intended to be
# used by editors, e.g. Atom which doesn't source .bashrc,
# and we need NIX_PATH to be set correctly.
source ~/.bashrc
# Walk up the FS hierarchy until we find a shell.nix
while [ "$PWD" != "/" ] && [ ! -f shell.nix ]; do
cd .. echo "$PWD"
done
# If we didn't find a shell.nix, give up.
if [ "$PWD" = "/" ]; then
(>&2 echo "No shell.nix found")
exit 1
fi
# Arg list trick:
# https://stackoverflow.com/questions/3104209
ARGS=$(printf "%q"" " "$@")
# get a filename this is executed with
execf="$(basename $0)"
mydir="$(dirname $0)"
# Remove this script's basedir from PATH
PATH=":$PATH:"
PATH=${PATH//:$mydir:/:}
PATH=${PATH#:}
PATH=${PATH%:}
# Just in case
export PATH
# Run $execf inside nix-shell
nix-shell --run "$execf $ARGS"
Then you could symlink nix-wrap
to ghc-mod
and whatnot (in the same directory or otherwise). Up to you if you want to add this dir to PATH or not, you could make due with adding that to 'Additional Path Directories'.
Thanks, good idea.
Maybe there's a way to make it a little more flexible without the difficulty of full generality? Like a extraGhcModArgs
setting that's a list of strings to be prepended to the arg list for all calls?
Depends on what "a little" is exactly. Arbitrary command line with argument substitution is kinda out of the question for a number of reasons. Configurable --with-ghc
etc is a possibility. Not sure if that would help any on NixOS though.
Okay, so I've implemented support for arbitrary ghc-mod options. See https://github.com/atom-haskell/haskell-ghc-mod#advanced-configuration. It's a little bit convoluted, but I didn't want to expose this in package settings directly; besides, per-project configuration may come in handy someday (which would be impossible with package settings).
@lierdakil @chris-martin If the failure case in nix-wrap
just runs the command as is, then you can just use symlinked versions of ghc-mod
, ghc-modi
, hlint
, cabal
, etc. for any project with or without nix.
I use this with Atom and it works well. I made some tweaks to allow running the command from the original directory but using the shell.nix file found in a parent.
https://gist.github.com/3noch/cb7c276c0b8d3e9d6f403c9a051fbf5c
/cc @fresheyeball, I believe this might be relevant to the question you asked on #ghc-mod
For my NixOS setup, I need to wrap commands in
nix-shell
, e.g.nix-shell --run 'ghc-mod check foo.hs --'
instead ofghc-mod check foo.hs --
. It would be very helpful if the commands that this plugin executes were customizable, rather than assuming they can be the same across all environments.