#!/bin/sh ## twerk: a twtxt client # by Case Duckworth ### Entry point usage() { cat >&2 < tee -a \`. parameters: FILE List of twtxt feeds to fetch, one feed per line. Optionally, a string after the feed URL will be its display name. EOF exit "${1:-0}" } configure() { # defaults TWERK_WIDTH="${TWERK_WIDTH:-72}" TWERK_LIMIT="${TWERK_LIMIT:-25}" TWERK_INCLUDE_TIME="${TWERK_INCLUDE_TIME:-0}" TWERK_USER_WIDTH="${TWERK_USER_WIDTH:-12}" TWERK_HANG="${TWERK_HANG:-}" # empty to calculate off other variables TWERK_FORCE="${TWERK_FORCE:-false}" TWERK_POST_COMMAND="${TWERK_POST_COMMAND:-:}" # no-op while getopts htfn:w:W:i:p:c: opt do case "$opt" in h) usage ;; t) TWERK_INCLUDE_TIME=1 ;; f) TWERK_FORCE=true ;; n) TWERK_LIMIT="$OPTARG" ;; w) TWERK_WIDTH="$OPTARG" ;; W) TWERK_USER_WIDTH="$OPTARG" ;; i) TWERK_HANG="$OPTARG" ;; p) TWERK_POST_COMMAND="$OPTARG" ;; c) TWERK_FEEDS="$OPTARG" ;; *) usage 1 ;; esac done if test -z "$TWERK_HANG" then TWERK_HANG=$((TWERK_USER_WIDTH+(TWERK_INCLUDE_TIME*6)+10+3)) echo >&2 "$TWERK_HANG" fi } main() { TWERK_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/twerk" mkdir -p "$TWERK_CACHE" TWERK_FILE="$TWERK_CACHE/:file:" TWERK_LESSKEY="$TWERK_CACHE/:lesskey:" lesskey_setup if "$_TWERK_INITIAL" then configure "$@" shift "$((OPTIND - 1))" TWERK_FEEDS="$1" fi cat "$TWERK_FEEDS" | fetch_posts | sort_posts | limit_posts "$TWERK_LIMIT" | format_posts > "$TWERK_FILE" read_posts "$TWERK_FILE" } ### Library fetch_posts() { while read -r url name do if test -z "$name" then file="$TWERK_CACHE/$(url_normalize "$name")" else file="$TWERK_CACHE/$name" fi if "$TWERK_FORCE" || test -z "$(find "$file" -prune -mtime -1 2>/dev/null)" then printf >&2 'Downloading %s...\n' "$url" curl -sf "$url" | filter_lines | while read -r date post do printf '%s\t%s\t%s\t%s\n' \ "$date" "$name" "$url" "$post" done | tee "$file" else cat "$file" fi done } url_normalize() { printf '%s\n' "$1" | tr -d ':/~' } filter_lines() { while read -r line do case "$line" in \#*) ;; '') ;; *) printf '%s\n' "$line" ;; esac done } limit_posts() { ln=0 while read -r line do if test "$1" -ne 0 && test "$ln" -gt "$1" then break fi printf '%s\n' "$line" ln=$((ln+1)) done } sort_posts() { sort -r } format_posts() { while IFS=' ' read -r date name url post do if test 0 -eq "$TWERK_INCLUDE_TIME" then TWERK_DATE_WIDTH=10 date="${date%T*}" else TWERK_DATE_WIDTH=16 fi printf "%${TWERK_DATE_WIDTH}s | %${TWERK_USER_WIDTH}s | " \ "$(echo "$date" | head -c$TWERK_DATE_WIDTH)" \ "$(echo "$name" | head -c$TWERK_USER_WIDTH)" export url name date post TWERK_WIDTH TWERK_HANG export linewidth="$TWERK_HANG" printf '%s\n' "$post" | tr ' ' '\n' | while IFS= read word do if test $(( linewidth + ${#word} )) -ge "$TWERK_WIDTH" then echo linewidth=0 printf "%${TWERK_HANG}s \` " "" linewidth=$((linewidth+TWERK_HANG+2)) fi printf '%s ' "$word" linewidth=$((linewidth + ${#word})) done echo done } lesskey_setup() { # t will exit with code 48 if ! test -r "$TWERK_LESSKEY" then lesskey -o "$TWERK_LESSKEY" - <&2 read -r post echo >&2 post="$(printf '%s\t%s\n' "$(date +'%FT%T%z')" "$post")" eval "printf '%s\n' \"\$post\" | $TWERK_POST_COMMAND" _TWERK_INITIAL=false main "$TWERK_FEEDS" } refresh() { TWERK_FORCE=true main "$TWERK_FEEDS" } ################################### _TWERK_INITIAL=true test -z "$DEBUG" || set -x test -z "$SOURCE" && main "$@"