File: ecoli.sh
   1 #!/bin/sh
   2 
   3 # The MIT License (MIT)
   4 #
   5 # Copyright © 2020-2025 pacman64
   6 #
   7 # Permission is hereby granted, free of charge, to any person obtaining a copy
   8 # of this software and associated documentation files (the “Software”), to deal
   9 # in the Software without restriction, including without limitation the rights
  10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 # copies of the Software, and to permit persons to whom the Software is
  12 # furnished to do so, subject to the following conditions:
  13 #
  14 # The above copyright notice and this permission notice shall be included in
  15 # all copies or substantial portions of the Software.
  16 #
  17 # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23 # SOFTWARE.
  24 
  25 
  26 # ecoli [regex/style pairs...]
  27 #
  28 # Expressions COloring LInes tries to match each line to the regexes given,
  29 # coloring/styling with the named-style associated to the first match, if
  30 # any.
  31 #
  32 # Lines not matching any regex stay verbatim.
  33 #
  34 # The colors/styles available are:
  35 #     blue
  36 #     bold
  37 #     gray
  38 #     green
  39 #     inverse
  40 #     magenta
  41 #     orange
  42 #     purple
  43 #     red
  44 #     underline
  45 #
  46 # Some style aliases are:
  47 #     b       blue
  48 #     g       green
  49 #     m       magenta
  50 #     o       orange
  51 #     p       purple
  52 #     r       red
  53 #     u       underline
  54 #     hi      inverse (highlight)
  55 
  56 
  57 case "$1" in
  58     -h|--h|-help|--help)
  59         awk '/^# +ecoli /, /^$/ { gsub(/^# ?/, ""); print }' "$0"
  60         exit 0
  61     ;;
  62 esac
  63 
  64 [ "$1" = "--" ] && shift
  65 
  66 if [ -p 1 ] || [ -t 1 ]; then
  67     command="stdbuf -oL awk"
  68 else
  69     command="awk"
  70 fi
  71 
  72 ${command} '
  73     BEGIN {
  74         # alias-lookup table
  75         a["r"] = "red"
  76         a["g"] = "green"
  77         a["b"] = "blue"
  78         a["o"] = "orange"
  79         a["p"] = "purple"
  80         a["m"] = "magenta"
  81         a["h"] = "invert"
  82         a["i"] = "invert"
  83         a["u"] = "underline"
  84         a["or"] = "orange"
  85         a["ma"] = "magenta"
  86         a["hi"] = "invert"
  87         a["in"] = "invert"
  88         a["un"] = "underline"
  89         a["inv"] = "invert"
  90         a["mag"] = "magenta"
  91         a["grey"] = "gray"
  92         a["inverse"] = "invert"
  93         a["inverted"] = "invert"
  94         a["hilite"] = "invert"
  95         a["hilited"] = "invert"
  96         a["highlight"] = "invert"
  97         a["highlighted"] = "invert"
  98         a["underlined"] = "underline"
  99         a["bb"] = "blueback"
 100         a["gb"] = "greenback"
 101         a["mb"] = "magentaback"
 102         a["ob"] = "orangeback"
 103         a["pb"] = "purpleback"
 104         a["rb"] = "redback"
 105         a["bg"] = "greenback"
 106         a["bm"] = "magentaback"
 107         a["bo"] = "orangeback"
 108         a["bp"] = "purpleback"
 109         a["br"] = "redback"
 110         a["bluebg"] = "blueback"
 111         a["graybg"] = "grayback"
 112         a["greenbg"] = "greenback"
 113         a["greyback"] = "grayback"
 114         a["greybg"] = "grayback"
 115         a["magentabg"] = "magentaback"
 116         a["orangebg"] = "orangeback"
 117         a["purplebg"] = "purpleback"
 118         a["redbg"] = "redback"
 119         a["magback"] = "magentaback"
 120         a["magbg"] = "magentaback"
 121         a["orback"] = "orangeback"
 122         a["orbg"] = "orangeback"
 123         a["purback"] = "purpleback"
 124         a["purbg"] = "purpleback"
 125 
 126         # style-lookup table
 127         s["red"] = "\x1b[38;2;204;0;0m"
 128         s["green"] = "\x1b[38;2;0;135;95m"
 129         s["blue"] = "\x1b[38;2;0;95;215m"
 130         s["orange"] = "\x1b[38;2;215;95;0m"
 131         s["purple"] = "\x1b[38;2;135;95;255m"
 132         s["magenta"] = "\x1b[38;2;215;0;255m"
 133         s["gray"] = "\x1b[38;2;168;168;168m"
 134         s["bold"] = "\x1b[1m"
 135         s["invert"] = "\x1b[7m"
 136         s["italic"] = "\x1b[3m"
 137         s["strike"] = "\x1b[9m"
 138         s["underline"] = "\x1b[4m"
 139         s["blueback"] = "\x1b[48;2;0;95;215m\x1b[38;2;238;238;238m"
 140         s["grayback"] = "\x1b[48;2;168;168;168m\x1b[38;2;238;238;238m"
 141         s["greenback"] = "\x1b[48;2;0;135;95m\x1b[38;2;238;238;238m"
 142         s["magentaback"] = "\x1b[48;2;215;0;255m\x1b[38;2;238;238;238m"
 143         s["orangeback"] = "\x1b[48;2;215;95;0m\x1b[38;2;238;238;238m"
 144         s["purpleback"] = "\x1b[48;2;135;95;255m\x1b[38;2;238;238;238m"
 145         s["redback"] = "\x1b[48;2;204;0;0m\x1b[38;2;238;238;238m"
 146 
 147         if (ARGC % 2 != 1) {
 148             printf "\x1b[31mmissing final style name\x1b[0m\n" > "/dev/stderr"
 149             exit 1
 150         }
 151 
 152         for (i = 1; i < ARGC; i++) {
 153             arg = ARGV[i]
 154             delete ARGV[i]
 155 
 156             if (i % 2 != 0) {
 157                 exprs[++n] = arg
 158                 continue
 159             }
 160 
 161             name = arg
 162             # resolve aliases
 163             if (a[name] != "") {
 164                 name = a[name]
 165             }
 166 
 167             if (s[name] == "") {
 168                 fmt = "\x1b[31mstyle/color %s not supported\x1b[0m\n"
 169                 printf(fmt, name) > "/dev/stderr"
 170                 exit 1
 171             }
 172 
 173             styles[n] = s[name]
 174             resetstyles[n] = "\x1b[0m" styles[n]
 175         }
 176     }
 177 
 178     {
 179         for (i = 1; i <= n; i++) {
 180             if ($0 ~ exprs[i]) {
 181                 gsub(/\x1b\[0m/, resetstyles[i])
 182                 printf "%s%s\x1b[0m\n", styles[i], $0
 183                 next
 184             }
 185         }
 186 
 187         print
 188     }
 189 ' "$@"