batdiff: Add batdiff script

This commit is contained in:
Ethan P 2020-04-27 04:00:44 -07:00 committed by Ethan P
parent 0d73f2abd5
commit ab0f1b96d6
7 changed files with 277 additions and 0 deletions

View File

@ -25,6 +25,12 @@ Watch for changes in one or more files, and print them with `bat`.
### [`batdiff`](doc/batgrep.md)
Diff a file against the current git index, or display the diff between two files.
<u>Requirements:</u> `bat`, `delta` (optional)
### [`prettybat`](doc/prettybat.md)
Pretty-print source code and highlight it with `bat`.

55
doc/batdiff.md Normal file
View File

@ -0,0 +1,55 @@
# bat-extras: batdiff
Diff a file against the current git index, or display the diff between two files.
This script supports using [delta](https://github.com/dandavison/delta) as an alternative highlighter for diffs.
## Command Line
**Synopsis:**
- `batdiff [OPTIONS] FILE`
- `batdiff [OPTIONS] FILE OTHER_FILE`
**Options:**
| Short | Long | Description |
| ----- | ------------------------- | ------------------------------------------------------------ |
| `-C` | `--context=[LINES]` | The number of lines to show before and after the differing lines. |
| | `--delta` | Display diffs using `delta`. |
| | `--color` | Force color output. |
| | `--no-color` | Force disable color output. |
| | `--paging=["never"|"always"]`| Enable/disable paging. |
| | `--pager=[PAGER]` | Specify the pager to use. |
| | `--terminal-width=[COLS]` | Generate output for the specified terminal width. |
## Installation
This script is a part of the `bat-extras` suite of scripts. You can find install instructions [here](../README.md#installation).
## Caveats
**When using `bat` as the printer:**
- Syntax highlighting in diffs between two files is not supported.
- Syntax highlighting in a single-file diff requires `bat` >= 0.15.
**When using `delta` as the printer:**
- The `--no-color` option does not remove all color output.
## Issues?
If you find an issue or have a feature suggestion, make a pull request or issue through GitHub!
Contributions are always welcome.

View File

@ -7,6 +7,7 @@
# -----------------------------------------------------------------------------
EXECUTABLE_BAT="bat"
EXECUTABLE_GIT="git"
EXECUTABLE_DELTA="delta"
PROGRAM="$(basename "$0" .sh)"
PROGRAM_HOMEPAGE="https://github.com/eth-p/bat-extras"
PROGRAM_COPYRIGHT="Copyright (C) 2019-2020 eth-p | MIT License"

27
lib/opt_hook_width.sh Normal file
View File

@ -0,0 +1,27 @@
#!/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
# -----------------------------------------------------------------------------
# Option parser hook: --terminal-width support.
# This will accept --terminal-width=number.
#
# The variable OPT_TERMINAL_WIDTH will be set.
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
}
# Default terminal width.
OPT_TERMINAL_WIDTH="$(stty size | cut -d' ' -f 2)"
}

173
src/batdiff.sh Executable file
View File

@ -0,0 +1,173 @@
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# bat-extras | Copyright (C) 2020 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)"
source "${LIB}/constants.sh"
source "${LIB}/print.sh"
source "${LIB}/pager.sh"
source "${LIB}/opt.sh"
source "${LIB}/opt_hooks.sh"
source "${LIB}/opt_hook_width.sh"
source "${LIB}/version.sh"
# -----------------------------------------------------------------------------
# Init:
# -----------------------------------------------------------------------------
hook_color
hook_pager
hook_version
hook_width
# -----------------------------------------------------------------------------
# Options:
# -----------------------------------------------------------------------------
BATDIFF_USE_DELTA="${BATDIFF_USE_DELTA:-}"
SUPPORTS_BAT_DIFF=false
SUPPORTS_DELTA=false
BAT_VERSION="$(bat_version)"
BAT_ARGS=()
DELTA_ARGS=()
FILES=()
OPT_TABS=
OPT_CONTEXT=2
OPT_ALL_CHANGES=false
# Set options based on bat version.
if version_compare "$BAT_VERSION" -ge "0.15"; then
SUPPORTS_BAT_DIFF=true
fi
# Set options based on delta availability.
if command -v "$EXECUTABLE_DELTA" &>/dev/null; then
SUPPORTS_DELTA=true
fi
# Parse arguments.
while shiftopt; do
case "$OPT" in
# bat options
-C | --context | --diff-context) shiftval; OPT_CONTEXT="$OPT_VAL" ;;
--terminal-width) shiftval; OPT_TERMINAL_WIDTH="$OPT_VAL" ;;
--tabs) shiftval; OPT_TABS="$OPT_VAL" ;;
# Script options
--all) OPT_ALL_CHANGES=true ;;
--delta) BATDIFF_USE_DELTA=true ;;
# ???
-*) {
printc "%{RED}%s: unknown option '%s'%{CLEAR}\n" "$PROGRAM" "$OPT" 1>&2
exit 1
} ;;
# Files
*) FILES+=("$OPT") ;;
esac
done
# Append arguments for delta/bat.
BAT_ARGS+=("--terminal-width=${OPT_TERMINAL_WIDTH}" "--paging=never")
DELTA_ARGS+=("--width=${OPT_TERMINAL_WIDTH}" "--paging=never" "--hunk-style=plain")
if "$OPT_COLOR"; then
BAT_ARGS+=("--color=always")
else
BAT_ARGS+=("--color=never")
DELTA_ARGS+=("--theme=none")
fi
if [[ -n "$OPT_TABS" ]]; then
BAT_ARGS+=("--tabs=${OPT_TABS}")
DELTA_ARGS+=("--tabs=${OPT_TABS}")
fi
# -----------------------------------------------------------------------------
# Printing:
# -----------------------------------------------------------------------------
print_bat_diff() {
local files=("$@")
# Diff two files.
if [[ "${#files[@]}" -eq 2 ]]; then
diff --unified="$OPT_CONTEXT" "${files[@]}" | "$EXECUTABLE_BAT" --language=diff - "${BAT_ARGS[@]}"
return $?
fi
# Diff git file.
if "$SUPPORTS_BAT_DIFF"; then
"$EXECUTABLE_BAT" --diff --diff-context="$OPT_CONTEXT" "${files[0]}" "${BAT_ARGS[@]}"
else
"$EXECUTABLE_GIT" diff -U"$OPT_CONTEXT" "${files[0]}" | "$EXECUTABLE_BAT" --language=diff - "${BAT_ARGS[@]}"
fi
}
print_delta_diff() {
local files=("$@")
# Diff two files.
if [[ "${#files[@]}" -eq 2 ]]; then
diff --unified="$OPT_CONTEXT" "${files[@]}" | "$EXECUTABLE_DELTA" "${DELTA_ARGS[@]}"
return $?
fi
# Diff git file.
"$EXECUTABLE_GIT" diff -U"$OPT_CONTEXT" "${files[0]}" | "$EXECUTABLE_DELTA" "${DELTA_ARGS[@]}"
}
if [[ "$BATDIFF_USE_DELTA" = "true" && "$SUPPORTS_DELTA" = "true" ]]; then
print_diff() {
print_delta_diff "$@"
return $?
}
else
print_diff() {
print_bat_diff "$@"
return $?
}
fi
# -----------------------------------------------------------------------------
# Validation:
# -----------------------------------------------------------------------------
# Handle no files.
if [[ "${#FILES[@]}" -eq 0 ]] && ! "$OPT_ALL_CHANGES"; then
print_error "no files provided"
exit 1
fi
# Handle too many files.
if [[ "${#FILES[@]}" -gt 2 ]]; then
print_error "too many files provided"
exit 1
fi
# -----------------------------------------------------------------------------
# Main:
# -----------------------------------------------------------------------------
main() {
if "$OPT_ALL_CHANGES"; then
local file
while read -r file; do
if [[ -f "$file" ]]; then
print_diff "$file"
fi
done < <(git diff --name-only --diff-filter=d)
return
fi
print_diff "${FILES[@]}"
}
pager_exec main
exit $?

3
test/shim/batdiff.sh Normal file
View File

@ -0,0 +1,3 @@
batdiff() {
"${BIN_DIR}/batdiff${BIN_SUFFIX}" "$@" || return $?
}

12
test/suite/batdiff.sh Normal file
View File

@ -0,0 +1,12 @@
setup() {
use_shim 'batdiff'
}
test:version() {
description "Test 'batdiff --version'"
snapshot stdout
snapshot stderr
batdiff --version | awk 'FNR <= 1 { print $1 }'
batdiff --version | awk 'p{print} /^$/ { p=1 }'
}