haskellcabal

How to run executables with cabal without any extra output?


When I use cabal run to run my programs I always get some extra noise in the output. For example:

Resolving dependencies...
Build profile: -w ghc-9.4.4 -O1
In order, the following will be built (use -v for more details):
 - output-test-0.1.0.0 (exe:output-test) (first run)
Configuring executable 'output-test' for output-test-0.1.0.0..
Preprocessing executable 'output-test' for output-test-0.1.0.0..
Building executable 'output-test' for output-test-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /private/tmp/output-test/dist-newstyle/build/x86_64-osx/ghc-9.4.4/output-test-0.1.0.0/x/output-test/build/output-test/output-test-tmp/Main.o )
[2 of 2] Linking /private/tmp/output-test/dist-newstyle/build/x86_64-osx/ghc-9.4.4/output-test-0.1.0.0/x/output-test/build/output-test/output-test

Or at best:

Up to date

Usually this isn't a big problem, but now I have an executable that generates output that I want to save to a file without this extra text. How can I do that? I can't find a --quiet option in the docs.


Solution

  • It used to be that there was no way, but these days a simple -v0 should suffice.

    Actually, I've found three defaults for run that are unfortunate, in my opinion:

    1. -v0 really ought to be default IMO
    2. The target selector really ought to default to exe:. (Perhaps it does these days? I haven't kept up with this issue.)
    3. Arguments ought to default to going to the executable being run, not to cabal.

    I have had the following script in my local bin to address these concerns for a while now, feel free to steal it. It adds exe: to the target unless there's already a : in the executable name, and it adds -- unless there already is one; these two escape hatches let you change the new default in exceptional circumstances (such as wanting to use v2-run with a test: selector or because you really do want to pass options to cabal).

    #!/bin/sh
    
    contains() {
        local needle="$1"
        while [ $# -gt 1 ]
        do
            shift
            if [ "$needle" = "$1" ]
            then
                return 0
            fi
        done
        return 1
    }
    
    executable="$1"
    shift
    if echo "$executable" | grep -q : >/dev/null
    then
        if contains -- "$@"
        then exec cabal v2-run "$executable" -v0 "$@"
        else exec cabal v2-run "$executable" -v0 -- "$@"
        fi
    else
        if contains -- "$@"
        then exec cabal v2-run exe:"$executable" -v0 "$@"
        else exec cabal v2-run exe:"$executable" -v0 -- "$@"
        fi
    fi