#!/usr/bin/env bash version="v1.2.4" shopt -s extglob configfiles="$HOME/.config/burrow/config $HOME/.config/burrow $HOME/.burrow" editor=${EDITOR:-vi} # vars from config config_dir_gopher="$HOME/gopher/" config_dir_recipebox="recipebox" config_dir_phlog="phlog" config_dir_topics="topics" config_gopher_server="sdf.org" config_gopher_port="70" config_gopher_root="/users/username/" config_phlog_gophermap=true config_phlog_usedate=true config_recipebox_gophermap=false config_recipebox_usedate=false config_topics_gophermap=true config_topics_usedate=false config_git_commit=false config_git_push=false config_autoindent=true config_autofold=false config_foldwidth=66 # vars from flags flag_debug=0 flag_version=0 flag_help=0 flag_noautoindent=0 # vars from args arg_options="hvd" arg_longoptions="help,version,debug,noautoindent" arg_shortlist=0 arg_recipe=0 arg_phlog=0 arg_topic=0 arg_create_config=0 arg_update_git=0 # silence directory movements pushd () { command pushd "$@" 2>/dev/null 1>&2 } popd () { command popd 2>/dev/null 1>&2 } function show_help { cat > /dev/stdout << END burrow [options] [commands] COMMANDS: phlog Create new phlog entry recipe Add new recipe to box topic Add or update a topic create-config Create a default configuration file update-git Silently pulls gopher git repo if it exists OPTIONAL FLAGS: -h, --help Show this help -v, --version Show current version info -d, --debug Debug mode END } function parse_input { parsed=$(getopt \ --options=$arg_options \ --longoptions=$arg_longoptions \ --name "$0" \ -- "$@") if [[ $? -ne 0 ]]; then die "Invalid input" 2 fi eval set -- "$parsed" while true; do case "$1" in -h|--help) flag_help=1 shift ;; -v|--version) flag_version=1 shift ;; -d|--debug) flag_debug=1 shift ;; --noautoindent) flag_noautoindent=1 shift ;; --) shift break ;; *) die "Internal error: $1" 3 ;; esac done for arg in "$@"; do argc=${arg,,} case $argc in "shortlist") arg_shortlist=1 ;; "phlog") arg_phlog=1 ;; "recipe") arg_recipe=1 ;; "topic") arg_topic=1 ;; "create-config") arg_create_config=1 ;; "update-git") arg_update_git=1 ;; *) echo "Unknown command: $arg";; esac done } function day_suffix { case $(date +%d) in 01|1|21|31) echo "st";; 02|2|22) echo "nd";; 03|3|23) echo "rd";; *) echo "th";; esac } function update_gopher_date { newdate=$(date +"%B %d$(day_suffix), %Y") sed -i "s/.*Last\ Updated:.*/ ==== Last Updated: $newdate ====/" \ "${config_dir_gopher}/gophermap" } function check_directory { if [[ ! -d "$1" ]]; then die "Missing directory: $1 aborting." 1 fi } function die { msg="$1" code="$2" # exit code defaults to 1 if [[ "$code" =~ /^[0-9]+$/ ]] ; then code=1 fi # output message to stdout or stderr based on code if [[ ! -z "$msg" ]]; then if [[ "$code" == 0 ]]; then echo "$msg" else echo "$msg" >&2 fi fi exit "$code" } function finish { if [[ -f "$temp_gophermap" ]]; then rm "$temp_gophermap" fi if [[ -f "$temp_links" ]]; then rm "$temp_links" fi if [[ -f "$temp_fold" ]]; then rm "$temp_fold" fi } trap finish EXIT function autofold { file="$1" if $config_autofold; then temp_fold=$(mktemp -t "$(basename "$0").fold.XXXXXXX") || \ die "Failed to create temporary file" 1 fold -s -w "$config_foldwidth" "$file" > "$temp_fold" cat "$temp_fold" > "$file" rm "$temp_fold" fi } function make_post { query="$1" type="$2" use_gophermap="$3" use_date="$4" update_root="$5" check_directory "$config_dir_gopher" check_directory "${config_dir_gopher}${type}" read -r -e -p "$query" title if [[ $title == "" ]]; then die "Cancelled." 0 fi type_gophermap="${config_dir_gopher}${type}/gophermap" if $use_gophermap; then title_slug=$(echo "${title}" | \ sed -E -e 's/[^[:alnum:]]/-/g' -e 's/^-+|-+$//g' | \ tr -s '-' | \ tr '[:upper:]' '[:lower:]') if $use_date; then post_dir="${config_dir_gopher}${type}/$(date +%Y%m%d)-$title_slug" post_path="${config_gopher_root}${type}/$(date +%Y%m%d)-$title_slug" else post_dir="${config_dir_gopher}${type}/$title_slug" post_path="${config_gopher_root}${type}/$title_slug" fi post_file="${post_dir}/gophermap" post_file_path="${post_path}" else post_dir="${config_dir_gopher}${type}" post_path="${config_gopher_root}${type}" title_slug=$(echo "${title}" | \ sed -E -e 's/[^[:alnum:]]/-/g' -e 's/^-+|-+$//g' | \ tr -s '-' | \ tr '[:upper:]' '[:lower:]') if $use_date; then title_slug="$(date +%Y%m%d)-${title_slug}" fi post_file="${post_dir}/${title_slug}.txt" post_file_path="${post_path}/${title_slug}.txt" fi if [[ -f $post_file ]]; then $editor "$post_file" else mkdir -p "${post_dir}" if [[ -f "${post_dir}/.template" ]]; then cat "${post_dir}/.template" > "$post_file" else { echo "----------------------------------------" echo "$title" if $use_date; then date +"%B %d$(day_suffix), %Y" fi echo "----------------------------------------" echo "" echo "" if $use_gophermap; then echo "Links:" echo "" fi } >> "$post_file" fi $editor "$post_file" if $use_gophermap; then if [[ $config_autoindent ]] && [[ $flag_noautoindent == 0 ]]; then temp_links=$(mktemp -t "$(basename "$0").links.XXXXXXX") || \ die "Failed to create temporary file" 1 sed -n '/^Links:$/,$p' "$post_file" | tail -n +2 > "$temp_links" sed -i '/^Links:$/,$d' "$post_file" autofold "$post_file" sed -i 's/^/ /' "$post_file" cat "$temp_links" >> "$post_file" rm "$temp_links" fi else autofold "$post_file" fi temp_gophermap=$(mktemp -t "$(basename "$0").gophermap.XXXXXXX") || \ die "Failed to create temporary file" 1 if $use_gophermap; then if $use_date; then # if using gophermap and date echo -e "1$(date +%Y-%m-%d) - $title\t${post_file_path}\t"\ "${config_gopher_server}\t${config_gopher_port}" > "$temp_gophermap" else # if using gophermap but not date echo -e "1$title\t${post_file_path}\t"\ "${config_gopher_server}\t${config_gopher_port}" > "$temp_gophermap" fi else if $use_date; then # if not using gophermap but using date echo -e "0$(date +%Y-%m-%d) - $title\t${post_file_path}\t"\ "${config_gopher_server}\t${config_gopher_port}" > "$temp_gophermap" else # if not using gophermap or date echo -e "0$title\t${post_file_path}\t"\ "${config_gopher_server}\t${config_gopher_port}" > "$temp_gophermap" fi fi cat "$type_gophermap" >> "$temp_gophermap" cat "$temp_gophermap" > "$type_gophermap" rm "$temp_gophermap" # sort gophermap if not using date if ! $use_date; then sort -fo "${post_dir}/gophermap" "${post_dir}/gophermap" fi if $update_root; then update_gopher_date fi if [[ $config_git_commit != false ]]; then pushd "$config_dir_gopher" git add "${post_dir}/gophermap" "${post_file}" "$type_gophermap" if $update_root; then git add "${config_dir_gopher}/gophermap" fi git commit -m "$type: $title" if [[ $config_git_push != false ]]; then git pull git push fi popd fi fi } function create_config { if [[ ! -f "$HOME/.config/burrow/config" ]] && \ [[ ! -f "$HOME/.config/burrow" ]] && \ [[ ! -f "$HOME/.burrow" ]]; then config="$HOME/.config/burrow/config" mkdir -p "$(dirname "$config")" { echo "config_dir_gopher=\"$HOME/gopher/\"" echo "" echo "config_gopher_server=\"sdf.org\"" echo "config_gopher_port=\"70\"" echo "config_gopher_root=\"/users/username/\"" echo "" echo "config_dir_phlog=\"phlog\"" echo "config_phlog_gophermap=true" echo "config_phlog_usedate=true" echo "" echo "config_dir_recipebox=\"recipebox\"" echo "config_recipebox_gophermap=false" echo "config_recipebox_usedate=false" echo "" echo "config_dir_topics=\"topics\"" echo "config_topics_gophermap=true" echo "config_topics_usedate=false" echo "" echo "config_git_commit=false" echo "config_git_push=false" echo "" echo "config_autofold=false" echo "config_foldwidth=66" echo "config_autoindent=true" } >> "$config" else echo "Configuration already exists." fi } function update_git { pushd "$config_dir_gopher" if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) ]]; then git pull -q fi popd } function main { parse_input "$@" if [[ $arg_shortlist -gt 0 ]]; then die "phlog topic recipe create-config update-git -v -h -d --version \ --help --debug --noautoindent" 0 fi if [[ $flag_version -gt 0 ]]; then echo "$version" fi if [[ $flag_help -gt 0 ]]; then show_help fi if [[ $flag_debug -gt 0 ]]; then set -x fi if [[ $arg_create_config -gt 0 ]]; then create_config fi for configfile in $configfiles; do if [[ -f $configfile ]]; then source "$configfile" fi done if [[ ${arg_update_git} -gt 0 ]]; then update_git fi if [[ ${arg_recipe} -gt 0 ]]; then make_post "What is the name of your recipe? " \ "$config_dir_recipebox" \ "$config_recipebox_gophermap" \ "$config_recipebox_usedate" \ true fi if [[ ${arg_topic} -gt 0 ]]; then make_post "What is the name of your topic? " \ "$config_dir_topics" \ "$config_topics_gophermap" \ "$config_topics_usedate" \ true fi if [[ ${arg_phlog} -gt 0 ]]; then make_post "Enter a title for your post: " \ "$config_dir_phlog" \ "$config_phlog_gophermap" \ "$config_phlog_usedate" \ true fi } main "$@"