diff options
| -rw-r--r-- | .config/timewarrior/extensions/__pycache__/common.cpython-313.pyc | bin | 0 -> 1735 bytes | |||
| -rw-r--r-- | .config/timewarrior/extensions/common.py | 30 | ||||
| -rwxr-xr-x | .config/timewarrior/extensions/total | 38 | ||||
| -rwxr-xr-x | .config/timewarrior/extensions/waybar | 52 | ||||
| -rw-r--r-- | .config/timewarrior/timewarrior.cfg | 24 | ||||
| -rwxr-xr-x | bin/dots | 4 | ||||
| -rwxr-xr-x | bin/equery-fuzzy | 16 | ||||
| -rwxr-xr-x | bin/git-sync | 38 | ||||
| -rwxr-xr-x | bin/grimshot | 15 | ||||
| -rwxr-xr-x | bin/ntfm | 38 | ||||
| -rwxr-xr-x | bin/screenrec | 28 |
11 files changed, 283 insertions, 0 deletions
diff --git a/.config/timewarrior/extensions/__pycache__/common.cpython-313.pyc b/.config/timewarrior/extensions/__pycache__/common.cpython-313.pyc new file mode 100644 index 0000000..eafdadc --- /dev/null +++ b/.config/timewarrior/extensions/__pycache__/common.cpython-313.pyc Binary files differdiff --git a/.config/timewarrior/extensions/common.py b/.config/timewarrior/extensions/common.py new file mode 100644 index 0000000..19467cb --- /dev/null +++ b/.config/timewarrior/extensions/common.py @@ -0,0 +1,30 @@ +import fileinput, json, sys +import datetime + +def loadstdin() -> (any, any): + meta = {} + data = [] + + for line in fileinput.input(encoding='utf-8'): + mp = line.removesuffix('\n').split(': ') + if len(mp) == 2: + meta[mp[0]] = mp[1] + + if line == "[\n" or len(data) != 0: + data.append(line) + + pass + + return (meta, json.loads("".join(data))) + + +def dumpstdout(output) -> None: + print(json.dumps(output), end='') + + +def parse_timedelta(s: str) -> datetime.timedelta: + t = datetime.datetime.strptime(s, '%H:%M') + return datetime.timedelta(hours=t.hour, minutes=t.minute) + +if __name__ == "__main__": + sys.exit(1) diff --git a/.config/timewarrior/extensions/total b/.config/timewarrior/extensions/total new file mode 100755 index 0000000..8742b68 --- /dev/null +++ b/.config/timewarrior/extensions/total @@ -0,0 +1,38 @@ +#!/bin/env python3 + +from common import loadstdin, dumpstdout, parse_timedelta +from datetime import datetime, timezone, timedelta +from os import getenv +from math import ceil + +RATE = int(getenv('REPORT_RATE', '0')) +BILL = parse_timedelta(getenv('REPORT_BILL', '1:00')) + +def timedelta_ceil(dur: timedelta, diff: timedelta) -> timedelta: + delta = ceil(dur.total_seconds() / diff.total_seconds()) * diff.total_seconds() - dur.total_seconds() + return timedelta(seconds=(dur.total_seconds() + delta)) + + +def main() -> None: + # parse stdin json + meta, data = loadstdin() + + # calc total + total = timedelta(0) + for e in data: + startt = datetime.fromisoformat(e['start']) + endt = datetime.fromisoformat(e['end']) + total += endt - startt + + # calc amount + total_billable = timedelta_ceil(total, BILL) + total_amount = (total_billable.total_seconds() / 3600) * RATE + + # presentation + print(f"total => {total}") + print(f"bill => {total_billable}") + print(f"{total_billable} @ {RATE} EUR => {total_amount} EUR") + + +if __name__ == "__main__": + main() diff --git a/.config/timewarrior/extensions/waybar b/.config/timewarrior/extensions/waybar new file mode 100755 index 0000000..45e3f03 --- /dev/null +++ b/.config/timewarrior/extensions/waybar @@ -0,0 +1,52 @@ +#!/bin/env python3 + +import fileinput, json +from datetime import datetime, timezone, timedelta + +ICO="" +CLS="timew" +ALT="timew" + +def main() -> None: + # only read actual json + input = [] + for line in fileinput.input(encoding='utf-8'): + if len(input) != 0: + input.append(line) + + if line == "[\n": + input = [line] + + pass + + # parse json + input = json.loads("".join(input)) + + # filter for active trackers + input = list(filter(lambda x: not "end" in x, list(input))) + + # exit early if no tracker is running + if len(input) == 0: + output = {} + else: + # pick first + input = input[0] + # parse start + startt = datetime.fromisoformat(input['start']) + # get now + nowt = datetime.now(timezone.utc); + # round away microseconds + nowt = nowt.replace(microsecond=0) + # calc diff + diff = nowt - startt.astimezone(timezone.utc) + # make output + output = { + 'text': f"{ICO} {diff} {",".join(input['tags'])}", + 'class': CLS, + 'alt': ALT, + } + + print(json.dumps(output), end='') + +if __name__ == "__main__": + main() diff --git a/.config/timewarrior/timewarrior.cfg b/.config/timewarrior/timewarrior.cfg new file mode 100644 index 0000000..25f8573 --- /dev/null +++ b/.config/timewarrior/timewarrior.cfg @@ -0,0 +1,24 @@ +define exclusions: + monday = <10:00 + tuesday = <10:00 + wednesday = <09:00 + thursday = <10:00 + friday = <09:00 + saturday = >00:00 + sunday = >00:00 + + +define theme: + colors: + today = white + holiday = gray4 + label = gray8 + ids = cyan + exclusion = "gray4 on gray2" + + palette: + color01 = "black on yellow" + color02 = "black on red" + color03 = "black on blue" + color04 = "black on green" + color05 = "black on magenta" diff --git a/bin/dots b/bin/dots index cee0d73..7076ece 100755 --- a/bin/dots +++ b/bin/dots @@ -25,4 +25,8 @@ push) $0 git push inazuma || true $0 git push origin || true ;; +untracked) + shift + exec $0 git ls-files -o $* + ;; esac diff --git a/bin/equery-fuzzy b/bin/equery-fuzzy new file mode 100755 index 0000000..1f0202a --- /dev/null +++ b/bin/equery-fuzzy @@ -0,0 +1,16 @@ +#!/bin/sh +set -eu +rel="equery list -f -op -F '[\$location] \$category/\$name-\$fullversion::\$repo' {q} || :" +opn="echo {2}" +pre="equery -N meta {2} && hr && equery -N uses {2}" +exec fzf --layout=reverse --height='~60%' \ + --disabled \ + --ansi \ + --query "${1:-portage}" \ + --accept-nth="2" \ + --preview="$pre" \ + --preview-window=down,wrap \ + --bind=start:reload:"$rel" \ + --bind=change:reload:"$rel" \ + --bind=tab:replace-query \ + --bind=enter:replace-query+become:"$opn" diff --git a/bin/git-sync b/bin/git-sync new file mode 100755 index 0000000..b18c94d --- /dev/null +++ b/bin/git-sync @@ -0,0 +1,38 @@ +#!/bin/bash +set -eu +[ -n "${DEBUG:-}" ] && set -x + +# use cli arg +base_branch=${1:-} + +# detect base branch (when git-new was used) +[ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/bases/"$(git symbolic-ref --short HEAD)" 2>/dev/null || :) + +# detect trunk via origin/HEAD +[ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null || :) + +# fallback to base branch => current branch +[ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short HEAD 2>/dev/null || :) + +# resolve upstream +if [[ "$base_branch" = "origin/"* ]]; then + upstream=$base_branch +else + upstream=$(git rev-parse --abbrev-ref --symbolic-full-name "$base_branch"'@{u}') +fi + +[ -n "${base_branch:?}" ] || exit 1 +[ -n "${upstream:?}" ] || exit 1 + +echo "Syncing with $upstream (base: $base_branch)" + +# fetch upstream +git fetch ${upstream/\// } + +# check if base and upstream have diverged +if ! git diff --quiet "$upstream" "$base_branch"; then + git diff --stat "$upstream" "$base_branch" +fi + +# rebase +git rebase --interactive "$upstream" diff --git a/bin/grimshot b/bin/grimshot new file mode 100755 index 0000000..b946c27 --- /dev/null +++ b/bin/grimshot @@ -0,0 +1,15 @@ +#!/bin/sh +set -eu + +screenshot_dir=$XDG_PICTURES_DIR/screenshots +screenshot_path=$screenshot_dir/"$(date --iso-8601=seconds).png" + +mkdir -p $screenshot_dir || exit 1 + +grim -g "$(slurp)" "$screenshot_path" || exit 1 + +wl-copy --type image/png < "$screenshot_path" || exit 1 + +wl-copy --primary "$screenshot_path" || exit 1 + +fyi -a grimshot -i "$screenshot_path" "grimshot" "$screenshot_path" diff --git a/bin/ntfm b/bin/ntfm new file mode 100755 index 0000000..dd7344f --- /dev/null +++ b/bin/ntfm @@ -0,0 +1,38 @@ +#!/bin/bash +set -eu + +# shellcheck disable=2034 +description="notification manager" + +FUZL_PROMPT=ntfm +. libfuzl.sh + +main() { + local nid + + nid=$(makoctl list | + awk '/Notification/{match($0,/[0-9]+/); print substr($0,RSTART,RLENGTH) "\t" substr($0,RSTART+RLENGTH+1)}' | + fuzl_menu $FUZL_MENU_FILTER --with-nth=2 --accept-nth=1 --no-run-if-empty) + [ -n "$nid" ] || return + + fuzl_action_add menu "" "open menu" + fuzl_action_add dismiss "" "dimiss" + fuzl_action_menu "$nid" +} + +# +# actions +# + +ntfm_menu() { + local nid=${1:?} + exec makoctl menu -n "$nid" -- fuzzel -d +} + +ntfm_dismiss() { + local nid=${1:?} + exec makoctl dismiss -n "$nid" +} + + +main diff --git a/bin/screenrec b/bin/screenrec new file mode 100755 index 0000000..5324ead --- /dev/null +++ b/bin/screenrec @@ -0,0 +1,28 @@ +#!/bin/sh +set -eu + +update_waybar() { + sleep .5 + pkill -RTMIN+1 -x waybar +} + +trap '{ update_waybar & disown; }' SIGCHLD EXIT + +if [ "${1:-}" = "stop" ]; then + exec pkill -HUP -x wl-screenrec +fi + +screengrab_dir=$XDG_VIDEOS_DIR/screengrabs +screengrab_path=$screengrab_dir/"$(date --iso-8601=seconds).mkv" + +mkdir -p $screengrab_dir || exit 1 + +output=$(slurp -b '#000000aa' -c '#4E437188' -w 50 -f '%o' -or) + +update_waybar & disown + +wl-screenrec --filename="$screengrab_path" --output="$output" $@ || true + +wl-copy "$screengrab_path" + +fyi -a screenrec "screenrec" "$screengrab_path" |