Last active
August 18, 2016 11:06
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 = "[0m"; | |
| $BB = "[1m"; | |
| $BE = "[22m"; | |
| $Inv = "[7m"; | |
| $Yellow = "[33m"; | |
| $BYellow = "[1;33m"; | |
| $Red = "[91m"; | |
| $BRed = "[1;31m"; | |
| $Cyan = "[96m"; | |
| $BCyan = "[1;96m"; | |
| $Blue = "[94m"; | |
| $Green = "[32m"; | |
| $LGreen = "[92m"; | |
| $BGreen = "[1;92m"; | |
| #$BBlue = "[1;94m"; | |
| $BLila = "[1;95m"; | |
| $Lila = "[95m"; | |
| $BGGray = "[100m"; | |
| $BGReset = "[49m"; | |
| $TypeErr = "[1;101;97m"; | |
| $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/; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.