From e9027cf92f5ff1426140a5122674edb57e70aa78 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Mon, 11 May 2026 09:09:11 -0400 Subject: [PATCH] add tweekmd alias, xndb2 db2 query function, and weekmd subcommand --- dotfiles/.bashrc | 45 +++++++++++++++++++++++++++++++++++++++++ dotfiles/bin/td | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/dotfiles/.bashrc b/dotfiles/.bashrc index 2a8fc4d..de2ab41 100644 --- a/dotfiles/.bashrc +++ b/dotfiles/.bashrc @@ -144,6 +144,7 @@ tstart() { command td start "$@"; } tstop() { command td stop; } treport() { command td report "$@"; } tweek() { command td week "$@"; } +tweekmd() { command td weekmd "$@"; } alias gr='git reset HEAD' alias gc='git commit -v' @@ -178,6 +179,50 @@ xnspa() { -f "$file" | vd - } +xndb2() { + local file candidates + + candidates=$( + lsof +D ~/.local/state/nvim/swap/ 2>/dev/null | grep -v 'lsof:' | + grep -o "/swap/.*" | + sed 's|^/swap/||' | + tr "%" "/" | + sed -E 's/\.sw[op]$//' | + grep '\.db2\.sql$' + ) + + if [[ -z "$candidates" ]]; then + echo "xndb2: no open .db2.sql nvim buffers found" >&2 + return 1 + fi + + file=$(echo "$candidates" | fzf) || return + + [[ -z "$file" ]] && return + + echo "xndb2: running $file" >&2 + + [[ -f ~/.jrqrc ]] && source ~/.jrqrc + + if [[ -z "$JR_URL_DB2" || -z "$JR_USER_DB2" || -z "$JR_PASS_DB2" ]]; then + echo "xndb2: DB2 credentials not set in ~/.jrqrc" >&2 + return 1 + fi + + local tmp + tmp=$(mktemp /tmp/xndb2_XXXXXX.csv) + + /opt/jrunner/bin/jrunner \ + -scu "$JR_URL_DB2" \ + -scn "$JR_USER_DB2" \ + -scp "$JR_PASS_DB2" \ + -sq "$file" \ + -f csv > "$tmp" + + vd "$tmp" + rm -f "$tmp" +} + # Add an "alert" alias for long running commands. Use like so: # sleep 10; alert diff --git a/dotfiles/bin/td b/dotfiles/bin/td index cddb1be..a307227 100755 --- a/dotfiles/bin/td +++ b/dotfiles/bin/td @@ -212,6 +212,57 @@ def cmd_week(args): print() print(f"Totals: completed {n_done} created {n_new} time {_fmt_dur(total_secs)}") +def _lookup_line(file, tid): + if not file or not os.path.exists(file): + return "" + try: + with open(file) as f: + for line in f: + if f"^{tid}" in line: + return line.rstrip() + except OSError: + pass + return "" + +def cmd_weekmd(args): + since = args.since or _default_since() + events = list(_scan_git(since)) + totals = _tid_totals() + if not events: + print(f"no task events since {since}"); return + by_day = defaultdict(list) + for ts, kind, tid, file, desc in events: + by_day[ts[:10]].append((ts, kind, tid, file, desc)) + marker = {"done": "[x]", "new": "[ ]", "done+new": "[+]", "reopen": "[o]"} + n_done = n_new = total_secs = 0 + counted_tids = set() + rows = [] + for day in sorted(by_day): + dt = datetime.fromisoformat(day) + day_label = dt.strftime("%a %Y-%m-%d") + first = True + for ts, kind, tid, file, desc in by_day[day]: + t = totals.get(tid, 0) + raw = _lookup_line(file, tid) or desc + line = re.sub(r"^\s*-\s*\[.\]\s*", "", raw) + line = re.sub(r"\s*\^\S+.*$", "", line).strip() + rows.append((day_label if first else "", marker.get(kind, "?"), tid, _fmt_dur(t) if t else "", file, line)) + first = False + if kind in ("done", "done+new"): n_done += 1 + if kind in ("new", "done+new"): n_new += 1 + if tid not in counted_tids: + counted_tids.add(tid); total_secs += t + print(f"# Week since {since}\n") + print("| Day | | TID | Time | File | Task |") + print("|-----|---|-----|------|------|------|") + for day_label, mk, tid, dur, file, line in rows: + dl = day_label.replace("|", "\\|") + fn = file.replace("|", "\\|") + ln = line.replace("|", "\\|") + print(f"| {dl} | {mk} | {tid} | {dur} | {fn} | {ln} |") + print() + print(f"**Totals:** completed {n_done} · created {n_new} · time {_fmt_dur(total_secs)}") + def main(): p = argparse.ArgumentParser(prog="td", description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) sp = p.add_subparsers(dest="cmd", required=True) @@ -221,6 +272,7 @@ def main(): sp.add_parser("current").set_defaults(func=cmd_current) sp.add_parser("tidgen").set_defaults(func=cmd_tidgen) s = sp.add_parser("week"); s.add_argument("--since", default=None); s.set_defaults(func=cmd_week) + s = sp.add_parser("weekmd"); s.add_argument("--since", default=None); s.set_defaults(func=cmd_weekmd) args = p.parse_args() args.func(args)