From 96151c44aae21849ea566d881310c48446045468 Mon Sep 17 00:00:00 2001 From: Ethan P Date: Sun, 4 Oct 2020 01:04:28 -0700 Subject: [PATCH] Add a batgrep as Bash script syntax tests --- .../syntax-tests/highlighted/Bash/batgrep.sh | 511 ++++++++++++++++++ tests/syntax-tests/source/Bash/batgrep.sh | 511 ++++++++++++++++++ 2 files changed, 1022 insertions(+) create mode 100644 tests/syntax-tests/highlighted/Bash/batgrep.sh create mode 100644 tests/syntax-tests/source/Bash/batgrep.sh diff --git a/tests/syntax-tests/highlighted/Bash/batgrep.sh b/tests/syntax-tests/highlighted/Bash/batgrep.sh new file mode 100644 index 00000000..16048f13 --- /dev/null +++ b/tests/syntax-tests/highlighted/Bash/batgrep.sh @@ -0,0 +1,511 @@ +#!/usr/bin/env bash +# ----------------------------------------------------------------------------- +# bat-extras | Copyright (C) 2020 eth-p and contributors | MIT License +# +# Repository: https://github.com/eth-p/bat-extras +# Issues: https://github.com/eth-p/bat-extras/issues +# ----------------------------------------------------------------------------- +printc(){ +printf "$(sed "$_PRINTC_PATTERN" <<<"$1")" "${@:2}" +} +printc_init(){ +case "$1" in +true)_PRINTC_PATTERN="$_PRINTC_PATTERN_ANSI";; +false)_PRINTC_PATTERN="$_PRINTC_PATTERN_PLAIN";; +"[DEFINE]"){ +_PRINTC_PATTERN_ANSI="" +_PRINTC_PATTERN_PLAIN="" +local name +local ansi +while read -r name ansi;do +if [[ -z $name && -z $ansi ]]||[[ ${name:0:1} == "#" ]];then +continue +fi +ansi="${ansi/\\/\\\\}" +_PRINTC_PATTERN_PLAIN="${_PRINTC_PATTERN_PLAIN}s/%{$name}//g;" +_PRINTC_PATTERN_ANSI="${_PRINTC_PATTERN_ANSI}s/%{$name}/$ansi/g;" +done +if [ -t 1 ];then +_PRINTC_PATTERN="$_PRINTC_PATTERN_ANSI" +else +_PRINTC_PATTERN="$_PRINTC_PATTERN_PLAIN" +fi +} +esac +} +print_warning(){ +printc "%{YELLOW}[%s warning]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 +} +print_error(){ +printc "%{RED}[%s error]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 +} +printc_init "[DEFINE]" <<END + CLEAR \x1B[0m + RED \x1B[31m + GREEN \x1B[32m + YELLOW \x1B[33m + BLUE \x1B[34m + MAGENTA \x1B[35m + CYAN \x1B[36m + + DEFAULT \x1B[39m + DIM \x1B[2m +END +is_pager_less(){ +[[ "$(pager_name)" == "less" ]] +return $? +} +is_pager_disabled(){ +[[ -z "$(pager_name)" ]] +return $? +} +pager_name(){ +_detect_pager 1>&2 +echo "$_SCRIPT_PAGER_NAME" +} +pager_version(){ +_detect_pager 1>&2 +echo "$_SCRIPT_PAGER_VERSION" +} +pager_exec(){ +if [[ -n $SCRIPT_PAGER_CMD ]];then +"$@"|pager_display +return $? +else +"$@" +return $? +fi +} +pager_display(){ +if [[ -n $SCRIPT_PAGER_CMD ]];then +if [[ -n $SCRIPT_PAGER_ARGS ]];then +"${SCRIPT_PAGER_CMD[@]}" "${SCRIPT_PAGER_ARGS[@]}" +return $? +else +"${SCRIPT_PAGER_CMD[@]}" +return $? +fi +else +cat +return $? +fi +} +_detect_pager(){ +if [[ $_SCRIPT_PAGER_DETECTED == "true" ]];then return;fi +_SCRIPT_PAGER_DETECTED=true +if [[ -z ${SCRIPT_PAGER_CMD[0]} ]];then +_SCRIPT_PAGER_VERSION=0 +_SCRIPT_PAGER_NAME="" +return +fi +local output +local output1 +output="$("${SCRIPT_PAGER_CMD[0]}" --version 2>&1)" +output1="$(head -n 1 <<<"$output")" +if [[ $output1 =~ ^less[[:blank:]]([[:digit:]]+) ]];then +_SCRIPT_PAGER_VERSION="${BASH_REMATCH[1]}" +_SCRIPT_PAGER_NAME="less" +else +_SCRIPT_PAGER_VERSION=0 +_SCRIPT_PAGER_NAME="$(basename "${SCRIPT_PAGER_CMD[0]}")" +fi +} +_configure_pager(){ +SCRIPT_PAGER_CMD=($PAGER) +SCRIPT_PAGER_ARGS=() +if [[ -n ${BAT_PAGER+x} ]];then +SCRIPT_PAGER_CMD=($BAT_PAGER) +SCRIPT_PAGER_ARGS=() +return +fi +if is_pager_less;then +SCRIPT_PAGER_CMD=("${SCRIPT_PAGER_CMD[0]}" -R --quit-if-one-screen) +if [[ "$(pager_version)" -lt 500 ]];then +SCRIPT_PAGER_CMD+=(--no-init) +fi +fi +} +if [[ -t 1 ]];then +_configure_pager +else +SCRIPT_PAGER_CMD=() +SCRIPT_PAGER_ARGS=() +fi +SHIFTOPT_HOOKS=() +setargs(){ +_ARGV=("$@") +_ARGV_LAST="$((${#_ARGV[@]}-1))" +_ARGV_INDEX=0 +} +shiftopt(){ +[[ $_ARGV_INDEX -gt $_ARGV_LAST ]]&&return 1 +OPT="${_ARGV[$_ARGV_INDEX]}" +unset OPT_VAL +if [[ $OPT =~ ^--[a-zA-Z0-9_-]+=.* ]];then +OPT_VAL="${OPT#*=}" +OPT="${OPT%%=*}" +fi +((_ARGV_INDEX++)) +local hook +for hook in "${SHIFTOPT_HOOKS[@]}";do +if "$hook";then +shiftopt +return $? +fi +done +return 0 +} +shiftval(){ +if [[ -n ${OPT_VAL+x} ]];then +return 0 +fi +if [[ $OPT =~ ^-[[:alpha:]][[:digit:]]{1,}$ ]];then +OPT_VAL="${OPT:2}" +return +fi +OPT_VAL="${_ARGV[$_ARGV_INDEX]}" +((_ARGV_INDEX++)) +if [[ $OPT_VAL =~ -.* ]];then +printc "%{RED}%s: '%s' requires a value%{CLEAR}\n" "batgrep" "$ARG" +exit 1 +fi +} +setargs "$@" +hook_color(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__color") +__shiftopt_hook__color(){ +case "$OPT" in +--no-color)OPT_COLOR=false;; +--color){ +case "$OPT_VAL" in +"")OPT_COLOR=true;; +always|true)OPT_COLOR=true;; +never|false)OPT_COLOR=false;; +auto)return 0;; +*)printc "%{RED}%s: '--color' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" +exit 1 +esac +};; +*)return 1 +esac +printc_init "$OPT_COLOR" +return 0 +} +if [[ -z $OPT_COLOR ]];then +if [[ -t 1 ]];then +OPT_COLOR=true +else +OPT_COLOR=false +fi +printc_init "$OPT_COLOR" +fi +} +hook_pager(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__pager") +__shiftopt_hook__pager(){ +case "$OPT" in +\ +--no-pager)shiftval +SCRIPT_PAGER_CMD='' +;; +--paging){ +shiftval +case "$OPT_VAL" in +auto):;; +always):;; +never)SCRIPT_PAGER_CMD='';; +*)printc "%{RED}%s: '--paging' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" +exit 1 +esac +};; +\ +--pager){ +shiftval +{ +SCRIPT_PAGER_CMD=($OPT_VAL) +PAGER_ARGS=() +} +};; +*)return 1 +esac +} +} +hook_version(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__version") +__shiftopt_hook__version(){ +if [[ $OPT == "--version" ]];then +printf "%s %s\n\n%s\n%s\n" \ +"batgrep" \ +"2020.10.04" \ +"Copyright (C) 2019-2020 eth-p | MIT License" \ +"https://github.com/eth-p/bat-extras" +exit 0 +fi +return 1 +} +} +term_width(){ +local width="$({ stty size 2>/dev/null||echo "22 80";}|cut -d ' ' -f2)" +if [[ $width -ne 0 ]];then +echo "$width" +else +echo "80" +fi +return 0 +} +hook_width(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__width") +__shiftopt_hook__width(){ +case "$OPT" in +--terminal-width)shiftval +OPT_TERMINAL_WIDTH="$OPT_VAL" +;; +*)return 1 +esac +return 0 +} +OPT_TERMINAL_WIDTH="$(term_width)" +} +bat_version(){ +"bat" --version|cut -d ' ' -f 2 +return +} +version_compare(){ +local version="$1" +local compare="$3" +if ! [[ $version =~ \.$ ]];then +version="$version." +fi +if ! [[ $compare =~ \.$ ]];then +compare="$compare." +fi +version_compare__recurse "$version" "$2" "$compare" +return $? +} +version_compare__recurse(){ +local version="$1" +local operator="$2" +local compare="$3" +local v_major="${version%%.*}" +local c_major="${compare%%.*}" +local v_minor="${version#*.}" +local c_minor="${compare#*.}" +if [[ -z $v_minor && -z $c_minor ]];then +[ "$v_major" $operator "$c_major" ] +return $? +fi +if [[ -z $v_minor ]];then +v_minor="0." +fi +if [[ -z $c_minor ]];then +c_minor="0." +fi +case "$operator" in +-eq)[[ $v_major -ne $c_major ]]&&return 1;; +-ne)[[ $v_major -ne $c_major ]]&&return 0;; +-ge|-gt)[[ $v_major -lt $c_major ]]&&return 1 +[[ $v_major -gt $c_major ]]&&return 0 +;; +-le|-lt)[[ $v_major -gt $c_major ]]&&return 1 +[[ $v_major -lt $c_major ]]&&return 0 +esac +version_compare__recurse "$v_minor" "$operator" "$c_minor" +} +hook_color +hook_pager +hook_version +hook_width +RG_ARGS=() +BAT_ARGS=() +PATTERN="" +FILES=() +OPT_CASE_SENSITIVITY='' +OPT_CONTEXT_BEFORE=2 +OPT_CONTEXT_AFTER=2 +OPT_FOLLOW=true +OPT_SNIP="" +OPT_HIGHLIGHT=true +OPT_SEARCH_PATTERN=false +OPT_FIXED_STRINGS=false +BAT_STYLE="header,numbers" +if version_compare "$(bat_version)" -gt "0.12";then +OPT_SNIP=",snip" +fi +if [[ -n $RIPGREP_CONFIG_PATH && -e $RIPGREP_CONFIG_PATH ]];then +for arg in $(cat "$RIPGREP_CONFIG_PATH");do +case "$arg" in +--context=*)val="${arg:10}" +OPT_CONTEXT_BEFORE="$val" +OPT_CONTEXT_AFTER="$val" +;; +--before-context=*)val="${arg:17}" +OPT_CONTEXT_BEFORE="$val" +;; +--after-context=*)val="${arg:16}" +OPT_CONTEXT_AFTER="$val" +;; +-C*)val="${arg:2}" +OPT_CONTEXT_BEFORE="$val" +OPT_CONTEXT_AFTER="$val" +;; +-B*)val="${arg:2}" +OPT_CONTEXT_BEFORE="$val" +;; +-A*)val="${arg:2}" +OPT_CONTEXT_AFTER="$val" +esac +done +fi +while shiftopt;do +case "$OPT" in +\ +-i|--ignore-case)OPT_CASE_SENSITIVITY="--ignore-case";; +-s|--case-sensitive)OPT_CASE_SENSITIVITY="--case-sensitive";; +-S|--smart-case)OPT_CASE_SENSITIVITY="--smart-case";; +-A*|--after-context)shiftval +OPT_CONTEXT_AFTER="$OPT_VAL" +;; +-B*|--before-context)shiftval +OPT_CONTEXT_BEFORE="$OPT_VAL" +;; +-C*|--context)shiftval +OPT_CONTEXT_BEFORE="$OPT_VAL" +OPT_CONTEXT_AFTER="$OPT_VAL" +;; +-F|--fixed-strings)OPT_FIXED_STRINGS=true +RG_ARGS+=("$OPT") +;; +-U|--multiline|\ +-P|--pcre2|\ +-z|--search-zip|\ +-w|--word-regexp|\ +--one-file-system|\ +--multiline-dotall|\ +--ignore|--no-ignore|\ +--crlf|--no-crlf|\ +--hidden|--no-hidden)RG_ARGS+=("$OPT") +;; +-E|--encoding|\ +-g|--glob|\ +-t|--type|\ +-T|--type-not|\ +-m|--max-count|\ +--max-depth|\ +--iglob|\ +--ignore-file)shiftval +RG_ARGS+=("$OPT" "$OPT_VAL") +;; +\ +\ +\ +--no-follow)OPT_FOLLOW=false;; +--no-snip)OPT_SNIP="";; +--no-highlight)OPT_HIGHLIGHT=false;; +-p|--search-pattern)OPT_SEARCH_PATTERN=true;; +--no-search-pattern)OPT_SEARCH_PATTERN=false;; +\ +--rg:*){ +if [[ ${OPT:5:1} == "-" ]];then +RG_ARGS+=("${OPT:5}") +else +RG_ARGS+=("--${OPT:5}") +fi +if [[ -n $OPT_VAL ]];then +RG_ARGS+=("$OPT_VAL") +fi +};; +\ +-*){ +printc "%{RED}%s: unknown option '%s'%{CLEAR}\n" "batgrep" "$OPT" 1>&2 +exit 1 +};; +\ +*){ +if [ -z "$PATTERN" ];then +PATTERN="$OPT" +else +FILES+=("$OPT") +fi +} +esac +done +if [[ -z $PATTERN ]];then +print_error "no pattern provided" +exit 1 +fi +SEP="$(printc "%{DIM}%${OPT_TERMINAL_WIDTH}s%{CLEAR}"|sed "s/ /─/g")" +if [[ -n $OPT_CASE_SENSITIVITY ]];then +RG_ARGS+=("$OPT_CASE_SENSITIVITY") +fi +if "$OPT_FOLLOW";then +RG_ARGS+=("--follow") +fi +if "$OPT_COLOR";then +BAT_ARGS+=("--color=always") +else +BAT_ARGS+=("--color=never") +fi +if [[ $OPT_CONTEXT_BEFORE -eq 0 && $OPT_CONTEXT_AFTER -eq 0 ]];then +OPT_SNIP="" +OPT_HIGHLIGHT=false +fi +if "$OPT_SEARCH_PATTERN";then +if is_pager_less;then +if "$OPT_FIXED_STRINGS";then +SCRIPT_PAGER_ARGS+=(-p $'\x12'"$PATTERN") +else +SCRIPT_PAGER_ARGS+=(-p "$PATTERN") +fi +elif is_pager_disabled;then +print_error "%s %s %s" \ +"The -p/--search-pattern option requires a pager, but" \ +'the pager was explicitly disabled by $BAT_PAGER or the' \ +"--paging option." +exit 1 +else +print_error "Unsupported pager '%s' for option -p/--search-pattern" \ +"$(pager_name)" +exit 1 +fi +fi +main(){ +FOUND_FILES=() +FOUND=0 +FIRST_PRINT=true +LAST_LR=() +LAST_LH=() +LAST_FILE='' +do_print(){ +[[ -z $LAST_FILE ]]&&return 0 +"$FIRST_PRINT"&&echo "$SEP" +FIRST_PRINT=false +"bat" "${BAT_ARGS[@]}" \ +"${LAST_LR[@]}" \ +"${LAST_LH[@]}" \ +--style="$BAT_STYLE$OPT_SNIP" \ +--paging=never \ +--terminal-width="$OPT_TERMINAL_WIDTH" \ +"$LAST_FILE" +echo "$SEP" +} +while IFS=':' read -r file line column text;do +((FOUND++)) +if [[ $LAST_FILE != "$file" ]];then +do_print +LAST_FILE="$file" +LAST_LR=() +LAST_LH=() +fi +line_start=$((line-OPT_CONTEXT_BEFORE)) +line_end=$((line+OPT_CONTEXT_AFTER)) +[[ $line_start -gt 0 ]]||line_start='' +LAST_LR+=("--line-range=$line_start:$line_end") +[[ $OPT_HIGHLIGHT == "true" ]]&&LAST_LH+=("--highlight-line=$line") +done < <(rg --with-filename --vimgrep "${RG_ARGS[@]}" --context=0 --no-context-separator --sort path "$PATTERN" "${FILES[@]}") +do_print +if [[ $FOUND -eq 0 ]];then +exit 2 +fi +} +pager_exec main +exit $? diff --git a/tests/syntax-tests/source/Bash/batgrep.sh b/tests/syntax-tests/source/Bash/batgrep.sh new file mode 100644 index 00000000..655b2637 --- /dev/null +++ b/tests/syntax-tests/source/Bash/batgrep.sh @@ -0,0 +1,511 @@ +#!/usr/bin/env bash +# ----------------------------------------------------------------------------- +# bat-extras | Copyright (C) 2020 eth-p and contributors | MIT License +# +# Repository: https://github.com/eth-p/bat-extras +# Issues: https://github.com/eth-p/bat-extras/issues +# ----------------------------------------------------------------------------- +printc(){ +printf "$(sed "$_PRINTC_PATTERN" <<<"$1")" "${@:2}" +} +printc_init(){ +case "$1" in +true)_PRINTC_PATTERN="$_PRINTC_PATTERN_ANSI";; +false)_PRINTC_PATTERN="$_PRINTC_PATTERN_PLAIN";; +"[DEFINE]"){ +_PRINTC_PATTERN_ANSI="" +_PRINTC_PATTERN_PLAIN="" +local name +local ansi +while read -r name ansi;do +if [[ -z $name && -z $ansi ]]||[[ ${name:0:1} == "#" ]];then +continue +fi +ansi="${ansi/\\/\\\\}" +_PRINTC_PATTERN_PLAIN="${_PRINTC_PATTERN_PLAIN}s/%{$name}//g;" +_PRINTC_PATTERN_ANSI="${_PRINTC_PATTERN_ANSI}s/%{$name}/$ansi/g;" +done +if [ -t 1 ];then +_PRINTC_PATTERN="$_PRINTC_PATTERN_ANSI" +else +_PRINTC_PATTERN="$_PRINTC_PATTERN_PLAIN" +fi +} +esac +} +print_warning(){ +printc "%{YELLOW}[%s warning]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 +} +print_error(){ +printc "%{RED}[%s error]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 +} +printc_init "[DEFINE]" <&2 +echo "$_SCRIPT_PAGER_NAME" +} +pager_version(){ +_detect_pager 1>&2 +echo "$_SCRIPT_PAGER_VERSION" +} +pager_exec(){ +if [[ -n $SCRIPT_PAGER_CMD ]];then +"$@"|pager_display +return $? +else +"$@" +return $? +fi +} +pager_display(){ +if [[ -n $SCRIPT_PAGER_CMD ]];then +if [[ -n $SCRIPT_PAGER_ARGS ]];then +"${SCRIPT_PAGER_CMD[@]}" "${SCRIPT_PAGER_ARGS[@]}" +return $? +else +"${SCRIPT_PAGER_CMD[@]}" +return $? +fi +else +cat +return $? +fi +} +_detect_pager(){ +if [[ $_SCRIPT_PAGER_DETECTED == "true" ]];then return;fi +_SCRIPT_PAGER_DETECTED=true +if [[ -z ${SCRIPT_PAGER_CMD[0]} ]];then +_SCRIPT_PAGER_VERSION=0 +_SCRIPT_PAGER_NAME="" +return +fi +local output +local output1 +output="$("${SCRIPT_PAGER_CMD[0]}" --version 2>&1)" +output1="$(head -n 1 <<<"$output")" +if [[ $output1 =~ ^less[[:blank:]]([[:digit:]]+) ]];then +_SCRIPT_PAGER_VERSION="${BASH_REMATCH[1]}" +_SCRIPT_PAGER_NAME="less" +else +_SCRIPT_PAGER_VERSION=0 +_SCRIPT_PAGER_NAME="$(basename "${SCRIPT_PAGER_CMD[0]}")" +fi +} +_configure_pager(){ +SCRIPT_PAGER_CMD=($PAGER) +SCRIPT_PAGER_ARGS=() +if [[ -n ${BAT_PAGER+x} ]];then +SCRIPT_PAGER_CMD=($BAT_PAGER) +SCRIPT_PAGER_ARGS=() +return +fi +if is_pager_less;then +SCRIPT_PAGER_CMD=("${SCRIPT_PAGER_CMD[0]}" -R --quit-if-one-screen) +if [[ "$(pager_version)" -lt 500 ]];then +SCRIPT_PAGER_CMD+=(--no-init) +fi +fi +} +if [[ -t 1 ]];then +_configure_pager +else +SCRIPT_PAGER_CMD=() +SCRIPT_PAGER_ARGS=() +fi +SHIFTOPT_HOOKS=() +setargs(){ +_ARGV=("$@") +_ARGV_LAST="$((${#_ARGV[@]}-1))" +_ARGV_INDEX=0 +} +shiftopt(){ +[[ $_ARGV_INDEX -gt $_ARGV_LAST ]]&&return 1 +OPT="${_ARGV[$_ARGV_INDEX]}" +unset OPT_VAL +if [[ $OPT =~ ^--[a-zA-Z0-9_-]+=.* ]];then +OPT_VAL="${OPT#*=}" +OPT="${OPT%%=*}" +fi +((_ARGV_INDEX++)) +local hook +for hook in "${SHIFTOPT_HOOKS[@]}";do +if "$hook";then +shiftopt +return $? +fi +done +return 0 +} +shiftval(){ +if [[ -n ${OPT_VAL+x} ]];then +return 0 +fi +if [[ $OPT =~ ^-[[:alpha:]][[:digit:]]{1,}$ ]];then +OPT_VAL="${OPT:2}" +return +fi +OPT_VAL="${_ARGV[$_ARGV_INDEX]}" +((_ARGV_INDEX++)) +if [[ $OPT_VAL =~ -.* ]];then +printc "%{RED}%s: '%s' requires a value%{CLEAR}\n" "batgrep" "$ARG" +exit 1 +fi +} +setargs "$@" +hook_color(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__color") +__shiftopt_hook__color(){ +case "$OPT" in +--no-color)OPT_COLOR=false;; +--color){ +case "$OPT_VAL" in +"")OPT_COLOR=true;; +always|true)OPT_COLOR=true;; +never|false)OPT_COLOR=false;; +auto)return 0;; +*)printc "%{RED}%s: '--color' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" +exit 1 +esac +};; +*)return 1 +esac +printc_init "$OPT_COLOR" +return 0 +} +if [[ -z $OPT_COLOR ]];then +if [[ -t 1 ]];then +OPT_COLOR=true +else +OPT_COLOR=false +fi +printc_init "$OPT_COLOR" +fi +} +hook_pager(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__pager") +__shiftopt_hook__pager(){ +case "$OPT" in +\ +--no-pager)shiftval +SCRIPT_PAGER_CMD='' +;; +--paging){ +shiftval +case "$OPT_VAL" in +auto):;; +always):;; +never)SCRIPT_PAGER_CMD='';; +*)printc "%{RED}%s: '--paging' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" +exit 1 +esac +};; +\ +--pager){ +shiftval +{ +SCRIPT_PAGER_CMD=($OPT_VAL) +PAGER_ARGS=() +} +};; +*)return 1 +esac +} +} +hook_version(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__version") +__shiftopt_hook__version(){ +if [[ $OPT == "--version" ]];then +printf "%s %s\n\n%s\n%s\n" \ +"batgrep" \ +"2020.10.04" \ +"Copyright (C) 2019-2020 eth-p | MIT License" \ +"https://github.com/eth-p/bat-extras" +exit 0 +fi +return 1 +} +} +term_width(){ +local width="$({ stty size 2>/dev/null||echo "22 80";}|cut -d ' ' -f2)" +if [[ $width -ne 0 ]];then +echo "$width" +else +echo "80" +fi +return 0 +} +hook_width(){ +SHIFTOPT_HOOKS+=("__shiftopt_hook__width") +__shiftopt_hook__width(){ +case "$OPT" in +--terminal-width)shiftval +OPT_TERMINAL_WIDTH="$OPT_VAL" +;; +*)return 1 +esac +return 0 +} +OPT_TERMINAL_WIDTH="$(term_width)" +} +bat_version(){ +"bat" --version|cut -d ' ' -f 2 +return +} +version_compare(){ +local version="$1" +local compare="$3" +if ! [[ $version =~ \.$ ]];then +version="$version." +fi +if ! [[ $compare =~ \.$ ]];then +compare="$compare." +fi +version_compare__recurse "$version" "$2" "$compare" +return $? +} +version_compare__recurse(){ +local version="$1" +local operator="$2" +local compare="$3" +local v_major="${version%%.*}" +local c_major="${compare%%.*}" +local v_minor="${version#*.}" +local c_minor="${compare#*.}" +if [[ -z $v_minor && -z $c_minor ]];then +[ "$v_major" $operator "$c_major" ] +return $? +fi +if [[ -z $v_minor ]];then +v_minor="0." +fi +if [[ -z $c_minor ]];then +c_minor="0." +fi +case "$operator" in +-eq)[[ $v_major -ne $c_major ]]&&return 1;; +-ne)[[ $v_major -ne $c_major ]]&&return 0;; +-ge|-gt)[[ $v_major -lt $c_major ]]&&return 1 +[[ $v_major -gt $c_major ]]&&return 0 +;; +-le|-lt)[[ $v_major -gt $c_major ]]&&return 1 +[[ $v_major -lt $c_major ]]&&return 0 +esac +version_compare__recurse "$v_minor" "$operator" "$c_minor" +} +hook_color +hook_pager +hook_version +hook_width +RG_ARGS=() +BAT_ARGS=() +PATTERN="" +FILES=() +OPT_CASE_SENSITIVITY='' +OPT_CONTEXT_BEFORE=2 +OPT_CONTEXT_AFTER=2 +OPT_FOLLOW=true +OPT_SNIP="" +OPT_HIGHLIGHT=true +OPT_SEARCH_PATTERN=false +OPT_FIXED_STRINGS=false +BAT_STYLE="header,numbers" +if version_compare "$(bat_version)" -gt "0.12";then +OPT_SNIP=",snip" +fi +if [[ -n $RIPGREP_CONFIG_PATH && -e $RIPGREP_CONFIG_PATH ]];then +for arg in $(cat "$RIPGREP_CONFIG_PATH");do +case "$arg" in +--context=*)val="${arg:10}" +OPT_CONTEXT_BEFORE="$val" +OPT_CONTEXT_AFTER="$val" +;; +--before-context=*)val="${arg:17}" +OPT_CONTEXT_BEFORE="$val" +;; +--after-context=*)val="${arg:16}" +OPT_CONTEXT_AFTER="$val" +;; +-C*)val="${arg:2}" +OPT_CONTEXT_BEFORE="$val" +OPT_CONTEXT_AFTER="$val" +;; +-B*)val="${arg:2}" +OPT_CONTEXT_BEFORE="$val" +;; +-A*)val="${arg:2}" +OPT_CONTEXT_AFTER="$val" +esac +done +fi +while shiftopt;do +case "$OPT" in +\ +-i|--ignore-case)OPT_CASE_SENSITIVITY="--ignore-case";; +-s|--case-sensitive)OPT_CASE_SENSITIVITY="--case-sensitive";; +-S|--smart-case)OPT_CASE_SENSITIVITY="--smart-case";; +-A*|--after-context)shiftval +OPT_CONTEXT_AFTER="$OPT_VAL" +;; +-B*|--before-context)shiftval +OPT_CONTEXT_BEFORE="$OPT_VAL" +;; +-C*|--context)shiftval +OPT_CONTEXT_BEFORE="$OPT_VAL" +OPT_CONTEXT_AFTER="$OPT_VAL" +;; +-F|--fixed-strings)OPT_FIXED_STRINGS=true +RG_ARGS+=("$OPT") +;; +-U|--multiline|\ +-P|--pcre2|\ +-z|--search-zip|\ +-w|--word-regexp|\ +--one-file-system|\ +--multiline-dotall|\ +--ignore|--no-ignore|\ +--crlf|--no-crlf|\ +--hidden|--no-hidden)RG_ARGS+=("$OPT") +;; +-E|--encoding|\ +-g|--glob|\ +-t|--type|\ +-T|--type-not|\ +-m|--max-count|\ +--max-depth|\ +--iglob|\ +--ignore-file)shiftval +RG_ARGS+=("$OPT" "$OPT_VAL") +;; +\ +\ +\ +--no-follow)OPT_FOLLOW=false;; +--no-snip)OPT_SNIP="";; +--no-highlight)OPT_HIGHLIGHT=false;; +-p|--search-pattern)OPT_SEARCH_PATTERN=true;; +--no-search-pattern)OPT_SEARCH_PATTERN=false;; +\ +--rg:*){ +if [[ ${OPT:5:1} == "-" ]];then +RG_ARGS+=("${OPT:5}") +else +RG_ARGS+=("--${OPT:5}") +fi +if [[ -n $OPT_VAL ]];then +RG_ARGS+=("$OPT_VAL") +fi +};; +\ +-*){ +printc "%{RED}%s: unknown option '%s'%{CLEAR}\n" "batgrep" "$OPT" 1>&2 +exit 1 +};; +\ +*){ +if [ -z "$PATTERN" ];then +PATTERN="$OPT" +else +FILES+=("$OPT") +fi +} +esac +done +if [[ -z $PATTERN ]];then +print_error "no pattern provided" +exit 1 +fi +SEP="$(printc "%{DIM}%${OPT_TERMINAL_WIDTH}s%{CLEAR}"|sed "s/ /─/g")" +if [[ -n $OPT_CASE_SENSITIVITY ]];then +RG_ARGS+=("$OPT_CASE_SENSITIVITY") +fi +if "$OPT_FOLLOW";then +RG_ARGS+=("--follow") +fi +if "$OPT_COLOR";then +BAT_ARGS+=("--color=always") +else +BAT_ARGS+=("--color=never") +fi +if [[ $OPT_CONTEXT_BEFORE -eq 0 && $OPT_CONTEXT_AFTER -eq 0 ]];then +OPT_SNIP="" +OPT_HIGHLIGHT=false +fi +if "$OPT_SEARCH_PATTERN";then +if is_pager_less;then +if "$OPT_FIXED_STRINGS";then +SCRIPT_PAGER_ARGS+=(-p $'\x12'"$PATTERN") +else +SCRIPT_PAGER_ARGS+=(-p "$PATTERN") +fi +elif is_pager_disabled;then +print_error "%s %s %s" \ +"The -p/--search-pattern option requires a pager, but" \ +'the pager was explicitly disabled by $BAT_PAGER or the' \ +"--paging option." +exit 1 +else +print_error "Unsupported pager '%s' for option -p/--search-pattern" \ +"$(pager_name)" +exit 1 +fi +fi +main(){ +FOUND_FILES=() +FOUND=0 +FIRST_PRINT=true +LAST_LR=() +LAST_LH=() +LAST_FILE='' +do_print(){ +[[ -z $LAST_FILE ]]&&return 0 +"$FIRST_PRINT"&&echo "$SEP" +FIRST_PRINT=false +"bat" "${BAT_ARGS[@]}" \ +"${LAST_LR[@]}" \ +"${LAST_LH[@]}" \ +--style="$BAT_STYLE$OPT_SNIP" \ +--paging=never \ +--terminal-width="$OPT_TERMINAL_WIDTH" \ +"$LAST_FILE" +echo "$SEP" +} +while IFS=':' read -r file line column text;do +((FOUND++)) +if [[ $LAST_FILE != "$file" ]];then +do_print +LAST_FILE="$file" +LAST_LR=() +LAST_LH=() +fi +line_start=$((line-OPT_CONTEXT_BEFORE)) +line_end=$((line+OPT_CONTEXT_AFTER)) +[[ $line_start -gt 0 ]]||line_start='' +LAST_LR+=("--line-range=$line_start:$line_end") +[[ $OPT_HIGHLIGHT == "true" ]]&&LAST_LH+=("--highlight-line=$line") +done < <(rg --with-filename --vimgrep "${RG_ARGS[@]}" --context=0 --no-context-separator --sort path "$PATTERN" "${FILES[@]}") +do_print +if [[ $FOUND -eq 0 ]];then +exit 2 +fi +} +pager_exec main +exit $?