diff --git a/reporting/highbeam b/reporting/highbeam index b82f4aa..14c6a81 100755 --- a/reporting/highbeam +++ b/reporting/highbeam @@ -1,161 +1,106 @@ -#!/bin/bash +#!/usr/bin/env python3 -function usage { -echo -e ' High Beam Highlighter -- a trial to create a very generic modifyable -syntax highlighter. - -Example rules: ( ~/.highbeamrc ) --------------------- -RULES=( - "[0-9]" "$c" # Show numbers with Cyan color. NOTE: since the colors are represented with numbers, having this later in the rules will break coloring! - "$USER[ ]\+$USER" "$BC$K" # Use quotes to have rules with spaces. This colors the "ls -la" usernames. background cyan, black text - status "$g" # simple word matching, coloring green - "^d[^ ]*" "$G" # color words at the beginning of line, starting with d. color bright green - "q.\{0,3\}r" "$Y" # q*r with maximum 3 characters in between. color bright yellow -) --------------------- -Rules can be also exressed as a space separated list variable: -export HB_RULES='\''"[0-9]" "$C" "g" "$Y"'\'' - HB_RULES are appended to other rules - -Bright colors: $R $G $B $Y $M $C $W $K -Dark colors: $r $g $b $y $m $c $w $k -Modify to bright version by prefixing with $H (e.g. $H$g) -Background colors: $BR $BG $BB $BY $BC $BM $BW -Underline: $U - -Usage: highbeam [-c] [-h] [-f config] - -c Be case sensitive - -D Print current rules, not the input - -s Simple highlight a string (as argument) - -h Help - -f Define config file (default ~/.highbeamrc) - -r Define rules with a string, replaces the other rules - -r '\''"land[^[:space:]]\+" "$G" "sky" "$B"'\'' - -' +import argparse +import json +import os +import re +import sys +import time +# Define color codes +E = "\x1b[" +colors = { + "K": f"{E}1;30m", + "R": f"{E}1;31m", + "G": f"{E}1;32m", + "B": f"{E}1;34m", + "Y": f"{E}1;33m", + "M": f"{E}1;35m", + "C": f"{E}1;36m", + "W": f"{E}1;37m", + "k": f"{E}30m", + "r": f"{E}31m", + "g": f"{E}32m", + "b": f"{E}34m", + "y": f"{E}33m", + "m": f"{E}35m", + "c": f"{E}36m", + "w": f"{E}37m", + "u": f"{E}4m", + "U": f"{E}4m", + "Z": f"{E}0m", + "BK": f"{E}40m", + "BR": f"{E}41m", + "BG": f"{E}42m", + "BB": f"{E}44m", + "BY": f"{E}43m", + "BM": f"{E}45m", + "BC": f"{E}46m", + "BW": f"{E}47m", } - -E='\x1b[' -H="${E}1m" -Z="${E}0m" - -# list of text colors: -K="${E}1;30m" -R="${E}1;31m" -G="${E}1;32m" -B="${E}1;34m" -Y="${E}1;33m" -M="${E}1;35m" -C="${E}1;36m" -W="${E}1;37m" -k="${E}30m" -r="${E}31m" -g="${E}32m" -b="${E}34m" -y="${E}33m" -m="${E}35m" -c="${E}36m" -w="${E}37m" - -# list of BG colors: -BR="${E}41m" -BG="${E}42m" -BB="${E}44m" -BY="${E}43m" -BM="${E}45m" -BC="${E}46m" -BW="${E}47m" - -# lines -U="${E}4m" - -CONF_FILE=~/.highbeamrc -CONF_LINE="" -FLAGS="ig" -PRINT=0 -while getopts chf:r:s:D opt -do case "$opt" in - c) - FLAGS="g" - ;; - h) - usage - exit - ;; - f) - CONF_FILE=$OPTARG - ;; - r) - CONF_LINE=( $( eval echo $OPTARG ) ) - ;; - s) - HB_RULES='"'"$OPTARG"'" "$U$Y"' exec "$0" - exit $? - ;; - D) - PRINT=1 - ;; - esac -done - -[[ -z "$CONF_LINE" ]] && { - # user rules: - [[ -e "${CONF_FILE}" ]] && { - . "${CONF_FILE}" || { - echo You may have wrong format in "${CONF_FILE}" >&2 - usage >&2 - exit 1 - } - } - for (( rIndex=0; rIndex<${#RULES[@]}; rIndex++ )); - do REGEX="$REGEX -e 's/\(${RULES[$rIndex]}\)/${RULES[$(( $rIndex + 1 ))]}\1${Z}/${FLAGS}'" - rIndex=$(( $rIndex + 1 )) - done -} || { - # string fed rules - for (( rIndex=0; rIndex<${#CONF_LINE[@]}; rIndex++ )); - do REGEX="$REGEX -e 's/\(${CONF_LINE[$rIndex]}\)/${CONF_LINE[$(( $rIndex + 1 ))]}\1${Z}/${FLAGS}'" - rIndex=$(( $rIndex + 1 )) - done -} -# env variable fed rules -[[ -z "$HB_RULES" ]] || { - CONF_ENV=( $( eval echo "$HB_RULES" ) ) - for (( rIndex=0; rIndex<${#CONF_ENV[@]}; rIndex++ )); - do REGEX="$REGEX -e 's/\(${CONF_ENV[$rIndex]}\)/${CONF_ENV[$(( $rIndex + 1 ))]}\1${Z}/${FLAGS}'" - rIndex=$(( $rIndex + 1 )) - done -} -[[ $PRINT -eq 1 ]] && { - echo "From $CONF_FILE:" - for (( rIndex=0; rIndex<${#RULES[@]}; rIndex++ )); - do printf "%s\\t%s" "${RULES[$rIndex]}" "${RULES[$(( $rIndex + 1 ))]}" - rIndex=$(( $rIndex + 1 )) - done - echo "From argument switches:" - for (( rIndex=0; rIndex<${#CONF_LINE[@]}; rIndex++ )); - do printf "%s\\t%s" "${CONF_LINE[$rIndex]}" "${CONF_LINE[$(( $rIndex + 1 ))]}" - rIndex=$(( $rIndex + 1 )) - done - echo "From HB_RULES environment:" - for (( rIndex=0; rIndex<${#CONF_ENV[@]}; rIndex++ )); - do printf "%s\\t%s" "${CONF_ENV[$rIndex]}" "${CONF_ENV[$(( $rIndex + 1 ))]}" - rIndex=$(( $rIndex + 1 )) - done -#~ echo ${CONF_ENV[@]} -#~ echo $HB_RULES -#~ echo $REGEX - exit -} - -[[ -z "$REGEX" ]] && { - cat - -} || { - eval sed $REGEX || echo Maybe errors in your rules: "$REGEX" >&2 -} +simple_colors = "GYCMW" +def highlight_text(text, rules, simple_words, regex_patterns, case_sensitive): + flags = 0 if case_sensitive else re.IGNORECASE + # Apply simple highlights + for i, word in enumerate(simple_words): + color = simple_colors[i % len(simple_colors)] + text = re.sub(rf"{re.escape(word)}", f"{colors[color]}{word}{colors['Z']}", text) + + # Apply regex highlights + for pattern, replacement in rules: + for code in colors: + replacement = replacement.replace("{" + code + "}", colors[code]) + text = re.sub(pattern, f"{replacement}\\g<0>{colors['Z']}", text, flags=flags) + + return text + + +def load_rules(config_file): + rules = [] + try: + with open(config_file, "r") as f: + rules = json.load(f) + except Exception as e: + print(f"Error reading config file: {e}") + sys.exit(1) + return rules + + +def main(): + parser = argparse.ArgumentParser( + description="High Beam Highlighter", + usage=""" cat code.py | highbeam -s def for lambda -r rules {B}{U} + +Example ~/.highbeamrc: +[ {"pattern":"view", "color":"{G}"}, {"pattern":"^qo[^ ]*", "color":"{U}{Y}"} ]""", + ) + parser.add_argument("-c", action="store_true", help="Be case sensitive") + parser.add_argument("-f", default="~/.highbeamrc", help="Define config file (default ~/.highbeamrc)") + parser.add_argument("-s", nargs="+", help="Simple highlight words") + parser.add_argument("-r", nargs="+", help='Define rules with a string, ex. "-r word {G} ^error {R}" ') + + args = parser.parse_args() + config_file = os.path.expanduser(args.f) + rules = [] + if os.path.exists(config_file): + rules = load_rules(config_file) + + simple_words = args.s if args.s else [] + regex_patterns = args.r if args.r else [] + + # Convert regex patterns to rules + for i in range(0, len(regex_patterns), 2): + if i + 1 < len(regex_patterns): + rules.append((regex_patterns[i], regex_patterns[i + 1])) + else: + raise ValueError("Regex patterns missing color code") + + for text in sys.stdin: + print(highlight_text(text, rules, simple_words, regex_patterns, args.c), end="") + + +if __name__ == "__main__": + main()