openbsd-dotfiles

Base configurations for my Openbsd desktop
git clone https://git.kausban.com/openbsd-dotfiles/raw/.git
Log | Files | Refs

sgrtab (6953B)


      1 #!/bin/sh
      2 # sgrtab - Display standard/custom table of SGR combinations (terminal colors)
      3 # Copyright 2017, Avi Halachmi  https://github.com/avih/sgrtab  License: MIT.
      4 
      5 if [ "$1" = '-h' ] || [ "$1" = '--help' ]; then
      6     echo "Usage: $(basename "$0") [[-g] G1..] [-m MODE] [-t TXT [-w W]] [-[xXyYzZ] S1..] ..."
      7     echo "Display terminal colors (SGR sequences) in various modes."
      8     echo "  MODE : table(default)/256/true/info"
      9     echo "  G1.. : Global individual SGR modifiers added to all table cells."
     10     echo
     11     echo "-m MODE or --MODE:"
     12     echo "  256  : 256 colors indexed palette (accepts -g, ignores others)."
     13     echo "  true : true-colors surface (accepts -[gt], ignores others)."
     14     echo "  info : attributes and their SGR codes (accepts -[gty], ignores others)."
     15     echo "  table: (default) display standard/custom table of terminal colors:"
     16     echo "   - The Z axis repeats each row with the different z values."
     17     echo "   - Default: X: 40-47 (bg colors), Y: 30-37 (fg), Z: -/1 (normal/bold)."
     18     echo
     19     echo "TXT   : Sample text. The default is ' gYw ', or ' ' with mode 'true'."
     20     echo "W     : On-screen width of txt (work around locale/alignment issues)."
     21     echo "S1..  : Axis SGR sequences. Use '-' as an empty sequence."
     22     echo "-[xyz]: S1 S2 ... are added to the axis. -[XYZ]: replace axis values."
     23     echo "Each cell uses an SGR sequence of: [x-seq][y-seq][z-seq][G1;G2...] ."
     24     echo "Example: $(basename "$0") -g 3 -y 7 '33;7' -X '- 2 4 48;5;40'"
     25     echo "         > global italic (3), two extra rows (-y), four columns (-X).";
     26     exit
     27 fi
     28 
     29 T=" gYw "
     30 X="- 40 41 42 43 44 45 46 47"
     31 Y="- 30 31 32 33 34 35 36 37"
     32 Z="- 1"
     33 G=     # global modifiers ("g1;g2...")
     34 W=     # on-screen text width. set if different than ${#T} e.g. maybe for UTF8
     35 ylen=2 # the widest y sequence, for row-headers alignment. considers ${#G} too
     36 zlen=2 # widest non-empty z +1, or 0 if empty (empty z headers are suppressed)
     37 mode=table  # table/256/true/info
     38 
     39 # for SGR. ignore empty or -* args, combine the rest with semicolon delimiter.
     40 # hot function. sets seq_out rather than printing from a (slow) subshell.
     41 seq_set() {
     42     seq_out=
     43     for c; do
     44         [ "${c##-*}" ] && seq_out="$seq_out;$c"
     45     done
     46     seq_out="${seq_out#;}"  # strip leading ';' from first concat
     47 }
     48 
     49 # from (CLI) args: possibly update T/W/G/X/Y/Z/ylen/zlen with minimal validation
     50 process_args() {
     51     ylen=0 zlen=0 state=g
     52     for a; do
     53         case $a in
     54         -[twgxyzm])
     55             state=${a#-}; continue;;
     56         -[XYZ])
     57             state=${a#-}; eval $state=; continue;;
     58         --table|--256|--true|--info)
     59             state=m; a=${a#??};;  # fall to the next case..esac
     60         esac
     61         case $state in
     62             t) T="$a";;
     63             w) W="$a";;
     64             g) G="$G $a";;
     65           x|X) X="$X $a";;
     66           y|Y) Y="$Y $a";;
     67           z|Z) Z="$Z $a";;
     68             m) mode=$a
     69                [ "$mode" = true ] && T=" "
     70                [ "$mode" = info ] && Y= ;;
     71         esac
     72         case $state in t|w|m) state=g; esac  # one arg, back to -g
     73     done
     74     case "$W$G$X$Y$Z" in *[!0-9\ \;-]*) echo Invalid arguments; exit 1; esac
     75     seq_set $G; G="$seq_out"
     76     has $X || X=-;  has $Y || [ $mode = info ] || Y=-;  has $Z || Z=-;  # be nice.
     77     for a in $Y; do [ ${#a} -gt $ylen ] && ylen=${#a}; done
     78     for a in $Z; do
     79         [ "${a##-*}" ] && [ ${#a} -ge $zlen ] && zlen=$((1 + ${#a}))
     80     done
     81     [ "$G" ] && [ ${#G} -gt $(($ylen + $zlen - 1)) ] && ylen=$((${#G} + 1 - $zlen))
     82 }
     83 
     84 # args: field width, text width, fmt, args... . pad pre/post spaces if shorter
     85 print_center() {
     86     [ $1 -le $2 ] && shift 2 && printf "$@" && return
     87 
     88     post=$(( ($1 - $2) / 2 ))  # post is smaller if non-even
     89     pre=$(( $1 - $post - $2 ))
     90     fmt="$3"; shift 3
     91     printf "%${pre}s$fmt%${post}s" "" "$@" ""
     92 }
     93 
     94 has() { [ $# -gt 0 ]; }
     95 print_row_header() { printf " %${ylen}s%${zlen}s" "$1" "${2##-*}"; }
     96 
     97 # -- main --
     98 has "$@" && process_args "$@"
     99 [ "$W" ] || W=${#T}
    100 echo() { printf %s\\n ${1+"$*"}; }
    101 
    102 case $mode in
    103 256) ESC=$(printf \\033)
    104     # $1: from, $2: len, $3: FG color sequence
    105     print_256_line() {
    106         i=$1 out=
    107         while [ $i -lt $(($1+$2)) ]; do
    108             case ${#i} in 1) pad="  ";; 2) pad=" ";; 3) pad=; esac
    109             out=$out"$ESC[$3m$ESC[48;5;${i}m${G:+$ESC[${G}m} $pad$i$ESC[m"
    110             i=$((i+1))
    111         done; echo "$out"
    112     }
    113 
    114     black="38;5;16"
    115     white="38;5;231"
    116 
    117     print_256_line 0 8 $black
    118     print_256_line 8 8 $black
    119     for from in 16 52 88 124 160 196 34 70 106 142 178 214; do
    120         case $from in 16|52|88|124|160|196) fg=$white;; *) fg=$black; esac
    121         print_256_line $from 18 $fg
    122     done
    123     print_256_line 232 12 $white
    124     print_256_line 244 12 $black
    125     ;;
    126 
    127 true) ESC=$(printf \\033)
    128     y=1
    129     while [ $y -le 16 ]; do
    130         x=1 out=
    131         while [ $x -le 64 ]; do
    132             top=$((256-y*16)); left=$((256-x*4)); bottomright=$((x*2+y*8-1))
    133             out=$out"$ESC[48;2;${top};${left};${bottomright}m${G:+$ESC[${G}m}$T$ESC[m"
    134             x=$((x+1))
    135         done; echo "$out"
    136         y=$((y+1))
    137     done
    138     ;;
    139 
    140 info) ESC=$(printf \\033)
    141     # $1: title, $2...: SGR code[s] to append
    142     print_var_line() {
    143         printf "%${ylen}s " "$1"; shift
    144         out=
    145         for x in - 30 31 32 33 34 35 36 37; do
    146             seq_set $* $x $G
    147             out=$out"$ESC[${seq_out}m$T$ESC[m"
    148         done; echo "$out"
    149     }
    150 
    151     # blink(5) and bright fg/bg (90-97,100-107) should be be used, so we don't
    152     ylen=28
    153     print_var_line "Normal"
    154     print_var_line "Bold (1)" 1
    155     print_var_line "Inverse (7)" 7
    156     print_var_line "Bold + Inverse (1;7)" "1;7"
    157     print_var_line "Italic (3)" 3
    158     print_var_line "Underline (4)" 4
    159     print_var_line "Crossed-out (9)" 9
    160     print_var_line "Dim (2)" 2
    161     print_var_line "Conceal (8)" 8
    162 
    163     v2q() { q=$(($1<48 ? 0 : $1<115 ? 1 : ($1-35)/40  )); }  # 0-255 -> 0-5
    164     printf "%${ylen}s " "256 colors (38/48;5;N)"
    165     i=0 out=
    166     while [ $i -lt 45 ]; do
    167         v2q $((255-i*5)); r=$q
    168         v2q $((20+i*5));  b=$q
    169         out=$out"$ESC[48;5;$((16 + 36*r + 6*0 + b))${G:+;$G}m $ESC[m"
    170         i=$((i+1))
    171     done; echo "$out"
    172 
    173     printf "%${ylen}s " "True colors (38/48;2;R;G;B)"
    174     i=0 out=
    175     while [ $i -lt 45 ]; do
    176         out=$out"$ESC[48;2;$((255-i*5));0;$((20+i*5))${G:+;$G}m $ESC[m"
    177         i=$((i+1))
    178     done; echo "$out"
    179 
    180     for y in $Y; do
    181         print_var_line "($y)" "$y"
    182     done
    183     ;;
    184 
    185 table)
    186     [ "$G" ] && printf " %$(($ylen + $zlen))s" "+$G" || print_row_header "" ""
    187     for x in $X; do
    188         print_center $W ${#x} " %s" $x  # headers line. center narrow headers
    189     done; echo
    190 
    191     for y in $Y; do
    192         for z in $Z; do
    193             print_row_header $y $z
    194             for x in $X; do
    195                 seq_set $x $y $z $G
    196                 print_center ${#x} $W " \033[%sm%s\033[m" "$seq_out" "$T"
    197             done; echo
    198         done
    199     done
    200     ;;
    201 
    202 *) >&2 printf "Invalid mode '%s'\n" "$mode"; exit 1
    203 esac