blob: c2570c7c5d17463530229976b060dc9166a0be6e (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#!/usr/bin/env bash
# pdf-fzf — interactive PDF text search via fzf + bat
# Deps: pdftotext (poppler-utils), fzf, bat
set -euo pipefail
DIR="${1:-.}"
CACHE=$(mktemp -d /tmp/pdf-fzf.XXXXXX)
trap 'rm -rf "$CACHE"' EXIT
MAPFILE="$CACHE/map.tsv"
INDEX="$CACHE/index.tsv"
echo "Indexing PDFs in '$DIR'..." >&2
find "$DIR" -type f -iname "*.pdf" | sort | while read -r pdf; do
hash=$(printf '%s' "$pdf" | md5sum | cut -c1-8)
txtfile="$CACHE/${hash}.txt"
pdftotext "$pdf" - 2>/dev/null > "$txtfile" || continue
[[ ! -s "$txtfile" ]] && continue
printf '%s\t%s\t%s\n' "$hash" "$pdf" "$txtfile" >> "$MAPFILE"
awk -v src="$pdf" -F'\t' \
'NF { printf "%s\t%d\t%s\n", src, NR, $0 }' "$txtfile"
done > "$INDEX"
PDF_COUNT=$(wc -l < "${MAPFILE:-/dev/null}" 2>/dev/null || echo 0)
LINE_COUNT=$(wc -l < "$INDEX")
echo "Indexed $LINE_COUNT lines from $PDF_COUNT PDFs." >&2
# Preview script — receives the raw fzf line, shows bat at matched line
PREVIEW_SH="$CACHE/preview.sh"
cat > "$PREVIEW_SH" <<PREVIEW
#!/usr/bin/env bash
IFS=\$'\\t' read -r pdf linenum _ <<< "\$1"
txtfile=\$(awk -F'\\t' -v p="\$pdf" '\$2==p{print \$3; exit}' "$MAPFILE")
[[ -f "\$txtfile" ]] || { echo "No preview for: \$pdf"; exit 1; }
echo -e "\\033[1;34m\$pdf\\033[0m"
batcat --style=numbers,grid \\
--highlight-line="\$linenum" \\
--language=txt \\
--pager=never \\
"\$txtfile"
PREVIEW
chmod +x "$PREVIEW_SH"
fzf \
--delimiter=$'\t' \
--with-nth='1,3' \
--preview="$PREVIEW_SH {}" \
--preview-window='right:65%:wrap' \
--prompt='PDF › ' \
--header="$LINE_COUNT lines · $PDF_COUNT PDFs · $DIR [Enter: open PDF]" \
--color='header:italic,prompt:bold' \
--bind "enter:execute(xdg-open {1} 2>/dev/null &)" \
< "$INDEX"
|