Open gelisam opened 11 years ago
I found the bug but I don't know how to fix it. Let me explain.
The output of Hawk
is produced by the function printRows
, that takes in input something that instantiate Rows
and print one line per row:
printRows :: forall a . (Rows a) => Bool -> a -> IO ()
printRows b = printRows_ . repr
where printRows_ [] = return ()
printRows_ (x:xs) = do
f x
handle ioExceptionsHandler (continue xs)
f = if b then handleErrors . C8.putStrLn else C8.putStrLn
continue xs = IO.hFlush IO.stdout >> printRows_ xs
ioExceptionsHandler e = case ioe_type e of
ResourceVanished -> return ()
_ -> IO.hPrint IO.stderr e
the function f
(I will change its name, I swear!) is in charge of printing a single row and it does it by using putStrLn
. So effectively there is a '\n' added to each row. But that's correct, because in this way you can write:
> hawk -e '[1,2,3]'
1
2
3
Now, if the expression to be printed out is a ByteString, Hawk
threats it like a single row. If that ByteString has at the end a newline, then it will be like using putStrLn
on "3\n2\n1\n":
ghci> P.putStrLn "3\n2\n1\n"
3
2
1
>
The right way to use Hawk
is to avoid the final unlines: why create a new string if you can print lists?
> seq 1 3 | hawk 'P.reverse . lines'
3
2
1
or as I prefer
seq 1 3 | hawk -d P.reverse
3
2
1
But apparently this is misleading. A hack/solution could be to check if the last character of a ByteString is a newline and ignore it. It is a hack but, again, this bug is hardcoded in the way Hawk
shows values.
Ah! Your explanation makes perfect sense, and guides me towards a more convenient use of the tool. Let's leave the "bug" unfixed and add your explanation as an FAQ. This way, users who encounter this will look it up, and return as better hawkers.
Or maybe alias unlines
to error "plase read the FAQ"
:)
I don't understand where the extra newline comes from.
In
hsl
, there was no spurious newline:Neither using
ghc -e
:Without looking at the code, I strongly suspect a
putStrLn
where aputStr
should be.