From 2cd48b9a51565a2b5831f62306ca88f061425b40 Mon Sep 17 00:00:00 2001 From: Mitchell Riedstra Date: Fri, 27 Jan 2023 21:15:20 -0500 Subject: Initial --- .gitignore | 2 + Makefile | 7 ++ pm | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 61 +++++++++++++++ strftime.c | 65 ++++++++++++++++ 5 files changed, 383 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100755 pm create mode 100644 readme.md create mode 100644 strftime.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..50152f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +ses.vim +strftime diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dbfbcff --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +PREFIX ?= /usr/local + +all: strftime + +install: strftime + install -m 755 strftime $(PREFIX)/bin/strftime + install -m 755 pm $(PREFIX)/bin/pm diff --git a/pm b/pm new file mode 100755 index 0000000..6993f9f --- /dev/null +++ b/pm @@ -0,0 +1,248 @@ +#!/bin/sh +# Copyright (c) 2023 Mitchell Riedstra +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +set -e +PASTE_MANAGER_FILE=~/.pastes +PASTE_MANAGER_LINES="${PASTE_MANAGER_LINES:-30}" +PASTE_MANAGER_X_SELECTION="${PASTE_MANAGER_X_SELECTION:-clipboard}" + +# Pretty much anything that implements a demu like interface should work here, +# the only option called elsewhere is `-p` +_menu="dmenu -l $PASTE_MANAGER_LINES -i $DMENU_FLAGS" + +# This awk script controls how the output is formatted, which, will probably +# be quite unwieldly if you don't have a fuzzy finder patch in dmenu. +#shellcheck disable=SC2016 +awkPrettyPrint=' +BEGIN{ + FS="::"; +} +{ + # "strftime \"%H:%M:%S %m.%d.%y\" " $2 | getline created; + "strftime \"%H:%M:%S %m.%d.%y\" " $3 | getline updated; + printf("ID: %s Updated %s Name: %-60s Content: %s\n", + $1, updated, $4, $5); +}' + +genid() { + { dd if=/dev/urandom 2>/dev/null | tr -C -d 'a-zA-Z0-9'; echo; } \ + | fold -w 8 | sed 1q +} + +getFifo() { + _p="$(mktemp)" + rm -f "$_p" + sleep 0.1 + mkfifo "$_p" + echo "$_p" +} + +tmpdir() { + _t=$(mktemp) + rm -f "$_t" + mkdir "$_t" + echo "$_t" +} + +_clip() { +case $(uname) in +Darwin) + pbcopy +;; +*) + xclip -selection "$PASTE_MANAGER_X_SELECTION" +:; +esac +} + +insert() { + exec <&- + + $_menu -p "Enter name: " > "$_fifo" & + name="$(tr -d '\n' < "$_fifo")" + [ -z "$name" ] && exit 1 + + $_menu -p "Enter content: " > "$_fifo" & + content="$(tr -d '\n' < "$_fifo")" + [ -z "$content" ] && exit 1 + + printf "%s::%s::%s::%s::%s\n" \ + "$(genid)" "$(date +%s)" "$(date +%s)" "$name" "$content" \ + >> "$PASTE_MANAGER_FILE" +} + +sel() { + awk "$awkPrettyPrint" < "$PASTE_MANAGER_FILE" \ + | $_menu -p "$@" \ + | sed -re 's/^ID: ([^ ]*).*$/\1/' +} + +selectName() { + id="$1"; shift + awk -F:: -v "id=$id" '{ + if (id == $1) { + print $4 + } + }' < "$PASTE_MANAGER_FILE" \ + | sed 1q \ + | tr -d '\n' +} + +selectContent() { + id="$1"; shift + awk -F:: -v "id=$id" '{ + if (id == $1) { + print $5 + } + }' < "$PASTE_MANAGER_FILE" \ + | sed 1q \ + | tr -d '\n' +} + +copy() { + sel "Will copy content" > "$_fifo" & + read -r id < "$_fifo" + selectContent "$id" \ + | _clip +} + +copyName() { + sel "Will copy entry name" > "$_fifo" & + read -r id < "$_fifo" + selectName "$id" \ + | _clip +} + +_type() { + sel "Will type content" > "$_fifo" & + read -r id < "$_fifo" + selectContent "$id" \ + | xdotool type --delay 1ms --clearmodifiers --file - +} + +typeName() { + sel "Will type entry name" > "$_fifo" & + read -r id < "$_fifo" + selectName "$id" \ + | xdotool type --delay 1ms --clearmodifiers --file - +} + +rename() { + sel "Item to rename" > "$_fifo" & + read -r id < "$_fifo" + item="$(grep "^$id" "$PASTE_MANAGER_FILE" | awk "$awkPrettyPrint" )" + name="$(selectName "$id")" + $_menu -p "Currently: ( $name ) New Name" > "$_fifo" & + read -r name < "$_fifo" + cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak + awk -F:: -v id="$id" -v name="$name" ' + BEGIN { OFS="::"; } + { + if ( $1 == id ) { + "date +%s" | getline now; + $3 = now; + $4 = name; + } + print $0; + }'< "$PASTE_MANAGER_FILE".bak > "$PASTE_MANAGER_FILE" +} + +update() { + sel "Item to update" > "$_fifo" & + read -r id < "$_fifo" + item="$(grep "^$id" "$PASTE_MANAGER_FILE" | awk "$awkPrettyPrint" )" + output="$(selectContent "$id")" + $_menu -p "Currently: ( $output ) New Content" > "$_fifo" & + read -r content < "$_fifo" + cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak + awk -F:: -v id="$id" -v content="$content" ' + BEGIN { OFS="::"; } + { + if ( $1 == id ) { + "date +%s" | getline now; + $3 = now; + $5 = content; + } + print $0; + }'< "$PASTE_MANAGER_FILE".bak > "$PASTE_MANAGER_FILE" +} + +delete() { + sel "Item to delete" > "$_fifo" & + read -r id < "$_fifo" + item="$(grep "^$id" "$PASTE_MANAGER_FILE" | awk "$awkPrettyPrint" )" + echo Item: "$item"' +yes +no' | $_menu -p "Are you sure?" > "$_fifo" & + read -r resp < "$_fifo" + if [ "$resp" = "yes" ] ; then + cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak + sed '/^'"$id"/d < "$PASTE_MANAGER_FILE".bak > "$PASTE_MANAGER_FILE" + fi +} + +actions='insert +type +copy +typeName +copyName +delete +rename +update' + +menu() { + echo "$actions" | $_menu -p "Command:" \ + | { + read -r action; + runAction "$action"; + } +} + +runAction() { +action="${1:-menu}" +case $1 in + insert) action=insert; shift ;; + type) action=_type; shift ;; + typeName) action=typeName; shift ;; + copy) action=copy; shift ;; + copyName) action=copyName; shift ;; + delete) action=delete; shift ;; + rename) action=rename; shift ;; + update) action=update; shift ;; + menu) action=menu; shift ;; + *) help ;; +esac + +$action "$@" +} + +help() { +cat < +#include +#include +#include + + +void +help() +{ + puts("strftime [timestamp]"); + exit(1); +} + +int +main(int argc, char **argv) { + time_t t = time(NULL); + char **a = argv+1; + struct tm *tm; + char *fmt; + char out[256] = {0}; + + if (!*a) { + help(); + } + + fmt = *a; + a++; + + if (*a) { + errno = 0; + t = strtol(*a, NULL, 10); + if (errno != 0) { + perror("strtol"); + exit(1); + } + } + + tm = localtime(&t); + + if (strftime(out, 256, fmt, tm) == 0) { + perror("strftime"); + exit(1); + } + + puts(out); +} -- cgit v1.2.3