#!/bin/sh set -eu usage() { printf 'Usage: %s -p PROFILE -c "COMMAND"\n' "$0" } help() { echo ' Options: -p profile to be used for gathering and storing data -c command to be run, reading from STDIN, writing to STDOUT See manpages for more information.' } missing() { printf 'Missing option: %s\n' "$1" >&2 } # shellcheck disable=2068 for flag in $@; do if [ "$flag" = '--help' ]; then usage help exit 0 fi done COMMANDFLAG= PROFILEFLAG= while getopts 'hc:p:' name; do case "$name" in c) COMMANDFLAG="$OPTARG" ;; p) PROFILEFLAG="$OPTARG" ;; h) usage help exit 0 ;; *) echo "Ignoring unrecognized flag '$name'" >&2 ;; esac done if [ -z "$COMMANDFLAG" ]; then missing '-c "COMMAND"' usage >&2 exit 2 fi if [ -z "$PROFILEFLAG" ]; then missing '-p PROFILE' usage >&2 exit 2 fi COMMAND="$COMMANDFLAG" PROFILE="${XDG_DATA_HOME:-$HOME/.local/share/remembering}/$PROFILEFLAG" if [ ! -e "$PROFILE" ]; then mkdir -p "$(dirname "$PROFILE")" touch "$PROFILE" fi MERGED="$(mktemp)" FILTERED="$(mktemp)" SORTED_STDIN="$(mktemp)" cat | sort -u > "$SORTED_STDIN" xargs printf '0:%s\n' < "$SORTED_STDIN" | \ sort -t: -k2,2 -m - "$PROFILE" | \ tac | \ sort -t: -k2,2 -u > "$MERGED" xargs printf 'filter_marker:%s\n' < "$SORTED_STDIN" | \ cat - "$PROFILE" | \ sort -t: -k2,2 | \ awk '{ split($0, l, ":") rank = l[1] entry = substr($0, length(rank) + 2) if (rank != "filter_marker") { prev_rank = rank prev_entry = entry } else { if (prev_entry == entry) { print prev_rank ":" entry } else { print "0:" entry } } }' > "$FILTERED" CHOICE="$(sort -t: -k1nr,1 -k2,2 < "$FILTERED" | \ cut -d: -f2- | \ sh -c "$COMMAND")" if [ -n "$CHOICE" ]; then NEW_PROFILE="$(mktemp)" awk -v choice="$CHOICE" '{ split($0, l, ":") rank = l[1] entry = substr($0, length(rank) + 2) if (entry == choice) { # Naively increment ranking by one print rank + 1 ":" entry } else { print rank ":" entry } }' "$MERGED" > "$NEW_PROFILE" mv "$NEW_PROFILE" "$PROFILE" echo "$CHOICE" fi