Search code examples
crystal-lang

ANSI escape code colored content truncated incorrectly when piped to `head`


Given the following file:

RED = "\e[0;31m"
RESET = "\e[0m"

content = [
  "01 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux",
  "02 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux",
  "03 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux",
  "04 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux",
  "05 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux",
].join("\n")

puts content.chars.map { |c| [RED, c, RESET].join }.join

When I run it then pipe it into head the output gets truncated part way though line 2. The same code works fine using Ruby.

Example:

$ crystal -v
Crystal 0.23.1 (2017-10-12) LLVM 4.0.1
$ crystal build test.cr && ./test | head -3
01 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux
02
$ ruby test.cr | head -3
01 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux
02 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux
03 foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux foo bar baz qux

How can I get this to behave like the Ruby version? I'm not sure if this is a bug in Crystal or if there is another way I should be outputting to STDOUT. Any help would be appreciated!


Solution

  • This issue is fixed in Crystal 0.25.0 and later, see https://github.com/crystal-lang/crystal/issues/2713 for a detailed discussion.

    I also ran the example on 0.25.1 and it works fine.