From 694c2dbc6fa71ee6582bade3ecc82e7b6ace83bf Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Fri, 18 Nov 2022 00:43:10 -0300 Subject: Refactor: rewrite logic to make it simpler and faster --- src/remembering.in | 163 +++++++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 74 deletions(-) (limited to 'src/remembering.in') diff --git a/src/remembering.in b/src/remembering.in index 2ce8e9c..907ffe1 100755 --- a/src/remembering.in +++ b/src/remembering.in @@ -14,12 +14,25 @@ help() { cat <<-'EOF' Options: - -p PROFILE profile to be used for gathering and storing data - -c COMMAND command to be run, reading from STDIN, writing to STDOUT - -h, --help show this help - -V, --version print the version number + -p PROFILE profile to be used for gathering and storing + data (default: create one based on $PWD) + -h, --help show this message + -V, --version print the version number - See "man remembering" for more information. + COMMAND command to be ran, reading from + STDIN, writing to STDOUT + + + Explanation FIXME. + + See "man @NAME@" for more information. + + + Examples: + + FIXME: + + $ FIXME EOF } @@ -27,10 +40,24 @@ version() { printf '%s %s %s\n' '@NAME@' '@VERSION@' '@DATE@' } -missing() { - printf 'Missing option: %s\n' "$1" + +uuid() { + od -xN20 /dev/urandom | + head -n1 | + awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' +} + +tmpname() { + echo "${TMPDIR:-/tmp}/@NAME@.tmpfile.$(uuid)" } +mkstemp() { + name="$(tmpname)" + touch "$name" + echo "$name" +} + + for flag in "$@"; do case "$flag" in --) @@ -50,15 +77,11 @@ for flag in "$@"; do esac done -COMMANDFLAG= -PROFILEFLAG= -while getopts 'hc:p:V' name; do - case "$name" in - c) - COMMANDFLAG="$OPTARG" - ;; +PROFILE_NAME="$(pwd | tr '/' '!')" +while getopts 'p:hV' flag; do + case "$flag" in p) - PROFILEFLAG="$OPTARG" + PROFILE_NAME="$OPTARG" ;; h) usage @@ -75,76 +98,68 @@ while getopts 'hc:p:V' name; do ;; esac done +shift $((OPTIND - 1)) -if [ -z "$COMMANDFLAG" ]; then - missing '-c COMMAND' >&2 - usage >&2 - exit 2 -fi -if [ -z "$PROFILEFLAG" ]; then - missing '-p PROFILE' >&2 +if [ $# = 0 ]; then + printf 'Missing "-- COMMAND"\n' >&2 usage >&2 exit 2 fi -COMMAND="$COMMANDFLAG" -PROFILE="${XDG_DATA_HOME:-$HOME/.local/share}/remembering/$PROFILEFLAG" +NAME='@NAME@' +PROFILE="${XDG_DATA_HOME:-$HOME/.local/share}"/$NAME/"$PROFILE_NAME" if [ ! -e "$PROFILE" ]; then mkdir -p "$(dirname "$PROFILE")" touch "$PROFILE" fi -MERGED="$(mktemp)" -FILTERED="$(mktemp)" -SORTED_STDIN="$(mktemp)" -cat - > "$SORTED_STDIN" - -# sed line to reverse lines, replacing GNU/Linux's tac -# Taken from: -# https://unix.stackexchange.com/questions/280685/reverse-sequence-of-a-file-with-posix-tools/280686#comment601716_280686 -xargs -I{} printf '0:%s\n' "{}" < "$SORTED_STDIN" | \ - sort -t: -k2,2 -m - "$PROFILE" | \ - sed '1!x;H;1h;$!d;g' | \ - sort -t: -k2,2 -u > "$MERGED" - -xargs -I{} 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 - } +NEXT_PROFILE="$PROFILE".tmp +MERGED="$(mkstemp)" +FILTERED="$(mkstemp)" +trap 'rm -f "$NEXT_PROFILE" "$MERGED" "$FILTERED"' EXIT +CHOICE="$( + cat - | + sed 's/^/0 stdin /' | + sort -k3 -k1nr - "$PROFILE" | + tee "$MERGED" | + awk ' + { rest = substr($0, 3 + length($1) + length($2)) } + $2 == "profile" { seen[rest] += $1 } + $2 == "stdin" { printf "%s %s\n", seen[rest]+0, rest } + ' | + sort -k1nr | + cut -d' ' -f2- | + "$@" +)" + +if [ -z "$CHOICE" ]; then + exit +fi + +cat "$MERGED" | + cut -d' ' -f1,3- | + uniq -f1 | + awk -vCHOICE="$CHOICE" ' + BEGIN { inc = 1 } + + { rest = substr($0, 2 + length($1)) } + + rest == CHOICE { + printf "%s profile %s\n", $1 + inc, rest + found = 1 + next } - }' > "$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 + + { printf "%s profile %s\n", $1, rest } + + END { + if (!found) { + printf "%s profile %s\n", 0 + inc, CHOICE + } } - }' "$MERGED" > "$NEW_PROFILE" - mv "$NEW_PROFILE" "$PROFILE" - printf '%s\n' "$CHOICE" -fi + ' > "$NEXT_PROFILE" + +mv "$NEXT_PROFILE" "$PROFILE" +printf '%s\n' "$CHOICE" -- cgit v1.2.3