atom-haskell-archive / haskell-ghc-mod

haskell-ghc-mod atom package
https://atom.io/packages/haskell-ghc-mod
MIT License
69 stars 20 forks source link

Request: customizable ghc-mod command #160

Closed chris-martin closed 7 years ago

chris-martin commented 8 years ago

For my NixOS setup, I need to wrap commands in nix-shell, e.g. nix-shell --run 'ghc-mod check foo.hs --' instead of ghc-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.

chris-martin commented 8 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"
chris-martin commented 8 years ago

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.

lierdakil commented 8 years ago

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'.

chris-martin commented 8 years ago

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?

lierdakil commented 8 years ago

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.

lierdakil commented 7 years ago

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).

3noch commented 7 years ago

@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.

3noch commented 7 years ago

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

lierdakil commented 7 years ago

/cc @fresheyeball, I believe this might be relevant to the question you asked on #ghc-mod