mirror of
https://github.com/eth-p/bat-extras.git
synced 2025-07-31 17:14:02 +02:00
243 lines
5.6 KiB
Bash
Executable File
243 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# -----------------------------------------------------------------------------
|
|
# bat-extras | Copyright (C) 2019 eth-p | MIT License
|
|
#
|
|
# Repository: https://github.com/eth-p/bat-extras
|
|
# Issues: https://github.com/eth-p/bat-extras/issues
|
|
# -----------------------------------------------------------------------------
|
|
# shellcheck disable=SC1090
|
|
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo ".")")/../lib" && pwd)"
|
|
BAT="bat"
|
|
source "${LIB}/print.sh"
|
|
source "${LIB}/pager.sh"
|
|
source "${LIB}/opt.sh"
|
|
source "${LIB}/opt_hooks.sh"
|
|
source "${LIB}/version.sh"
|
|
# -----------------------------------------------------------------------------
|
|
# Init:
|
|
# -----------------------------------------------------------------------------
|
|
hook_color
|
|
hook_pager
|
|
# -----------------------------------------------------------------------------
|
|
# Options:
|
|
# -----------------------------------------------------------------------------
|
|
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"
|
|
|
|
# Set options based on the bat version.
|
|
if version_compare "$(bat_version)" -gt "0.12"; then
|
|
OPT_SNIP=",snip"
|
|
fi
|
|
|
|
# Parse arguments.
|
|
while shiftopt; do
|
|
case "$OPT" in
|
|
|
|
# ripgrep options
|
|
-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")
|
|
;;
|
|
|
|
# bat options
|
|
|
|
# Script options
|
|
--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 ;;
|
|
|
|
# Option forwarding
|
|
--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" "$PROGRAM" "$OPT" 1>&2
|
|
exit 1
|
|
} ;;
|
|
|
|
# Search
|
|
*) {
|
|
if [ -z "$PATTERN" ]; then
|
|
PATTERN="$OPT"
|
|
else
|
|
FILES+=("$OPT")
|
|
fi
|
|
} ;;
|
|
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$PATTERN" ]]; then
|
|
print_error "no pattern provided"
|
|
exit 1
|
|
fi
|
|
|
|
# Generate separator.
|
|
COLS="$(tput cols)"
|
|
SEP="$(printc "%{DIM}%${COLS}s%{CLEAR}" | sed "s/ /─/g")"
|
|
|
|
# Append ripgrep and bat arguments.
|
|
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
|
|
|
|
# Handle the --search-pattern option.
|
|
if "$OPT_SEARCH_PATTERN"; then
|
|
if is_pager_less; then
|
|
if "$OPT_FIXED_STRINGS"; then
|
|
# This strange character is a ^R, or Control-R, character. This instructs
|
|
# less to NOT use regular expressions, which is what the -F flag does for
|
|
# ripgrep. If we did not use this, then less would match a different pattern
|
|
# than ripgrep searched for. See man less(1).
|
|
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:
|
|
# -----------------------------------------------------------------------------
|
|
main() {
|
|
# shellcheck disable=SC2034
|
|
FOUND_FILES=()
|
|
FOUND=0
|
|
FIRST_PRINT=true
|
|
LAST_LR=()
|
|
LAST_LH=()
|
|
LAST_FILE=''
|
|
|
|
do_print() {
|
|
[[ -z "$LAST_FILE" ]] && return 0
|
|
|
|
# Print the separator.
|
|
"$FIRST_PRINT" && echo "$SEP"
|
|
FIRST_PRINT=false
|
|
|
|
# Print the file.
|
|
"$BAT" "${BAT_ARGS[@]}" \
|
|
"${LAST_LR[@]}" \
|
|
"${LAST_LH[@]}" \
|
|
--style="${BAT_STYLE}${OPT_SNIP}" \
|
|
--paging=never \
|
|
--terminal-width="$COLS" \
|
|
"$LAST_FILE"
|
|
|
|
# Print the separator.
|
|
echo "$SEP"
|
|
}
|
|
|
|
# shellcheck disable=SC2034
|
|
while IFS=':' read -r file line column; do
|
|
((FOUND++))
|
|
|
|
if [[ "$LAST_FILE" != "$file" ]]; then
|
|
do_print
|
|
LAST_FILE="$file"
|
|
LAST_LR=()
|
|
LAST_LH=()
|
|
fi
|
|
|
|
# Calculate the context line numbers.
|
|
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[@]}" --sort path "$PATTERN" "${FILES[@]}")
|
|
do_print
|
|
|
|
# Exit.
|
|
if [[ "$FOUND" -eq 0 ]]; then
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
pager_exec main
|
|
exit $?
|