aboutsummaryrefslogtreecommitdiff
path: root/.vim/contrib/highlight-log
blob: c4697fd3418e1a83d2707d19180b27d63a5b18c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env bash

# This script adds color highlighting to the output from Neomake's Vader tests
# (when called with "vader"), or to the file that gets written into according
# to `neomake_logfile`.
#
# You can use the following to watch colored logs in a terminal window, after
# having used `let g:neomake_logfile = '/tmp/neomake.log'` in Neovim/Vim:
#
#     tail -f /tmp/neomake.log | /path/to/neomake/contrib/highlight-log

bold=""  # $(tput bold)
bold_off=""
debug_color=""  # $(tput dim), does not work in urxvt (although in infocmp/terminfo).
debug_color_off=""
color_off=""
log_color=""
log_color_off="$bold_off$color_off"
error_color=""
error_color_off="$bold_off$color_off"

# compact: display test headers, but not inner output for successful ones.
compact=0

while [ $# -ne 0 ]; do
    case $1 in
    --compact) compact=1; shift ;;
    --)  shift; break ;;
    -?*) echo "Unknown option: $1" 1>&2; exit 64 ;;
    *) break ;;
    esac
done

if [ "$1" = vader ]; then
  # Match non-log lines (i.e. keep output from :Log, which should cause
  # all messages from a case to be visible).
  # This should also ignore empty lines and lines starting with a character
  # (e.g. via NVIM_LOG_FILE:=/dev/stderr, and from :echom).
  re_log_line='^(.*(  )?    )(> .*)$'
  re_ignore_log_line='^.*(  )?    > \[(debug  |verbose|warning|error  )|((D|V|W|E) +\+[.0-9]+)\]'

  colorize() {
    # Only colorize if stdout is connected to a tty (not with :!make).
    if ! [ -t 1 ]; then
      cat -
      return
    fi

    # sed: add coloring to Vader's output:
    # 1. failures (includes pending) in red "(X)"
    # 2. test case header in bold "(2/2)"
    # 3. Neomake's error log messages
    # 4. Neomake's debug log messages
    # 5. non-Neomake log lines (e.g. from :Log)
    sed -E -e 's/^(([^ ].*)? +)\([ [:digit:]]+\/[[:digit:]]+\) \[[ [:alpha:]]+\] \(X\).*/'"$error_color"'\0'"$error_color_off"'/' \
      -e 's/^(([^ ].*)? +)(\([ [:digit:]]+\/[[:digit:]]+\))/\1'"$bold"'\3'"$bold_off"'/' \
      -e 's/^ +> \[(error  |E +[.[:digit:]]+)\]: .*/'"$bold"'\0'"$bold_off"'/' \
      -e 's/^ +> \[(debug  |D +[.[:digit:]]+)\]: .*/'"$debug_color"'\0'"$debug_color_off"'/' \
      -e '/'"$re_ignore_log_line"'/! s/'"$re_log_line"'/\1'"$log_color"'\3'"$log_color_off"'/'
  }

  if ((compact)); then
    # Do not display output for successful tests (i.e. the log statements).
    last_start_match=
    # Match Vader header ("( 1/33) [EXECUTE] …"), but also if there is output
    # from Vim, e.g. with ":colder".
    re_vader_header='^([^ ].*)?\ +(\(\ *[0-9]+/[0-9]+\))'
    filtering=0
    finished_reading=0
    stopped_filtering=0
    while [ "$finished_reading" = 0 ]; do
      if ! read -r; then
        if [ -z "$REPLY" ]; then
          break
          finished_reading=1
        fi
      fi
      if [[ "$REPLY" == *'Vader error:'* ]] || [[ "$REPLY" == 'Error'* ]] || [[ "$REPLY" == 'Traceback'* ]]; then
        printf "\r" >&2
        printf "%s\n" "$REPLY"
        continue
      fi
      if (( stopped_filtering )); then
        echo "$REPLY"
        continue
      fi
      if [[ "$REPLY" == *'Starting Vader:'* ]]; then
        echo "$REPLY"
      elif [[ "$REPLY" == '      Duration: '* ]]; then
        echo "$REPLY"
      elif [[ "$REPLY" == *'(X)'* ]]; then
        # Should also match "(1/1) [EXECUTE] (X) Error: Vim(function):E126: Missing :endfunction" already.
        if [[ -n "$filtered" ]]; then
          echo "$filtered"
        fi
        echo "$REPLY"
        filtered=
        filtering=0
      elif [[ "$REPLY" =~ $re_vader_header  ]]; then
        filtering=1
        if [[ ${BASH_REMATCH[2]} == "$last_start_match" ]]; then
          filtered="$filtered"$'\n'"$REPLY"
        else
          echo "$REPLY"
          filtered=
        fi
        last_start_match="${BASH_REMATCH[2]}"
      elif [[ "$REPLY" == *'Success/Total: '* || "$REPLY" == '  Slowest tests:' ]]; then
        echo "$REPLY"
        filtering=0
        filtered=
        stopped_filtering=1
      elif ! ((filtering)); then
        echo "$REPLY"
      elif [[ "$REPLY" =~ $re_log_line && ! "$REPLY" =~ $re_ignore_log_line ]]; then
        if [[ "$REPLY" =~ '> SKIP:' ]]; then
          echo "$REPLY"
          continue
        fi
        if [[ -n "$filtered" ]]; then
          echo "$filtered"
        fi
        echo "$REPLY"
        filtered=
        filtering=0
      elif [[ -n "$filtered" ]]; then
        filtered="$filtered"$'\n'"$REPLY"
      else
        filtered="$REPLY"
      fi
    done
  else
    cat -
  fi | colorize

else
  # Output from neomake_logfile.
  error='^[:[:digit:]]\+ \[E .*'
  warn='^[:[:digit:]]\+ \[W .*'
  debug='^[:[:digit:]]\+ \[D .*'
  sed -e "s/$error/\0/" \
      -e "s/$warn/w:\0/" \
      -e "s/$debug/$debug_color\\0$debug_color_off/"
fi