Compare commits

..

No commits in common. "master" and "v2023.09.19" have entirely different histories.

23 changed files with 106 additions and 303 deletions

View file

@ -67,7 +67,7 @@ runs:
uses: dsaltares/fetch-gh-release-asset@master
if: ${{ env.ACT || inputs.test == 'true' }}
with:
file: "ripgrep_[0-9\\.-]+_amd64.deb"
file: "ripgrep_[0-9\\.]+_amd64.deb"
repo: "BurntSushi/ripgrep"
# version: "${{ inputs.version_ripgrep || "latest" }}"
regex: true

View file

@ -1,5 +1,6 @@
name: Release
on:
release: {}
push:
tags: ['*']
@ -33,11 +34,10 @@ jobs:
output_title="Release: $(date '+%Y-%m-%d')"
bash "${{ github.workspace }}/.github/actions/build/create-release-notes.sh" | tee "${output_file}"
echo "file=${output_file}" >> "$GITHUB_OUTPUT"
echo "title=${output_title}" >> "$GITHUB_OUTPUT"
echo "::set-output name=file::${output_file}"
echo "::set-output name=title::${output_title}"
- name: Create release
if: ${{ !env.ACT }}
uses: ncipollo/release-action@v1
with:
artifacts: "bat-extras-*.zip"

View file

@ -53,21 +53,11 @@ All of the `bat-extras` scripts can be installed with `brew install bat-extras`.
If you would prefer to only install the specific scripts you need, you can use the `eth-p/software` tap to install individual scripts: `brew install eth-p/software/bat-extras-[SCRIPT]`
### MacPorts
The `bat-extras` scripts can also be installed via [MacPorts](https://www.macports.org) on macOS:
```bash
sudo port install bat-extras
```
Port info [here](https://ports.macports.org/port/bat-extras/).
### Pacman
`bat-extras` is [officially available](https://archlinux.org/packages/extra/any/bat-extras/) on the Arch extra repository!
`bat-extras` is [officially available](https://archlinux.org/packages/community/any/bat-extras/) on the Arch community repository!
If you have the extra repository enabled, you can install `bat-extras` by running:
If you have the community repository enabled, you can install `bat-extras` by running:
```bash
pacman -S bat-extras

View file

@ -1,5 +1,5 @@
# -----------------------------------------------------------------------------
# bat-extras | Copyright (C) 2020-2024 eth-p and contributors | MIT License
# 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

View file

@ -31,8 +31,7 @@ Search through files or directories looking for matching regular expressions (or
| | `--paging=["never"/"always"]`| Enable/disable paging. |
| | `--pager=[PAGER]` | Specify the pager to use. |
| | `--terminal-width=[COLS]` | Generate output for the specified terminal width. |
| | `--no-separator` | Disable printing separator between files. |
| | `--rga` | Use `ripgrep-all` instead of `ripgrep`. |
| | `--no-separator` | Disable printing separator between files |
The following options are passed directly to ripgrep, and are not handled by this script.

View file

@ -11,19 +11,7 @@ If you have `fzf` installed, you can even use `batman` to search through manual
batman [SECTION] [ENTRY]
### As a Replacement for Man
With bash:
```bash
eval "$(batman --export-env)"
```
With fish:
```fish
batman --export-env | source
```
## Environment

View file

@ -21,23 +21,22 @@ See `man bat` for more information.
## Languages
| Language | Formatter |
| -------------------- | ------------------------------------------------------------------------------------------------------ |
| JavaScript (JS, JSX) | [prettier](https://prettier.io/) |
| TypeScript (TS, TSX) | [prettier](https://prettier.io/) |
| CSS, SCSS, SASS | [prettier](https://prettier.io/) |
| Markdown | [prettier](https://prettier.io/) |
| JSON | [yq](https://mikefarah.gitbook.io/yq), [prettier](https://prettier.io/) |
| YAML | [yq](https://mikefarah.gitbook.io/yq), [prettier](https://prettier.io/) |
| HTML | [prettier](https://prettier.io/) |
| SVG | [prettier](https://prettier.io/) |
| Rust | [rustfmt](https://github.com/rust-lang/rustfmt) |
| Bash | [shfmt](https://github.com/mvdan/sh) |
| C | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| C++ | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| Objective-C | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| Python | [black](https://black.readthedocs.io/) |
| Elixir | [mix format](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) |
| Language | Formatter |
| -------------------- | ----------------------------------------------------------- |
| JavaScript (JS, JSX) | [prettier](https://prettier.io/) |
| TypeScript (TS, TSX) | [prettier](https://prettier.io/) |
| CSS, SCSS, SASS | [prettier](https://prettier.io/) |
| Markdown | [prettier](https://prettier.io/) |
| JSON | [prettier](https://prettier.io/) |
| YAML | [prettier](https://prettier.io/) |
| HTML | [prettier](https://prettier.io/) |
| SVG | [prettier](https://prettier.io/) |
| Rust | [rustfmt](https://github.com/rust-lang/rustfmt) |
| Bash | [shfmt](https://github.com/mvdan/sh) |
| C | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| C++ | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| Objective-C | [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) |
| Python | [black](https://black.readthedocs.io/) |

View file

@ -39,11 +39,8 @@ parent_shell() {
break
fi
# If the parent process is one of:
# - `*sh`; or
# - `nu`
# Followed by "-l", it's probably a login shell.
if [[ "$target_name" =~ ^(.*sh|nu)\ .*-l ]]; then
# If the parent process has "*sh " followed by "-l", it's probably a login shell.
if [[ "$target_name" =~ sh\ .*-l ]]; then
target_name="$(cut -f1 -d' ' <<< "${target_name}")"
break
fi

View file

@ -155,8 +155,8 @@ print_bat_diff() {
# Diff git file.
if "$SUPPORTS_BAT_DIFF"; then
"$EXECUTABLE_GIT" diff "${GIT_ARGS[@]}" --name-only -z "${files[0]}" \
| xargs --null "$EXECUTABLE_BAT" --diff --diff-context="$OPT_CONTEXT" "${BAT_ARGS[@]}"
"$EXECUTABLE_GIT" diff "${GIT_ARGS[@]}" --name-only "${files[0]}" \
| xargs "$EXECUTABLE_BAT" --diff --diff-context="$OPT_CONTEXT" "${BAT_ARGS[@]}"
else
"$EXECUTABLE_GIT" diff "${GIT_ARGS[@]}" "${files[0]}" | "$EXECUTABLE_BAT" --language=diff - "${BAT_ARGS[@]}"
fi

View file

@ -97,10 +97,7 @@ Options:
Generate output for the specified terminal width.
--no-separator:
Disable printing separator between files.
--rga:
Use ripgrep-all instead of ripgrep.
Disable printing separator between files
Options passed directly to ripgrep:
-F, --fixed-strings
@ -144,7 +141,6 @@ EOF
# -----------------------------------------------------------------------------
# Options:
# -----------------------------------------------------------------------------
RIPGREP="$EXECUTABLE_RIPGREP"
RG_ARGS=()
BAT_ARGS=()
PATTERN=""
@ -256,14 +252,6 @@ while shiftopt; do
-p | --search-pattern) OPT_SEARCH_PATTERN=true ;;
--no-search-pattern) OPT_SEARCH_PATTERN=false ;;
--no-separator) OPT_NO_SEPARATOR=true ;;
--rga) {
if ! rga --version | grep 'ripgrep-all' &>/dev/null; then
printc "%{RED}%s: option '--rga' requires ripgrep-all to be installed%{CLEAR}\n" "$PROGRAM" 1>&2
exit 1
fi
RIPGREP='rga'
};;
# Option forwarding
--rg:*) {
@ -389,10 +377,10 @@ main() {
)
if "$READ_FROM_STDIN"; then
"$RIPGREP" "${COMMON_RG_ARGS[@]}" <<< "$STDIN_DATA"
"$EXECUTABLE_RIPGREP" "${COMMON_RG_ARGS[@]}" <<< "$STDIN_DATA"
return $?
else
"$RIPGREP" "${COMMON_RG_ARGS[@]}"
"$EXECUTABLE_RIPGREP" "${COMMON_RG_ARGS[@]}"
return $?
fi
}

View file

@ -9,6 +9,7 @@
SELF_NC="${BASH_SOURCE:-$0}"
SELF="$(cd "$(dirname "${SELF_NC}")" && cd "$(dirname "$(readlink "${SELF_NC}" || echo ".")")" && pwd)/$(basename "$(readlink "${SELF_NC}" || echo "${SELF_NC}")")"
LIB="$(cd "$(dirname "${SELF_NC}")" && cd "$(dirname "$(readlink "${SELF_NC}" || echo ".")")/../lib" && pwd)"
if [[ -n "${MANPAGER}" ]]; then BAT_PAGER="$MANPAGER"; fi
source "${LIB}/constants.sh"
source "${LIB}/pager.sh"
source "${LIB}/print.sh"
@ -22,13 +23,11 @@ hook_version
FORWARDED_ARGS=()
MAN_ARGS=()
BAT_ARGS=()
OPT_EXPORT_ENV=false
SHIFTOPT_SHORT_OPTIONS="SPLIT"
while shiftopt; do
case "$OPT" in
--export-env) OPT_EXPORT_ENV=true ;;
--paging|--pager|--wrap) shiftval; FORWARDED_ARGS+=("${OPT}=${OPT_VAL}");
--paging|--pager) shiftval; FORWARDED_ARGS+=("${OPT}=${OPT_VAL}");
BAT_ARGS+=("${OPT}=${OPT_VAL}") ;;
*) MAN_ARGS+=("$OPT") ;;
esac
@ -49,8 +48,7 @@ fi
if [[ "${BATMAN_IS_BEING_MANPAGER:-}" = "yes" ]]; then
print_manpage() {
sed -e 's/\x1B\[[0-9;]*m//g; s/.\x08//g' \
| "$EXECUTABLE_BAT" --language=man "${BAT_ARGS[@]}"
col -bx | "$EXECUTABLE_BAT" --language=man "${BAT_ARGS[@]}"
exit $?
}
@ -66,48 +64,30 @@ if [[ "${BATMAN_IS_BEING_MANPAGER:-}" = "yes" ]]; then
fi
# -----------------------------------------------------------------------------
if [[ -n "${MANPAGER}" ]]; then BAT_PAGER="$MANPAGER"; fi
export MANPAGER="env BATMAN_IS_BEING_MANPAGER=yes bash $(printf "%q " "$SELF" "${FORWARDED_ARGS[@]}")"
export MANPAGER="${MANPAGER%"${MANPAGER##*[![:space:]]}"}"
export MANROFFOPT='-c'
# If `--export-env`, print exports to use batman as the manpager directly.
if "$OPT_EXPORT_ENV"; then
printf "export %s=%q\n" \
"MANPAGER" "$MANPAGER" \
"MANROFFOPT" "$MANROFFOPT"
exit 0
fi
# If no argument is provided and fzf is installed, use fzf to search for man pages.
if [[ "${#MAN_ARGS[@]}" -eq 0 ]] && [[ -z "$BATMAN_LEVEL" ]] && command -v "$EXECUTABLE_FZF" &>/dev/null; then
export BATMAN_LEVEL=1
selected_page="$(man -k . | "$EXECUTABLE_FZF" --delimiter=" - " --reverse -e --preview="
echo {1} \
| sed 's/, /\n/g;' \
| sed 's/\([^(]*\)(\([0-9A-Za-z ]\))/\2\t\1/g' \
| BAT_STYLE=plain xargs -n2 batman --color=always --paging=never
")"
if [[ -z "$selected_page" ]]; then
exit 0
fi
# Some entries from `man -k .` may include "synonyms" of a man page's title.
# For example, the manual for kubectl-edit will appear as:
#
# kubectl-edit(1), kubectl edit(1) - Edit a resource on the server
#
# `man` only needs one name/title, so we're taking the first one here.
selected_page_unaliased="$(echo "$selected_page" | cut -d, -f1)"
# Convert the page(section) format to something that can be fed to the man command.
while read -r line; do
if [[ "$line" =~ ^(.*)\(([0-9a-zA-Z ]+)\) ]]; then
MAN_ARGS+=("${BASH_REMATCH[2]}" "$(echo ${BASH_REMATCH[1]} | xargs)")
fi
done <<< "$selected_page_unaliased"
done <<< "$selected_page"
fi
# Run man.

View file

@ -67,13 +67,13 @@ if [[ "$#" -eq 0 ]]; then
# Detect the shell.
#
# This will directly check if the parent is a non-sh/bash shell, since
# there's a good chance that `bash` or `sh` will be invoking it.
case "$(basename -- "$(parent_executable | cut -f1 -d' ')")" in
fish) detected_shell="fish" ;;
nu) detected_shell="nu" ;;
*) detected_shell="$(parent_shell)" ;;
esac
# This will directly check if the parent is fish, since there's a
# good chance that `bash` or `sh` will be invoking fish.
if [[ "$(basename -- "$(parent_executable | cut -f1 -d' ')")" == "fish" ]]; then
detected_shell="fish"
else
detected_shell="$(parent_shell)"
fi
# Print the commands required to add `batpipe` to the environment variables.
case "$(basename -- "${detected_shell:bash}")" in
@ -81,12 +81,6 @@ if [[ "$#" -eq 0 ]]; then
printc '%{YELLOW}set -x %{CLEAR}LESSOPEN %{CYAN}"|%q %%s"%{CLEAR};\n' "$SELF"
printc '%{YELLOW}set -e %{CLEAR}LESSCLOSE;\n'
;;
nu) # Nushell
printc '%{BLUE}$env%{CLEAR}.LESSOPEN = %{CYAN}"|%q %%s"%{CLEAR}\n' "$SELF"
if [[ "${LESSCLOSE:-}" != "" ]]; then
printc '%{BLUE}hide-env%{CLEAR} LESSCLOSE\n' "$SELF"
fi
;;
*) # Bash-like
printc '%{MAGENTA}LESSOPEN%{CLEAR}=%{CYAN}"|%s %%s"%{CLEAR};\n' "$SELF"
printc '%{YELLOW}export%{CLEAR} LESSOPEN;\n' "$SELF"
@ -105,10 +99,6 @@ if [[ "$#" -eq 0 ]]; then
printc '%{YELLOW}set -x %{CLEAR}LESS %{CYAN}"%{MAGENTA}$LESS%{CYAN} -R"%{CLEAR};\n' "$SELF"
printc '%{YELLOW}set -x %{CLEAR}BATPIPE %{CYAN}"color"%{CLEAR};\n'
;;
nu) # Nushell
printc '%{BLUE}$env%{CLEAR}.LESS = %{CYAN}$"%{MAGENTA}($env.LESS)%{CYAN} -R"%{CLEAR}\n' "$SELF"
printc '%{BLUE}$env%{CLEAR}.BATPIPE = %{CYAN}"color"%{CLEAR}\n' "$SELF"
;;
*) # Bash-like
printc '%{MAGENTA}LESS%{CLEAR}=%{CYAN}"%{MAGENTA}$LESS%{CYAN} -R"%{CLEAR};\n' "$SELF"
printc '%{MAGENTA}BATPIPE%{CLEAR}=%{CYAN}"color"%{CLEAR};\n' "$SELF"

View file

@ -14,7 +14,6 @@ source "${LIB}/str.sh"
source "${LIB}/print.sh"
source "${LIB}/version.sh"
source "${LIB}/check.sh"
source "${LIB}/term.sh"
# -----------------------------------------------------------------------------
# Init:
# -----------------------------------------------------------------------------
@ -23,10 +22,7 @@ hook_version
# Formatters:
# -----------------------------------------------------------------------------
FORMATTERS=(
"yq" "prettier" "rustfmt" "shfmt" "clangformat"
"black" "mix_format" "column"
)
FORMATTERS=("prettier" "rustfmt" "shfmt" "clangformat" "black")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -122,96 +118,6 @@ formatter_black_process() {
return $?
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_mix_format_supports() {
case "$1" in
.ex | \
.exs | \
.eex | \
.heex)
return 0
;;
esac
return 1
}
formatter_mix_format_process() {
mix format
return $?
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_column_supports() {
case "$1" in
.tsv)
return 0
;;
esac
return 1
}
formatter_column_process() {
local needs_newline=true
local args=(
-t
-s $'\t'
-c "$TERMINAL_WIDTH"
)
if column --help &>/dev/null; then
# GNU `column`
args+=(--keep-empty-lines)
needs_newline=false
fi
{ { "$needs_newline" && sed 's/$/\n/'; } || cat; } | column "${args[@]}"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_yq_supports__version_ok() {
local yq_version
yq_version=$(yq --version | sed 's/^.* version v//')
# If it's older than yq version 4, replace the functions to save processing.
if version_compare "$yq_version" -lt 4.0; then
formatter_yq_supports() { return 1; }
formatter_yq_supports__version_ok() { return 1; }
return 1
fi
# It's supported.
formatter_yq_supports__version_ok() { return 0; }
return 0
}
formatter_yq_supports() {
case "$1" in
.yaml | yml | \
.json)
formatter_yq_supports__version_ok
return $?
;;
esac
return 1
}
formatter_yq_process() {
local args=()
case "$1" in
*.json) args+=(--output-format json) ;;
esac
yq --prettyPrint --indent 4 "${args[@]}" \
| sed -e ':l' -e 's/^\(\t*\) /\1\t/g; t l'
return $?
}
# -----------------------------------------------------------------------------
# Functions:
# -----------------------------------------------------------------------------
@ -239,9 +145,6 @@ map_language_to_extension() {
rust | rs) ext=".rs" ;;
graphql | gql) ext=".graphql" ;;
python | py) ext=".py" ;;
elixir | ex) ext=".ex" ;;
exs) ext=".exs" ;;
tsv) ext=".tsv" ;;
esac
echo "$ext"
@ -369,8 +272,6 @@ OPT_LANGUAGE=
FILES=()
DEBUG_PRINT_FORMATTER=false
TERMINAL_WIDTH="$(term_width)"
# Parse arguments.
while shiftopt; do
case "$OPT" in

View file

@ -1,4 +1,14 @@
#!/usr/bin/env bash
# Run bash, but with executable name as `fish`.
exec -a "${SHIM_ARGV0:-fish}" bash "$@"
exit $?
# Find the real fish.
HERE="$(cd "$(dirname "$0")" && pwd)"
while read -d ':' -r dir; do
if [[ "$dir" == "$HERE" || -z "$dir" ]]; then continue; fi
if [[ -f "${dir}/fish" ]]; then
TMPDIR='' "${dir}/fish" "$@"
exit $?
fi
done <<<"$PATH:"
# Print error and exit.
echo "fish was not found on \$PATH" 1>&2
exit 127

View file

@ -12,10 +12,4 @@ EOF
exit 0
fi
FILES=()
while [[ $# -gt 0 ]]; do
-*) : ;;
*) FILES+=("$1")
done
cat "${FILES[@]}"
cat "$1"

View file

@ -1,7 +0,0 @@
#!/usr/bin/env bash
# Run bash, but with executable name as `nu`.
#
# Spawn the process in the background and wait on it to ensure we keep
# the fake shell as a parent process.
exec -a "${SHIM_ARGV0:-nu}" bash "$@"
exit $?

View file

@ -63,10 +63,7 @@ Options:
Generate output for the specified terminal width.
--no-separator:
Disable printing separator between files.
--rga:
Use ripgrep-all instead of ripgrep.
Disable printing separator between files
Options passed directly to ripgrep:
-F, --fixed-strings

View file

@ -1,8 +1,8 @@
────────────────────────────────────────────────────────────────────────────────
File: file.txt
 1 cat 
 2 dog
 3 car 
 4 frog
 5 fox
 1 cat 
 2 dog
 3 car 
 4 frog
 5 fox
────────────────────────────────────────────────────────────────────────────────

View file

@ -1,6 +1,6 @@
File: file.txt
 1 cat 
 2 dog
 3 car 
 4 frog
 5 fox
 1 cat 
 2 dog
 3 car 
 4 frog
 5 fox

View file

@ -1,7 +1,7 @@
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
cat 
dog
car 
frog
fox
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────

View file

@ -1,26 +1,26 @@
───────┬────────────────────────────────
│ File: file.txt
───────┼────────────────────────────────
 1 │ cat
 2 │ dog
 3 │ car
 4 │ frog
 5 │ fox
 6 │ clocks
 7 │ bash
 8 │ $300
 9 │ ^$!@
───────┴────────────────────────────────
───────┬────────────────────────────────────────────────────
│ File: file.txt
───────┼────────────────────────────────────────────────────
 1 │ cat
 2 │ dog
 3 │ car
 4 │ frog
 5 │ fox
 6 │ clocks
 7 │ bash
 8 │ $300
 9 │ ^$!@
───────┴────────────────────────────────────────────────────
───────┬────────────────────────────────
│ File: file.txt
───────┼────────────────────────────────
 1 │ cat
 2 │ dog
 3 │ car
 4 │ frog
 5 │ fox
 6 │ clocks
 7 │ bash
 8 │ $300
 9 │ ^$!@
───────┴────────────────────────────────
───────┬────────────────────────────────────────────────────
│ File: file.txt
───────┼────────────────────────────────────────────────────
 1 │ cat
 2 │ dog
 3 │ car
 4 │ frog
 5 │ fox
 6 │ clocks
 7 │ bash
 8 │ $300
 9 │ ^$!@
───────┴────────────────────────────────────────────────────

View file

@ -11,35 +11,12 @@ test:detected_bash_shell() {
}
test:detected_fish_shell() {
description "Test it can detect a fish shell."
# Note: We don't use bash's `-c` option when testing with a fake fish shell.
# Bash `-c` will automatically exec() into the last process, which loses the
# argv0 we intentionally named after a different shell.
# Test detection via `*sh -l` parent process.
output="$(printf "%q" "$(batpipe_path)" | fish -l)"
grep '^set -x' <<< "$output" >/dev/null || fail 'Detected wrong shell when checking parent process args.'
# Test detection via hypen-prefixed parent process.
output="$(printf "%q" "$(batpipe_path)" | SHIM_ARGV0='-fish' fish)"
grep '^set -x' <<< "$output" >/dev/null || fail 'Detected wrong shell when checking parent process.'
}
test:detected_nu_shell() {
description "Test it can detect a nushell shell."
# Note: We don't use bash's `-c` option when testing with a fake nu shell.
# Bash `-c` will automatically exec() into the last process, which loses the
# argv0 we intentionally named after a different shell.
# Test detection via `*sh -l` parent process.
output="$(printf "%q" "$(batpipe_path)" | nu -l)"
grep '^\$env' <<< "$output" >/dev/null || fail 'Detected wrong shell when checking parent process args.'
# Test detection via hypen-prefixed parent process.
output="$(printf "%q" "$(batpipe_path)" | SHIM_ARGV0='-nu' nu -l)"
grep '^\$env' <<< "$output" >/dev/null || fail 'Detected wrong shell when checking parent process.'
description "Test it can detect a bash shell."
command -v "fish" &>/dev/null || skip "Test requires fish shell."
fish -c 'exit 0' &>/dev/null || skip "Test requires fish shell." # This is in case it finds "fish" in shimexec dir.
output="$(SHELL="fish" fish --login -c "$(batpipe_path)")"
grep '^set -x' <<< "$output" >/dev/null || fail "Detected the wrong shell for fish."
}
test:viewer_gzip() {

View file

@ -1 +1 @@
2024.08.24
2023.09.19