feat(preview): add universal file preview script and installer
Universal preview command handling text (bat), images (chafa), PDFs (pdftotext), markdown (glow), and archives. Includes install.d script for preview dependencies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
160
home/.local/bin/preview
Executable file
160
home/.local/bin/preview
Executable file
@@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Universal file preview — used by fzf widgets and as a standalone command.
|
||||||
|
# Usage: preview <file> [line]
|
||||||
|
|
||||||
|
file="${1:?usage: preview <file> [line]}"
|
||||||
|
line="${2:-}"
|
||||||
|
|
||||||
|
if [[ ! -e "$file" ]]; then
|
||||||
|
echo "not found: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Directory preview
|
||||||
|
if [[ -d "$file" ]]; then
|
||||||
|
if command -v eza &>/dev/null; then
|
||||||
|
eza --tree --level=2 --icons --color=always "$file"
|
||||||
|
else
|
||||||
|
ls -1A "$file"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Standalone mode: full terminal, can page output
|
||||||
|
# fzf mode: constrained to preview pane dimensions
|
||||||
|
is_fzf() { [[ -n "${FZF_PREVIEW_COLUMNS:-}" ]]; }
|
||||||
|
|
||||||
|
preview_image() {
|
||||||
|
local w h
|
||||||
|
if is_fzf; then
|
||||||
|
w="$FZF_PREVIEW_COLUMNS"
|
||||||
|
h="$FZF_PREVIEW_LINES"
|
||||||
|
chafa --size="${w}x${h}" "$file"
|
||||||
|
else
|
||||||
|
w="$(tput cols)"
|
||||||
|
h="$(tput lines)"
|
||||||
|
printf '\033[?1049h'
|
||||||
|
chafa --size="${w}x${h}" "$file"
|
||||||
|
read -rsn1
|
||||||
|
printf '\033[?1049l'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_pdf() {
|
||||||
|
if is_fzf; then
|
||||||
|
pdftotext -l 3 "$file" -
|
||||||
|
else
|
||||||
|
pdftotext "$file" - | bat --paging=always --style=plain --language=txt
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_markdown() {
|
||||||
|
if is_fzf; then
|
||||||
|
bat --color=always --style=numbers ${line:+--highlight-line="$line"} "$file"
|
||||||
|
elif command -v glow &>/dev/null; then
|
||||||
|
glow -p "$file"
|
||||||
|
else
|
||||||
|
bat --paging=always --color=always --style=numbers "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_archive() {
|
||||||
|
local lower_file
|
||||||
|
lower_file="$(printf '%s' "$file" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
local output
|
||||||
|
case "$lower_file" in
|
||||||
|
*.tar|*.tar.gz|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz)
|
||||||
|
output="$(tar -tf "$file" | head -80)" ;;
|
||||||
|
*.zip|*.jar|*.war)
|
||||||
|
output="$(unzip -l "$file" | head -80)" ;;
|
||||||
|
*.gz)
|
||||||
|
output="$(gzip -l "$file")" ;;
|
||||||
|
*)
|
||||||
|
output="$(file "$file")" ;;
|
||||||
|
esac
|
||||||
|
if is_fzf; then
|
||||||
|
printf '%s\n' "$output"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$output" | bat --paging=always --style=plain --language=txt
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_text() {
|
||||||
|
local bat_args=(--color=always --style=numbers)
|
||||||
|
if [[ -n "$line" ]]; then
|
||||||
|
bat_args+=(--highlight-line="$line")
|
||||||
|
if is_fzf; then
|
||||||
|
local start=$((line > 30 ? line - 30 : 1))
|
||||||
|
bat_args+=(--line-range="$start:$((line + 30))")
|
||||||
|
fi
|
||||||
|
elif is_fzf; then
|
||||||
|
bat_args+=(--line-range=:100)
|
||||||
|
fi
|
||||||
|
if ! is_fzf; then
|
||||||
|
bat_args+=(--paging=always)
|
||||||
|
fi
|
||||||
|
bat "${bat_args[@]}" "$file" 2>/dev/null || head -100 "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_binary() {
|
||||||
|
local output
|
||||||
|
output="$(file "$file"; echo ""; hexdump -C "$file" | head -40)"
|
||||||
|
if is_fzf; then
|
||||||
|
printf '%s\n' "$output"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$output" | bat --paging=always --style=plain --language=txt
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Route by extension
|
||||||
|
ext="${file##*.}"
|
||||||
|
ext="$(printf '%s' "$ext" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
|
case "$ext" in
|
||||||
|
png|jpg|jpeg|gif|webp|bmp|svg|ico|tiff|tif|avif)
|
||||||
|
if command -v chafa &>/dev/null; then
|
||||||
|
preview_image
|
||||||
|
else
|
||||||
|
file "$file"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
pdf)
|
||||||
|
if command -v pdftotext &>/dev/null; then
|
||||||
|
preview_pdf
|
||||||
|
else
|
||||||
|
file "$file"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
md|markdown|mdx)
|
||||||
|
preview_markdown
|
||||||
|
;;
|
||||||
|
tar|gz|tgz|bz2|tbz2|xz|txz|zip|jar|war)
|
||||||
|
preview_archive
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# MIME fallback for extensionless or ambiguous files
|
||||||
|
mime="$(file --mime-type -b "$file" 2>/dev/null || echo "unknown")"
|
||||||
|
case "$mime" in
|
||||||
|
image/*)
|
||||||
|
if command -v chafa &>/dev/null; then
|
||||||
|
preview_image
|
||||||
|
else
|
||||||
|
file "$file"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
application/pdf)
|
||||||
|
if command -v pdftotext &>/dev/null; then
|
||||||
|
preview_pdf
|
||||||
|
else
|
||||||
|
file "$file"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
text/*|application/json|application/xml|application/javascript|*/x-shellscript)
|
||||||
|
preview_text
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
preview_binary
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
65
install.d/27-preview.sh
Executable file
65
install.d/27-preview.sh
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Description:
|
||||||
|
# Install preview dependencies: chafa (images), poppler (PDFs), glow (markdown).
|
||||||
|
#
|
||||||
|
|
||||||
|
# chafa — terminal image viewer
|
||||||
|
if ! command -v chafa &> /dev/null; then
|
||||||
|
case "$DOTS_PKG" in
|
||||||
|
brew)
|
||||||
|
brew install chafa
|
||||||
|
;;
|
||||||
|
apt)
|
||||||
|
sudo apt-get install -qq chafa
|
||||||
|
;;
|
||||||
|
pacman)
|
||||||
|
sudo pacman -S --noconfirm --needed chafa
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_warn "Skipping chafa install: no supported package manager found"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
command -v chafa &> /dev/null && chafa --version | head -1 | log_quote
|
||||||
|
|
||||||
|
# pdftotext — PDF text extraction (part of poppler)
|
||||||
|
if ! command -v pdftotext &> /dev/null; then
|
||||||
|
case "$DOTS_PKG" in
|
||||||
|
brew)
|
||||||
|
brew install poppler
|
||||||
|
;;
|
||||||
|
apt)
|
||||||
|
sudo apt-get install -qq poppler-utils
|
||||||
|
;;
|
||||||
|
pacman)
|
||||||
|
sudo pacman -S --noconfirm --needed poppler
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_warn "Skipping poppler install: no supported package manager found"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
command -v pdftotext &> /dev/null && pdftotext -v 2>&1 | head -1 | log_quote
|
||||||
|
|
||||||
|
# glow — rendered markdown in terminal
|
||||||
|
if ! command -v glow &> /dev/null; then
|
||||||
|
case "$DOTS_PKG" in
|
||||||
|
brew)
|
||||||
|
brew install glow
|
||||||
|
;;
|
||||||
|
apt)
|
||||||
|
sudo apt-get install -qq glow
|
||||||
|
;;
|
||||||
|
pacman)
|
||||||
|
sudo pacman -S --noconfirm --needed glow
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_warn "Skipping glow install: no supported package manager found"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
command -v glow &> /dev/null && glow --version | head -1 | log_quote
|
||||||
|
|
||||||
|
log_pass "preview dependencies"
|
||||||
Reference in New Issue
Block a user