#!/bin/bash
# exhibit - exhibit preparation helper
lib_load 'net/email'
lib_load 'doc/tool/email2pdf'
lib_load 'doc/text'
lib_load 'doc/tool/latex'
lib_load 'sys/tool/git'
######
# Config
doc_legal_exhibit_config_init() {
lib_setting_vars --null exhibit_case exhibit_timestamp \
exhibit_offset exhibit_number exhibit_count
lib_setting_vars --null exhibit_binder_author
lib_setting_vars --null exhibit_binder_sort
lib_setting_vars --null exhibitdir
lib_setting_vars --null exhibit_binderdir
exhibit_binder_sort=true
exhibit_case="test"
exhibit_offset=1
exhibit_count=1
lib_setting_vars exhibit_summary_lines
exhibit_summary_lines=20
lib_setting_vars --null exhibit_review_state
lib_setting_vars exhibit_review_type
exhibit_review_type="${exhibit_review_type:-unknown}"
}
error_if_unset() { declare -p "$1" >/dev/null || error "$1 is not set"; }
run_mkdir_if_set() {
error_if_unset "$1"
run_mkdir "$(vecho "$1")"
}
check_exhibitdir() { run_mkdir_if_set "$exhibitdir"; }
check_binderdir() { run_mkdir_if_set "$exhibit_binderdir"; }
######
# Unknown
exhibit_unknown() {
warn "$1: unknown file type"
}
exhibit_unknown_view() { exhibit_unknown "$@"; }
exhibit_unknown_view_raw() { exhibit_unknown "$@"; }
exhibit_unknown_view_pdf() { exhibit_unknown "$@"; }
exhibit_unknown_view_summary() { exhibit_unknown "$@"; }
######
# Text Exhibit
exhibit_text_gen() {
latex_document exhibit_text_gen_head exhibit_text_gen_body "$@"
}
exhibit_text_gen_head() {
latex_package "geometry" "margin=0.1cm"
}
exhibit_text_gen_body() {
local file=$1
}
exhibit_text_build() {
local file=$1
text_pdf "$file"
exhibit_text_gen "$file"
}
exhibit_text_view() { run_pager "$1"; }
exhibit_text_view_raw() { run_pager "$1"; }
exhibit_text_view_pdf() { run_text_pdf_viewer "$1"; }
exhibit_text_view_summary() { head -n "$exhibit_summary_lines" "$1"; }
######
# Email Exhibit
exhibit_email_gen() {
latex_document exhibit_email_gen_head exhibit_emailimg_gen_body "$@"
}
exhibit_email_gen_head() {
latex_package "geometry" "margin=0.1cm"
}
exhibit_email_gen_body() {
local file=$1
}
exhibit_email_build() {
local file=$1
local subject
subject=$(email_header "subject")
exhibit_email_gen "$file"
email_pdf "$file"
}
exhibit_email_pdf() { email_pdf "$1"; }
exhibit_email_view() { email_view "$1"; }
exhibit_email_view_raw() { run_pager "$1"; }
exhibit_email_view_pdf() { run_email_pdf_viewer "$file"; }
exhibit_email_view_summary() {
email_headers_simple "$file"
echo
email_body "$file" | head -n "$exhibit_summary_lines"
}
######
# Image Exhibit
exhibit_img_gen() {
latex_document exhibit_img_gen_head exhibit_img_gen_body "$@"
}
exhibit_img_gen_head() {
latex_package "geometry" "margin=0.1cm"
}
exhibit_img_gen_body() {
:
}
exhibit_img_build() {
:
}
exhibit_image_view() { image_view "$1"; }
exhibit_image_view_raw() { run_image_viewer "$1"; }
exhibit_image_view_pdf() { run_image_pdf_viewer "$file"; }
exhibit_image_view_summary() { file "$file"; }
######
# PDF Exhibit
exhibit_pdf_gen() {
latex_document exhibit_pdf_gen_head exhibit_pdf_gen_body "$@"
}
exhibit_pdf_gen_head() {
latex_package "geometry" "margin=0.1cm"
}
exhibit_pdf_gen_body() {
:
}
exhibit_pdf_build() {
:
}
exhibit_pdf_view() { run_pdf_viewer "$1"; }
exhibit_pdf_view_raw() { run_pdf_viewer "$1"; }
exhibit_pdf_view_pdf() { run_pdf_viewer "$1"; }
exhibit_pdf_view_summary() { file "$1"; }
######
# Generation
exhibit_filename() {
check_exhibitdir
echo "$exhibitdir/$exhibit_number.pdf"
}
exhibit_next() { ((exhibit_number++)); }
exhibit_generate() {
has_args 1 "$@"
local name=$1
latex_document exhibit_generate_head exhibit_generate_body "$name"
}
exhibit_generate_head() {
local name=$1
latex_package "color"
latex_tag color "red"
latex_package "geometry" "margin=0.5in,bottom=0.1in"
# latex_package "fullpage" "cm"
latex_page_style "fancyplain"
latex_tag "lhead" "Exhibit \#$exhibit_number"
[ -z "$exhibit_case" ] || latex_tag "rhead" "Case \#$exhibit_case"
local file
file=$(basename "$name")
latex_tag "lfoot" "$file"
latex_package 'lastpage'
latex_tag "cfoot" '\thepage\ of\ \pageref{LastPage}'
[ -z "$exhibit_timestamp" ] || latex_tag "rfoot" "$exhibit_timestamp"
}
exhibit_generate_body() {
local name=$1
local pages
pages=$(pdf_page_count "$name")
for page in $(seq 1 $pages); do
echo "~\\newpage"
done
}
exhibit_build() {
has_args 2 "$@"
local src=$1
local dst=$2
local otmp
otmp=$(cmd_tempfile)
pdf_fair_use "$src" "$otmp"
local etmp
etmp=$(cmd_tempfile)
exhibit_generate "$src" >"$etmp"
latex_pdf "$etmp"
pdf_overlay "$otmp" "$dst" "$etmp.pdf"
}
######
# Binders
exhibit_binder_list() {
local cbdir
cbdir=$(git_repo_dir)
(
source "$cbdir/case.conf"
IFS=$'\n'
echo "${binders[*]}"
)
}
exhibit_binderdir() {
has_args 1 "$@"
local cbdir=$(exhibit_case_binderdir)
echo "$cbdir/$1"
}
exhibit_binder_new() {
local name=$1
local binderdir
binderdir=$(exhibit_binderdir "$name")
[ ! -d "$binderdir" ] || error "$name: binder exists"
run_mkdir "$binderdir"
}
exhibit_binder_generate() {
has_args 1 "$@"
local name=$1
shift
local binderdir binderconf
binderdir=$(exhibit_binderdir "$name")
binderconf="$binderdir.conf"
[ -f "$binderconf" ] || error "$name.conf: binder configuration missing"
local gendir
gendir=$(exhibit_binderdir "gen/$name")
run_mkdir "$gendir"
local -a bfiles
local file_find_opts=( -type f )
file_find bfiles "$binderdir"
! $exhibit_binder_sort || qsort_list bfiles
local n_files=${#bfiles[@]}
local exhibit_start=${exhibit_number:-${exhibit_offset:-1}}
exhibit_number=$exhibit_start
local -a exhibits
for file in "${bfiles[@]}"; do
local -a exhibit
exhibit=$(printf "$gendir/%04d.pdf" "$exhibit_number")
exhibits+=( "$exhibit" )
app_echo "$file: building exhibit $exhibit/$n_files..."
exhibit_build "$file" "$exhibit"
exhibit_next
done
exhibit_count=$((exhibit_number - exhibit_start))
local cover
cover=$(cmd_tempfile)
local binder_name
binder_name=$(
source "$binderconf"
[ "$name" ] || error "$binderconf: name is not set"
echo "$name"
)
exhibit_number=$exhibit_start
exhibit_binder_gen_cover "$binder_name" "${bfiles[@]}" >"$cover"
latex_pdf "$cover"
# calculate offset
local cover_page_offset
cover_page_offset=$(pdf_page_count "$cover.pdf")
((cover_page_offset++))
# generate cover again
exhibit_number=$exhibit_start
exhibit_binder_gen_cover "$binder_name" "${bfiles[@]}" >"$cover"
latex_pdf "$cover"
local pdftk_output="$binderdir.pdf"
local -a pdftk_inputs=( "$cover.pdf" "${exhibits[@]}" )
local -a pdftk_op=( cat )
run_pdftk
}
exhibit_binder_gen_cover() {
min_args 1 "$@"
debug "$1: generating ToC"
latex_document exhibit_binder_gen_head exhibit_binder_gen_body "$@"
}
exhibit_binder_gen_head() {
local file=$1
local name
name=$(basename "$file")
latex_document_title "$name"
[ -z "$exhibit_binder_author" ] \
|| latex_document_author "$exhibit_binder_author"
latex_document_date_today
}
exhibit_binder_gen_body() {
local file=$1
shift
latex_newpage
local name
name=$(basename "$file")
latex_section "$name Contents"
local page_number=${cover_page_offset:-1}
latex_tabular '|r|l|r|' \
exhibit_binder_toc_header \
exhibit_binder_toc_entry \
"$@"
}
exhibit_binder_toc_header() {
latex_tag hline
echo 'Number&Name&Page(s)&SHA-1\\'
latex_tag hline
}
exhibit_binder_toc_entry() {
local name=$1
local label
label=$(basename "$name")
local sha1sum
sha1sum=$(sha1sum "$name")
local pages
pages=$(pdf_page_count "$name")
local page_range=$page_number
if (( pages > 1 )); then
local last_page=$(($page_number + pages - 1))
page_range="$page_range--$last_page"
fi
echo "$exhibit_number&$label&$page_range&$sha1sum"'\\'
latex_tag hline
page_number=$((page_number + pages))
exhibit_next
}
######
# Case
exhibit_case_binderdir() {
local casedir
casedir=$(git_repo_dir)
echo "$casedir/binders"
}
exhibit_case_list() {
:
}
exhibit_case_new() {
local name=$1
local casedir
casedir="$(git_repo_dir)/$name"
[ ! -d "$casedir" ] || error "$name: case exists"
run_mkdir "$casedir"
}
exhibit_case_update() {
has_args 1 "$@"
local file=$1
local casedir
casedir=$(git_repo_dir)
local tmp
tmp=$(cmd_tempfile)
sed -e "s, *\t,|,g" "$file" >"$tmp"
local -a lines
readarray -t lines <"$tmp"
for_each exhibit_case_update_one "${lines[@]}"
}
exhibit_case_update_one() {
has_args 1 "$@"
local line=$1
# ensure we found a tab
if [ "${line/\|/}" = "$line" ]; then
warn "bad line: $line"
return 0
fi
local exhibit=${line%%|*}
local -a binders=( ${line#*|} )
for binder in "${binders[@]}"; do
local bdir="$casedir/binders/$binder"
[ -d "$bdir" ] || error "$binder: binder does not exist"
file_mkdir "$bdir/$exhibit"
run_rsync --archive "$exhibit" "$bdir/$exhibit"
done
}
exhibit_case_generate() {
local tmp
tmp=$(cmd_tempfile)
exhibit_binder_list >"$tmp"
local -a binders
readarray -t binders <"$tmp"
for binder in "${binders[@]}"; do
exhibit_binder_generate "$binder"
done
}
######
# Review
exhibit_review_type_prompt() {
has_args 2 "$@"
local file=$1
local -n var=$2
local rtypeglob="text|email|image|pdf"
while read -p "Select type ($rtypeglob) or 'q' to quit: " -e $2; do
case "$var" in
(text|email|image|pdf)
return 0
;;
(q)
exit 0
;;
(*)
warn "$var: invalid type"
;;
esac
done
}
exhibit_review_type_guess() {
has_args 1 "$@"
local file=$1
info "$file: guessing file type..."
case "${file##*.}" in
(txt)
echo "text"
;;
(eml)
echo "email"
;;
(jpg|png)
echo "image"
;;
(pdf)
echo "pdf"
;;
(*)
echo "unknown"
;;
esac
}
exhibit_review_type_probe() {
has_args 1 "$@"
local file=$1
local rtype=$exhibit_review_type
if [ "$rtype" = "unknown" ]; then
rtype=$(exhibit_review_type_guess "$file")
fi
case "$rtype" in
(text|email|image|pdf)
;;
(*)
error "$rtype: unknown file type"
;;
esac
}
exhibit_review_usage() {
cat <<USAGE
Exhibit Reviewal Commands:
view, raw, pdf, summary, skip, pass, add, maybe, remove,
rescan, type, help, usage, quit
print
USAGE
}
exhibit_review_help() {
cat <<HELP
View Commands:
v|view Views the file
V|raw Views the raw file
p|pdf Views PDF version of the file
P|summary Views a summary of the file
Action Commands:
t|tag <tag>+ Add tags to the file
s|skip Skips the file for good
S|pass Skips the file for later
a|add Adds the file and marks reviews
A|maybe Adds file without marking
r|remove Removes a maybe'd file
File Type Commands:
f|filter <word>+ Filters futher exhibits by word
R|rescan Performs a fresh file type scan
T|type <type> View as specified file type
General Commands:
h|?|help Displays this help
|usage Displays command usage
HELP
}
exhibit_review_file() {
has_args 1 "$@"
local file=$1
_exhibit_review_file "$file"
local percent=$((100 * exhibit_review_n / exhibit_review_max))
app_echo "$file: review $percent% done..."
((exhibit_review_n++))
}
_exhibit_review_file() {
has_args 1 "$@"
local file=$1
for f in "${review_filters[@]}"; do
if ! grep "$f" "$file" >/dev/null; then
app_echo "$file: filter '$f' does not match"
return
fi
done
[ -f "$exhibit_review_state" ] || exhibit_review_reset
if grep -F "$file" "$exhibit_review_state" >/dev/null 2>&1; then
app_echo "$file: already reviewed, skipping..."
return
fi
local review_type=$exhibit_review_type
if ! exhibit_review_type_probe "$file"; then
exhibit_review_type_prompt "$file" review_type
fi
clear
info "$file: reviewing $review_type file..."
app_echo "$file:"
exhibit_${review_type}_view_summary "$file"
local -a tags
local default='v'
local done=false
local line mark
local portion="$exhibit_review_n/$exhibit_review_max"
local prompt="Reviewing $portion [$default]>> "
while ! $done && read -p "$prompt" -e line; do
[ "$*" ] || line=$default
mark=false
local -a rcmd=( $line )
case "$rcmd" in
(q|quit)
exit
;;
(v|view)
exhibit_${review_type}_view "$file"
default='a'
;;
(V|raw)
exhibit_${review_type}_view_raw "$file"
default='a'
;;
(p|pdf)
exhibit_${review_type}_view_pdf "$file"
default='a'
;;
(P|summary)
exhibit_${review_type}_view_summary "$file"
;;
(s|skip|S|pass)
if [ "${#rcmd[@]}" -eq 0 ]; then
[ "$line" != 's' -a "$line" != 'skip' ] \
|| mark=true
done=true
else
warn "$rcmd: too many arguments"
fi
;;
(r|remove)
run git rm "$file"
done=true
;;
(t|tag)
tags+=( "${rcmd[@]:1}" )
mark=true
done=true
;;
(R|rescan)
exhibit_review_type_probe "$file"
default='v'
;;
(T|type)
review_type=${rcmd[1]}
default='v'
;;
(f|filter)
review_filters+=( "${rcmd[@]:1}" )
;;
(F|filters)
echo "active filters: ${review_filters[@]}"
;;
(h|help|?)
exhibit_review_help
;;
(usage|'')
exhibit_review_usage
;;
(*)
warn "$line: unknown command"
exhibit_review_usage
;;
esac
if $mark; then
if [ "${tags[*]}" ]; then
app_echo "$file: marked..."
echo "$file\t${tags[*]}" >> "$exhibit_review_state"
run git add "$file"
else
warn "$file: no tags specified"
done=false
fi
fi
done
}
exhibit_review() {
min_args 1 "$@"
for_each exhibit_review_top "$@"
}
exhibit_review_top() {
local top=$1
local exhibit_review_state="$top.tags"
local extmp
extmp=$(cmd_tempfile)
local -a file_find_opts=( -type f )
run find "$top" -type f | sort >"$extmp"
local -a exlist
readarray -t exlist <"$extmp"
[ "${exlist[*]}" ] || error "no $exhibit_review_type files found"
local -a review_filters
local exhibit_review_n=1
local exhibit_review_max=${#exlist[@]}
app_echo "Reviewing $exhibit_review_max $exhibit_review_type files..."
for_each exhibit_review_file "${exlist[@]}"
}
exhibit_review_reset() {
[ "$exhibit_review_state" ] || debug=true error
file_mkdir "$exhibit_review_state"
: > "$exhibit_review_state"
}
Generated on Tue Apr 25 21:20:58 PDT 2017 by mcsh i7 v0.18.0.