bat-extras/src/prettybat.sh
2019-06-21 16:17:20 -07:00

218 lines
4.8 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
# -----------------------------------------------------------------------------
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../lib"
source "${LIB}/opt.sh"
source "${LIB}/str.sh"
source "${LIB}/print.sh"
# -----------------------------------------------------------------------------
PROGRAM="$0"
# -----------------------------------------------------------------------------
# Formatters:
# -----------------------------------------------------------------------------
FORMATTERS=("prettier" "rustfmt" "shfmt")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_prettier_supports() {
case "$1" in
.js|.jsx|\
.ts|.tsx|\
.css|.scss|.sass|\
.html|\
.json|\
.md|\
.yml)
return 0;;
esac
return 1
}
formatter_prettier_process() {
prettier --stdin --stdin-filepath "$1" 2>/dev/null
return $?
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_rustfmt_supports() {
[[ "$1" = ".rs" ]]
return $?
}
formatter_rustfmt_process() {
rustfmt
return $?
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
formatter_shfmt_supports() {
[[ "$1" = ".sh" ]]
return $?
}
formatter_shfmt_process() {
shfmt
return $?
}
# -----------------------------------------------------------------------------
# Functions:
# -----------------------------------------------------------------------------
# This function will map a bat `--language=...` argument into an appropriate
# file extension for the language provided. This must be hardcoded for
# performance reasons.
map_language_to_extension() {
local ext=".txt"
case "$1" in
sh|bash) ext=".sh" ;;
js|es6|es) ext=".js" ;;
jsx) ext=".jsx" ;;
ts) ext=".ts" ;;
tsx) ext=".tsx" ;;
css) ext=".css" ;;
scss) ext=".scss" ;;
sass) ext=".sass" ;;
html|htm|shtml|xhtml) ext=".html" ;;
json) ext=".json" ;;
md|mdown|markdown) ext=".md" ;;
yaml|yml) ext=".yml" ;;
rust|rs) ext=".rs" ;;
esac
echo "$ext"
}
# This function will map a file extension to a formatter.
# Formatters are defined higher up in the file.
map_extension_to_formatter() {
local formatter
for formatter in "${FORMATTERS[@]}"; do
if "formatter_${formatter}_supports" "$1"; then
echo "$formatter"
return 0
fi
done
echo "none"
return 0
}
extname() {
local file="$1"
echo ".${file##*.}"
}
print_file() {
if [[ "${#BAT_ARGS[@]}" -eq 0 ]]; then
bat "$@"
return $?
else
bat "${BAT_ARGS[@]}" "$@"
return $?
fi
}
process_file() {
local file="$1"
local ext="$2"
local fext="$ext"
local lang="${ext:1}"
if [[ -n "$OPT_LANGUAGE" ]]; then
lang="$OPT_LANGUAGE"
fext="$(map_language_to_extension "$lang")"
fi
local formatter="$(map_extension_to_formatter "$fext")"
if [[ "$formatter" = "none" ]]; then
if [[ -z "$OPT_LANGUAGE" ]]; then
print_file "$file"
else
print_file --language="$OPT_LANGUAGE" "$file"
fi
return $?
fi
# Prettify, then print.
local status
local data_raw
local data_formatted
if [[ "$file" = "-" ]]; then
data_raw="$(cat -)"
data_formatted="$("formatter_${formatter}_process" "$file" 2>/dev/null <<< "$data_raw")"
if [[ $? -ne 0 ]]; then
printc "%{YELLOW}[%s warning]%{CLEAR}: 'STDIN': Unable to format with '%s'\n" "$PROGRAM" "$formatter" 1>&2
print_file --language="$lang" - <<< "$data_raw"
return 1
fi
else
data_formatted="$("formatter_${formatter}_process" "$file" < "$file")"
if [[ $? -ne 0 ]]; then
printc "%{YELLOW}[%s warning]%{CLEAR}: '%s': Unable to format with '%s'\n" "$PROGRAM" "$file" "$formatter" 1>&2
print_file --language="$lang" "$file"
return 1
fi
fi
print_file --language="$lang" - <<< "$data_formatted"
return $?
}
# -----------------------------------------------------------------------------
# Main:
# -----------------------------------------------------------------------------
BAT_ARGS=()
OPT_LANGUAGE=
FILES=()
# Parse arguments.
while shiftopt; do
case "$OPT" in
# Language Options
-l) shiftval; OPT_LANGUAGE="${OPT_VAL}" ;;
-l*) OPT_LANGUAGE="${OPT:2}" ;;
--language) shiftval; OPT_LANGUAGE="$OPT_VAL" ;;
# Bat Options
-*) {
BAT_ARGS+=("$OPT=$OPT_VAL")
};;
# Files
*) {
FILES+=("$OPT")
};;
esac
done
if [[ "${#FILES[@]}" -eq 0 ]]; then
FILES="-"
fi
# Handle input files.
FAIL=0
for file in "${FILES[@]}"; do
if ! process_file "$file" "$(tolower "$(extname "$file")")"; then
FAIL=1
fi
done
# Exit.
exit $EXIT