Skip to content

Instantly share code, notes, and snippets.

@TK009
Last active August 18, 2016 11:06
Show Gist options
  • Select an option

  • Save TK009/9437d3928196d43714d9 to your computer and use it in GitHub Desktop.

Select an option

Save TK009/9437d3928196d43714d9 to your computer and use it in GitHub Desktop.
Add terminal colors to output messages of ghc, cabal, hlint, etc. This is just a fun little regex hackathon... so if someone likes this and wants to help improve or maintain it, leave comment below
#!/bin/perl -lp
# -w # Note: throws some warnings about using uninitialized vars
#
# Author: Tuomas Kinnunen
#
# Description: colorizes terminal output of some haskell tools: ghc, cabal, hlint
# This script comes without warranty of any kind. Bugs in this script might hide parts of compiler errors.
#
#
# Usage: pipe stdout and stderr to haskelltool-color
# e.g. put this in your ~/.bashrc or similar:
#
# cabal-color() {cabal "$@" 2>&1 | haskelltool-color}
# alias cabal=cabal-color
#
# ghc-color() {ghc "$@" 2>&1 | haskelltool-color}
# alias ghc=ghc-color
#
# hlint-color() {hlint "$@" 2>&1 | haskelltool-color}
# alias hlint=hlint-color
# TODO:
# ‘a’ is a rigid type variable bound by
# the type signature for
# ...
BEGIN {
#$Esc = "";
$Reset = "";
$BB = "";
$BE = "";
$Inv = "";
$Yellow = "";
$BYellow = "";
$Red = "";
$BRed = "";
$Cyan = "";
$BCyan = "";
$Blue = "";
$Green = "";
$LGreen = "";
$BGreen = "";
#$BBlue = "";
$BLila = "";
$Lila = "";
$BGGray = "";
$BGReset = "";
$TypeErr = "";
$LastExpected = ""; # for type errors (Expected: _ Actual: _)
}
{
# Mainly haskell error syntax highliting
# haskell errors; no "Error" string
s/^((?:[\w\/]*\.hs(?::[0-9]+)+:|<[^>]*>(?:(?::[0-9]+)+)?:))$/$Red$1/;
s/^((?:[\w\/]*\.hs(?::[0-9]+)+:|<[^>]*>(?:(?::[0-9]+)+)?:) (?![Ww]arning).*)$/$Red$1$Reset/; # "inline" next-line
s/^((?:[\w\/]*\.hs(?::[0-9]+)+:|<[^>]*>(?:(?::[0-9]+)+)?:) [Ww]arning.*)$/$Yellow$1/;
# fileline marker:
s/
(?|
((?:[\w_.-]*\/)*) # $1 (last) dirs
([\w_-]+) # $2 file,
(\.\w+:) # $3 extension,
|
(<) # $1
([^>]+) # $2, this is for unknown source errors: <interactive>:2:1
(>:) # $3
)
([0-9]+) # $4 line,
([:0-9-]*) # $5 column etc,
(.*)$ # $5 column etc,
/$1$BB$2$BE$3$BB$4$BE$5$BB$6/x;
# GHC error sentences
s/^(?|(\s*)(Deprecated:)|(\s*\w+)( is deprecated))(.*)$/$BCyan$1$BRed$2$BCyan$3$Reset/;
# experimental type error matching, FIXME
if (s/^[\s•]*(Expected )(type: )(.*)$/$BGreen$1$BE$Lila$2$BGreen$3/) {
my @words = split / /, $3;
my @rewords = map { "(?:" . quotemeta($_) . ")" } grep { $_ ne "" } @words;
#print @rewords;
$LastExpected = "(?:" . join('|', @rewords) . "| )+";
#print $LastExpected;
}
# Actual type, FIXME multiline (^\s*->)? Single line actual type?
if (s/^(\s*Actual )(type: )(?|(.*?)($LastExpected)()|()($LastExpected)(.*))$/$Reset$BRed$1$BE$Lila$2$TypeErr$3$Reset$LGreen$4$TypeErr$5$Reset$BYellow/) {
$LastExpected = "";
}
# "In" expr:
s/^[\s•]*
(In|When) # $1 In,
(\ \w+) # $2 a,an,the,
(
(?:(?!\ for|\ of|:)\ \w+)+
) # $3 thing,
(?| # branch numbering reset
(\ of\ a|\ of\ an|\ of\ the|\ of|\ for) # $4 of,for
(
(?:(?:\ [^ :‘’]+)+|\ (?:‘[^’]*’))
) # $5 what,
|
() # $4 empty
(‘[^’]*’) # $5 what,
)?
(,\ namely|:)? # $6 end
(.*)$ # $7 inline-next-line
/$Reset$Lila$1$Reset$Blue$2$BLila$3$Reset$Blue$4$BCyan$5$BE$Blue$6$Reset$7/x;
# ... use: ..., Use <Extension>, Probable cause:, Perhaps you (meant one of these|intended to use):\n
s/^([\s•]*(?:.*\W[Uu]se:|Use [\w.]+|Probable cause:|Perhaps you \w+|To avoid this|To \w+ \w+ use|Try |[(]maybe ))(.*)$/$BCyan$1$BE$Cyan$2/;
# possible fix: # FIXME: incoherent coloring? merge with above?
s/(Possible fix:)/$BGreen$1$BE$Cyan/;
# quoted names and expressions
s/(‘[^’]*’)/$BGGray$BB$1$BE$BGReset/g;
# reset haskell error color
s/^(\s*\()/$Reset$1/;
# "arising from _ of _" # add (type) at the end
s/(arising)(\ from)(\ a|\ an|\ the) # $1 $2 $3
(
(?:(?!\ for|\ of|:)\ \w+)+ # from In regex
) # $4 thing
(\ of|\ for)? # $5 of, for,
(
(?:(?!\ at)\ [^\ ]+)*
) # $6 what,
(\ (?:at\ ).*)?$ # $8 at? <end>
/$Lila$1$Blue$2$3$Lila$4$Blue$5$Cyan$6$Reset$8/x;
# at fileline
s/(\Wat)(.*)$/$BE$Green$1$2$Reset/;
# ghc Linking ...
s/^(Linking )([\w\/]*)( ...)/$Green$1$BB$2$BE$3$Reset\n/;
# hlint
s/(Found:)/$Yellow$BB$1$BE/;
s/(Why not:)/$LGreen$BB$1$Cyan/;
s/(No suggestions)/$LGreen$1$Reset/;
s/^([0-9]* suggestions?)$/$BYellow$1$Reset/;
s/^$/$Reset/;
# cabal
s/^(Resolving dependencies...)/$Lila$1$Reset/;
s/^(Downloading)( .*)$/$Blue$1$BE$Green$2$Reset/;
s/^(Configuring)( .*)$/$BLila$1$BE$Green$2$Reset/;
s/^(Building)( .*)$/$BGreen$1$BE$2$Reset/;
s/^(Installing)( .*)$/$BGreen$1$BE$2$Reset/;
# $1 phase, $2 executable/lib, $3 name, $4 for, $5 package
s/^(Preprocessing)( \w*)( '\w*')( for)(.*)$/$BGreen$1$Reset$Lila$2$BB$3$Reset$Blue$4$Green$5$Reset/;
# Compiling; $1 [, $2 i/_, $3 of, $4 _/n, $5 ], $6 Compiling, $7 module, $8 (from, to)
s/^(\[ *)([0-9]+)( of )([0-9]+)(\])(\sCompiling)( [\w.]*)(\s+.*)$/$Blue$1$BLila$2$BE$Blue$3$BLila$4$BE$Blue$5$BGreen$6$Cyan$7$BE$Blue$8$Reset/;
s/^(Updating)( documentation index)/$BLila$1$BE$2$Reset/;
s/^(Installed)(.*)/$Inv$BGreen$1$2$Reset/;
s/^(Failed to install)(.*)/$Inv$BRed$1$Reset$BRed$2$Reset/;
s/^(ExitFailure .*)$/$BRed$1$Reset/;
# cabal dependency errors
s/^(cabal:)( .*)$/$Red$1$2$Reset/;
s/^(trying:)(.*)$/$BYellow$1$Reset$2/;
s/(user goal)([)])$/$BLila$1$Reset$2/;
s/^(rejecting:)(.*)$/$BRed$1$Reset$2/;
s/([(])(conflict:)/$1$BRed$2$Reset/;
s/^(next goal:)/$Green$1$Reset/;
s/(dependency)( of)/$BLila$1$Reset$Blue$2$Reset/;
s/(=>)/$BLila$1$Reset/g;
s/(==|<=|>=|&& >|&& <)/$Blue$1$Reset/g;
# backjump; $1 thing, $2 limit reached, $3 (, $4 change, $5 with, $6 param
s/^(\w+ )(limit reached )([(])(change)( with)( --[-_\w]+)/$BRed$1$BE$2$Reset$3$BCyan$4$BE$Blue$5$BCyan$6$Reset/;
s/^(Dependency tree exhaustively searched.)/$Red$1$Reset/;
s/^(\s*(?:Note: .*$|Notice:))/$BCyan$1$Reset/;
# ghci
s/^(Ok, )(modules loaded:)(.*)$/$BGreen$1$BE$2$BB$3/;
# Generic compiler messages
s/^(\W*)([Ww]arning.*)$/$Yellow$1$BB$2/;
s/^(\W*)([Ee]rror.*)$/$Red$1$2$Reset/;
}
@TK009
Copy link
Author

TK009 commented Aug 18, 2016

This is just a fun little regex hackathon... so if someone likes this and wants to help improve or maintain it, leave a comment here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment