diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2026-08-02 14:48:29 +0200 |
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2026-08-02 14:48:29 +0200 |
| commit | e43eb1177872f52e949fb5f0f93396ed94b0d093 (patch) | |
| tree | 78b73af6a989fa2996d71b112e161b70d35081ef /home/dot_local/share/bin | |
| parent | 2f14a896e4b897bd747c24d7ad8e9e7bb3237d03 (diff) | |
move to chezmoi
Diffstat (limited to 'home/dot_local/share/bin')
86 files changed, 1961 insertions, 0 deletions
diff --git a/home/dot_local/share/bin/executable_16 b/home/dot_local/share/bin/executable_16 new file mode 100644 index 0000000..f8cc49f --- /dev/null +++ b/home/dot_local/share/bin/executable_16 @@ -0,0 +1,3 @@ +#!/bin/sh +python3 -c 'import sys ; print(f"{int(sys.stdin.read().strip()):x}")' + diff --git a/home/dot_local/share/bin/executable_= b/home/dot_local/share/bin/executable_= new file mode 100644 index 0000000..5e69f91 --- /dev/null +++ b/home/dot_local/share/bin/executable_= @@ -0,0 +1,45 @@ +#!/bin/python3 -- +from sys import argv as _argv +from os import environ as _environ, path as _path +from math import * + +_ans_path = _path.join(_environ["XDG_CACHE_HOME"], "calc_ans") +try: + _ans_file = open(_ans_path, "r+") +except: + _ans_file = open(_ans_path, "w+") +_exit_code = 0 + +ans = 0 +try: + _ans_str = _ans_file.read() + if "." in _ans_str: + ans = float(_ans_str) + else: + ans = int(_ans_str) +except: + pass + +deg = pi / 180 + +MIN = min +MAX = max +BIT = lambda n: 1 << n +GENMASK = lambda h, l: (BIT(MAX(h, l) + 1) - 1) ^ (BIT(MIN(h, l)) - 1) +KB = lambda x: x << 10 +MB = lambda x: x << 20 +GB = lambda x: x << 30 + +try: + ans = eval(" ".join(_argv[1:])) + print(ans) +except: + pass + +_ans_file.truncate(0) +_ans_file.seek(0) +_ans_file.write(str(ans)) +_ans_file.close() + +exit(_exit_code) + diff --git a/home/dot_local/share/bin/executable_addtoqueue b/home/dot_local/share/bin/executable_addtoqueue new file mode 100644 index 0000000..535e250 --- /dev/null +++ b/home/dot_local/share/bin/executable_addtoqueue @@ -0,0 +1,3 @@ +#!/bin/sh +exec st -T "[floating]" -g 120x20 -e fzmp + diff --git a/home/dot_local/share/bin/executable_addtorrent b/home/dot_local/share/bin/executable_addtorrent new file mode 100644 index 0000000..bf238d6 --- /dev/null +++ b/home/dot_local/share/bin/executable_addtorrent @@ -0,0 +1,41 @@ +#!/bin/sh +progname="$(basename "$0")" + +title="Torrent" +msg_ok="Torrent successfully added" +msg_err="Could not add torrent" +usage="usage: $progname URL" +err_no_seedbox="error: \$SEEDBOX_LOGIN is not set" + +case "$LANG" in + ja_JP*) + title="トレント" + msg_ok="一つのトレントを追加しました" + msg_err="トレントを追加できませんでした" + usage="用法: $progname URL" + err_no_seedbox="エラー: \$SEEDBOX_LOGINに値がありません" + ;; +esac + +die() { + echo "$1" + exit 1 +} + +[ $# -eq 0 ] && die "$usage" +[ -z "$SEEDBOX_LOGIN" ] && die "$err_no_seedbox" + +ssh "$SEEDBOX_LOGIN" transmission-remote -a "'$(echo "$1" | sed "s/'/'\\''/g")'" +if [ $? -eq 0 ]; then + msg="$msg_ok" + urgency="normal" +else + msg="$msg_err" + urgency="critical" +fi + +notify-send \ + --app-name "$title" \ + --urgency "$urgency" \ + "$title" "$msg" + diff --git a/home/dot_local/share/bin/executable_androidwifistore2pass b/home/dot_local/share/bin/executable_androidwifistore2pass new file mode 100644 index 0000000..b03eb9d --- /dev/null +++ b/home/dot_local/share/bin/executable_androidwifistore2pass @@ -0,0 +1,43 @@ +#!/bin/sh +# Use xmlstarlet and ADB to pull WifiConfigStore.xml from a (rooted) Android +# phone and import wifi network passwords into pass. Tested with a rooted pixel +# 4a (sunfish) running LineageOS 21 (Android 14) + +TAB="$(printf '\t')" + +get_wifi_cfg() { + adb shell cat /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml + if [ $? -ne 0 ] ; then + echo "note: try running \`adb root\` first" + exit 1 + fi +} + +parse_filter() { + xmlstarlet select --template \ + --match '/WifiConfigStoreData/NetworkList/Network' \ + --if './WifiConfiguration/string[@name="PreSharedKey"]' \ + --value-of './WifiConfiguration/string[@name="SSID"]' \ + --output "$TAB" \ + --value-of './WifiConfiguration/string[@name="PreSharedKey"]' \ + --nl +} + +cut_quotes() { + cut -c2- | rev | cut -c2- | rev +} + +import_pass() { + while read line; do + SSID="$(echo "$line" | cut -d"$TAB" -f1 | cut_quotes)" + PASSWD="$(echo "$line" | cut -d"$TAB" -f2 | cut_quotes)" + PASS_NAME="net/$(echo "$SSID" | tr '/' '-')/passwd" + + printf 'insert SSID "%s" as %s ...' "$SSID" "$PASS_NAME" + echo "$PASSWD" | pass insert --multiline "$PASS_NAME" 1>/dev/null 2>/dev/null + printf ' %s\n' "$([ $? -eq 0 ] && echo "OK" || echo "ERROR")" + done +} + +get_wifi_cfg | parse_filter | import_pass + diff --git a/home/dot_local/share/bin/executable_ansi2polybar b/home/dot_local/share/bin/executable_ansi2polybar new file mode 100644 index 0000000..e543ce5 --- /dev/null +++ b/home/dot_local/share/bin/executable_ansi2polybar @@ -0,0 +1,67 @@ +#!/bin/sh +# convert ansi escape codes into polybar/lemonbar color tags. this script makes +# some very dumb assumptions about which escape codes will be in the input +# stream, and is by no means complete, just good enough + +. "$XDG_CACHE_HOME/mode/state/theme" +export bg fg $(seq 0 15 | sed 's/^/color/') + +exec gawk ' +function flush_buffer() { + switch (buf) { + case 0: printf "%{T-}%{F-}%{B-}%{u-}%{o-}" ; break + case 1: printf "%{T2}" ; break + case 30: printf "%{F" ENVIRON["color0"] "}" ; break + case 31: printf "%{F" ENVIRON["color1"] "}" ; break + case 32: printf "%{F" ENVIRON["color2"] "}" ; break + case 33: printf "%{F" ENVIRON["color3"] "}" ; break + case 34: printf "%{F" ENVIRON["color4"] "}" ; break + case 35: printf "%{F" ENVIRON["color5"] "}" ; break + case 36: printf "%{F" ENVIRON["color6"] "}" ; break + case 37: printf "%{F" ENVIRON["color7"] "}" ; break + case 90: printf "%{F" ENVIRON["color8"] "}" ; break + case 91: printf "%{F" ENVIRON["color9"] "}" ; break + case 92: printf "%{F" ENVIRON["color10"] "}" ; break + case 93: printf "%{F" ENVIRON["color11"] "}" ; break + case 94: printf "%{F" ENVIRON["color12"] "}" ; break + case 95: printf "%{F" ENVIRON["color13"] "}" ; break + case 96: printf "%{F" ENVIRON["color14"] "}" ; break + case 97: printf "%{F" ENVIRON["color15"] "}" ; break + default: break + } + buf = "" +} +function reset() { + bold = 0 + buf = "" + esc = 0 +} +BEGIN { + RS = "(.)" # make awk read character by character + reset() +} +# start of escape code +esc == 0 && RT == "\x1b" { esc += 1 } + +# ignore some characters for buffering +esc > 0 && RT == "\x1b" { next } +esc > 0 && RT == "[" { next } + +esc > 0 && RT == ";" { + flush_buffer() + next +} + +# end of escape code +esc > 0 && RT == "m" { + flush_buffer() + reset() + next +} + +esc > 0 { buf = buf RT } + +# print while not reading escape code +esc == 0 { printf RT } +' + diff --git a/home/dot_local/share/bin/executable_bgcol b/home/dot_local/share/bin/executable_bgcol new file mode 100644 index 0000000..276e479 --- /dev/null +++ b/home/dot_local/share/bin/executable_bgcol @@ -0,0 +1,9 @@ +#!/bin/sh +COLOR="$1" +if [ -z "$COLOR" ] ; then + . "$XDG_CACHE_HOME/mode/state/theme" + COLOR="$bg" +fi +magick -size 1x1 "xc:$COLOR" /tmp/bgcol.png +feh --no-fehbg --bg-tile /tmp/bgcol.png +rm /tmp/bgcol.png diff --git a/home/dot_local/share/bin/executable_bootloader b/home/dot_local/share/bin/executable_bootloader new file mode 100644 index 0000000..c310d4f --- /dev/null +++ b/home/dot_local/share/bin/executable_bootloader @@ -0,0 +1,13 @@ +#!/bin/sh + +bye () { + echo "run me as root!" + exit 1 +} + +[ $(id -g) -ne 0 ] && bye + +# mount /boot +# pacman --noconfirm -S linux +grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB # --removable +grub-mkconfig -o /boot/grub/grub.cfg diff --git a/home/dot_local/share/bin/executable_brightness b/home/dot_local/share/bin/executable_brightness new file mode 100644 index 0000000..c1c6139 --- /dev/null +++ b/home/dot_local/share/bin/executable_brightness @@ -0,0 +1,29 @@ +#!/bin/sh +case "$*" in + +*) action="+" ;; + -*) action="-" ;; + *) action="=" ;; +esac +value="$(echo "$*" | tr -dc '[[:digit:]]')" + +if [ -n "$(command -v xbacklight)" ] ; then + [ "$action" = "+" ] && action="-inc" + [ "$action" = "-" ] && action="-dec" + [ "$action" = "=" ] && action="-set" + + fork xbacklight -time 100 -fps 60 $action $value + + exit 0 + +elif [ -n "$(command -v ddcutil)" ] ; then + [ "$action" = "=" ] && action="" + + for bus in 2 3 ; do + fork ddcutil --bus="$bus" --skip-ddc-checks --noverify setvcp 10 $action $value + done + + exit 0 + +fi +exit 1 + diff --git a/home/dot_local/share/bin/executable_caffeine b/home/dot_local/share/bin/executable_caffeine new file mode 100644 index 0000000..9901426 --- /dev/null +++ b/home/dot_local/share/bin/executable_caffeine @@ -0,0 +1,8 @@ +#!/bin/sh +xset s off -dpms +reset() { + trap - EXIT + xset s default +} +trap reset INT +sleep infinity diff --git a/home/dot_local/share/bin/executable_cc1080p30 b/home/dot_local/share/bin/executable_cc1080p30 new file mode 100644 index 0000000..6619a17 --- /dev/null +++ b/home/dot_local/share/bin/executable_cc1080p30 @@ -0,0 +1,2 @@ +#!/bin/sh +ccpreview 1920 1080 30 diff --git a/home/dot_local/share/bin/executable_cc720p60 b/home/dot_local/share/bin/executable_cc720p60 new file mode 100644 index 0000000..c78fe6d --- /dev/null +++ b/home/dot_local/share/bin/executable_cc720p60 @@ -0,0 +1,2 @@ +#!/bin/sh +ccpreview 1280 720 60 diff --git a/home/dot_local/share/bin/executable_ccpreview b/home/dot_local/share/bin/executable_ccpreview new file mode 100644 index 0000000..9f13acc --- /dev/null +++ b/home/dot_local/share/bin/executable_ccpreview @@ -0,0 +1,74 @@ +#!/bin/sh + +# capture card sysfs device path +SYSFS_PATH="/devices/pci0000:00/0000:00:14.0/usb1/1-12" + +# script args +WIDTH="$1" +HEIGHT="$2" +FRAMERATE="$3" + +# find audio device (pulseaudio) +PULSE_DEVICE="$(pactl -f json list sources | jq \ + --arg sysfs_path "$SYSFS_PATH" --raw-output \ + '.[] | select(.properties["sysfs.path"] | . != null and startswith($sysfs_path)) | .name')" +AUDIO_URL="av://pulse:$PULSE_DEVICE" + +# find video device (video4linux) +V4L_PATH="$(find "/sys$SYSFS_PATH" -name 'video4linux' | head -n1)" +V4L_PATH="$(find "$V4L_PATH" -name 'index' | xargs grep -l '^0$')" +V4L_PATH="$(echo "$V4L_PATH" | sed 's#/index$#/uevent#')" +VIDEO_DEVICE="$(. "$V4L_PATH" ; echo "/dev/$DEVNAME")" +VIDEO_DEVICE="$(readlink -f "$VIDEO_DEVICE")" +VIDEO_URL="av://v4l2:$VIDEO_DEVICE" + +RESOLUTION="${WIDTH}x${HEIGHT}" + +fork() { + JOBS="$JOBS $( + "$@" > /dev/null 2> /dev/null & + echo $! + )" +} + +# set capture card v4l parameters +v4l2-ctl --silent --device "$VIDEO_DEVICE" \ + --set-parm "$FRAMERATE" \ + --set-fmt-video "width=$WIDTH,height=$HEIGHT,pixelformat=MJPG" \ + --set-ctrl "brightness=0,contrast=128,saturation=128,hue=0" + +_mpv() { + fork mpv \ + --quiet --msg-level=input=no \ + --no-config --input-conf=/dev/null \ + --no-osc --no-border \ + --no-input-default-bindings --pause=no --force-seekable=no \ + --cache=no \ + "$@" +} + +# audio preview +_mpv \ + --no-demuxer-thread \ + --audio-buffer=0 \ + --cache-pause=no \ + --interpolation=no \ + --stream-buffer-size=4k \ + --profile=low-latency \ + --speed=1.001 \ + "$AUDIO_URL" + +# video preview +_mpv \ + --untimed --no-correct-pts --no-demuxer-thread \ + --profile=low-latency \ + --demuxer-lavf-o-add=input_format=mjpeg \ + --demuxer-lavf-o-add=framerate="$FRAMERATE" \ + --demuxer-lavf-o-add=resolution="$RESOLUTION" \ + --demuxer-lavf-o-add=rw_timeout=30000000 \ + --speed=1.05 \ + "$VIDEO_URL" + +sleep infinity +kill -9 -- $JOBS + diff --git a/home/dot_local/share/bin/executable_clean b/home/dot_local/share/bin/executable_clean new file mode 100644 index 0000000..8c824f1 --- /dev/null +++ b/home/dot_local/share/bin/executable_clean @@ -0,0 +1,3 @@ +#!/bin/sh +[ -n "$UB_SOCKET" ] && ueberzugpp cmd --socket "$UB_SOCKET" --action remove --identifier PREVIEW + diff --git a/home/dot_local/share/bin/executable_darkroom b/home/dot_local/share/bin/executable_darkroom new file mode 100644 index 0000000..28e2589 --- /dev/null +++ b/home/dot_local/share/bin/executable_darkroom @@ -0,0 +1,20 @@ +#!/bin/sh + +SCREENS="`xrandr | grep ' connected ' | cut -f1 -d' '`" + +mxr() { + for screen in $SCREENS; do + xrandr --output "$screen" $@ + done +} + +if [ -e "$XDG_CACHE_HOME/darkroom" ]; then + rm -f "$XDG_CACHE_HOME/darkroom" + mxr --gamma '1:1:1' +else + mkdir -p "$XDG_CACHE_HOME" + touch "$XDG_CACHE_HOME/darkroom" + killall -q redshift # redshift hijacks gamma + mxr --gamma '1:0.0001:0.0001' + lights darkroom +fi diff --git a/home/dot_local/share/bin/executable_dbg b/home/dot_local/share/bin/executable_dbg new file mode 100644 index 0000000..d042ba5 --- /dev/null +++ b/home/dot_local/share/bin/executable_dbg @@ -0,0 +1,27 @@ +#!/bin/sh +GDB="arm-none-eabi-gdb" + +found_executable=false + +while ! $found_executable ; do + [ ! -e build/zephyr ] && break + [ ! -e build/zephyr/zephyr.elf ] && break + set -- --se="build/zephyr/zephyr.elf" "$@" + + [ -e build/tfm/bin/tfm_s.elf ] && set -- "$@" --eval-command="add-symbol-file build/tfm/bin/tfm_s.elf" + + found_executable=true +done + +while ! $found_executable ; do + exec="$(find . -maxdepth 3 -name '*.elf' | head -n1)" + [ -n "$exec" ] && set -- "$@" --se="$exec" + found_executable=true + break +done + +set -- "$@" --eval-command="set jlink autoconnect on" +set -- "$@" --eval-command="set jlink watchdog on" + +exec "$GDB" "$@" + diff --git a/home/dot_local/share/bin/executable_dbg_xprop b/home/dot_local/share/bin/executable_dbg_xprop new file mode 100644 index 0000000..1aa0b0c --- /dev/null +++ b/home/dot_local/share/bin/executable_dbg_xprop @@ -0,0 +1,10 @@ +#!/bin/sh +# debug xprop +# +# runs xprop for all newly created windows (when mouse capture is not +# available) + +xev -root -1 |\ + grep --line-buffered '^CreateNotify' |\ + awk --non-decimal-data -F', ' '{ system("sleep 0.1"); printf("%d\n", substr($6, 8)); fflush(stdout) }' |\ + xargs -I{} sh -c 'echo "------ window data for window {}"; xprop -id {}' diff --git a/home/dot_local/share/bin/executable_decsync2plain b/home/dot_local/share/bin/executable_decsync2plain new file mode 100644 index 0000000..745a1c2 --- /dev/null +++ b/home/dot_local/share/bin/executable_decsync2plain @@ -0,0 +1,60 @@ +#!/bin/sh + +EXEC_NAME="$(basename "$0")" +EXTENSION="$1" + +usage() { + cat << EOF +usage: $EXEC_NAME [EXT] + +examples: + cd Decsync/calendars/$(uuidgen)/v2/DeviceName-DecSyncCC-$RANDOM ; $EXEC_NAME ics + + cd Decsync/contacts/$(uuidgen)/v2/DeviceName-DecSyncCC-$RANDOM ; $EXEC_NAME vcf + +$EXEC_NAME will attempt to guess the appropriate file extension based on the parent folder names. the first parent folder that matches exactly one of the following determines the file extension: + calendars -> .ics + contacts -> .vcf + tasks -> .ics + +if no file extension is found and none is explicitly provided, $EXEC_NAME will exit. +EOF +} + +if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then + usage + exit 0 +fi + +if [ ! -e sequences ] ; then + echo "error: could not find decsync sequences file" + exit 1 +fi + +# auto detect extension if not explicitly provided +if [ -z "$EXTENSION" ] ; then + EXTENSION="$(realpath "$PWD" | tr '/' '\n' | tac | while read -r folder ; do + case "$folder" in + calendars|tasks) echo ics ; break ;; + contacts) echo vcf ; break ;; + esac + done)" +fi + +if [ -z "$EXTENSION" ] ; then + echo "error: could not detect EXT" + exit 1 +fi + +COLLECTION_PREFIX="$(jq --raw-output 'if .[2] == "name" then "\(.[3])/" else empty end' info)" +mkdir -p "$COLLECTION_PREFIX" + +jq --raw-output '. | keys | join("\n")' sequences |\ + sed '/^info$/d' |\ + tr '\n' '\0' |\ + xargs -0 -n1 cat |\ +while read -r line ; do + filename="$COLLECTION_PREFIX$(echo "$line" | jq --raw-output '.[0][1]').$EXTENSION" + echo "$filename" + echo "$line" | jq --raw-output '.[3]' > "$filename" +done diff --git a/home/dot_local/share/bin/executable_delta b/home/dot_local/share/bin/executable_delta new file mode 100644 index 0000000..83fb629 --- /dev/null +++ b/home/dot_local/share/bin/executable_delta @@ -0,0 +1,4 @@ +#!/bin/sh +[ -e "$XDG_CACHE_HOME/mode/state/vars" ] && . "$XDG_CACHE_HOME/mode/state/vars" +[ "$mode" = "light" ] && theme="--light" || theme="--dark" +exec /bin/delta "$theme" "$@" diff --git a/home/dot_local/share/bin/executable_discord b/home/dot_local/share/bin/executable_discord new file mode 100644 index 0000000..d2f894b --- /dev/null +++ b/home/dot_local/share/bin/executable_discord @@ -0,0 +1,3 @@ +#!/bin/sh +installbd +exec /usr/bin/discord "$@" diff --git a/home/dot_local/share/bin/executable_dox-open b/home/dot_local/share/bin/executable_dox-open new file mode 100644 index 0000000..493c435 --- /dev/null +++ b/home/dot_local/share/bin/executable_dox-open @@ -0,0 +1,31 @@ +#!/bin/node + +import { glob, readFile } from 'node:fs/promises'; +import { spawn } from 'node:child_process'; +import { argv, chdir, cwd } from 'node:process'; +import { join } from 'node:path'; + +argv.shift(); +argv.shift(); +chdir("search"); + +var symbols = {}; +for await (const chunk of glob('all_*.js')) { + const contents = await readFile(chunk); + const searchData = eval(`${contents}; searchData`); + const here = cwd(); + + for (const [ _id, [ symbol, ...entry ] ] of searchData) { + symbols[symbol] = entry.map(e => `file://${join(here, e[0])}`); + } +} + +for (const symbol of argv) { + if (!(symbol in symbols)) { + console.error(`No doxygen index for symbol \`${symbol}\``); + continue; + } + const urls = symbols[symbol]; + spawn('xdg-open', [ urls[0], ]); +} + diff --git a/home/dot_local/share/bin/executable_editor b/home/dot_local/share/bin/executable_editor new file mode 100644 index 0000000..d4bf664 --- /dev/null +++ b/home/dot_local/share/bin/executable_editor @@ -0,0 +1,2 @@ +#!/bin/sh +exec nvim -p "$@" diff --git a/home/dot_local/share/bin/executable_extmon b/home/dot_local/share/bin/executable_extmon new file mode 100644 index 0000000..dcaa0b3 --- /dev/null +++ b/home/dot_local/share/bin/executable_extmon @@ -0,0 +1,26 @@ +#!/bin/sh +out_int="eDP1" +out_ext="HDMI1" +res_int="1366x768" +res_ext="1920x1080" + +off() { + xrandr \ + --output "$out_ext" --off \ + --output "$out_int" --mode "$res_int" --panning "$res_int" --transform none --primary \ + --fb "$res_int" +} + +on() { + xrandr \ + --fb "$res_ext" \ + --output "$out_int" --mode "$res_int" --panning "$res_ext" --scale-from "$res_ext" \ + --output "$out_ext" --mode "$res_ext" --scale 1x1 --same-as "$out_int" --primary +} + +[ "$1" = "on" ] && on +[ "$1" = "off" ] && off + +# reload polybar (doesn't adjust to new resolution automatically) +fork polybar-msg cmd restart + diff --git a/home/dot_local/share/bin/executable_fcitx5-temp-off b/home/dot_local/share/bin/executable_fcitx5-temp-off new file mode 100644 index 0000000..b2f8ea9 --- /dev/null +++ b/home/dot_local/share/bin/executable_fcitx5-temp-off @@ -0,0 +1,8 @@ +#!/bin/sh +mkdir -p "$XDG_DATA_HOME/fcitx5" +fcitx5-remote > "$XDG_DATA_HOME/fcitx5/state" +fcitx5-remote -n > "$XDG_DATA_HOME/fcitx5/ime_name" + +fcitx5-remote -c +fcitx5-remote -s 'keyboard-us' + diff --git a/home/dot_local/share/bin/executable_fcitx5-temp-restore b/home/dot_local/share/bin/executable_fcitx5-temp-restore new file mode 100644 index 0000000..d00b11c --- /dev/null +++ b/home/dot_local/share/bin/executable_fcitx5-temp-restore @@ -0,0 +1,7 @@ +#!/bin/sh +[ ! -e "$XDG_DATA_HOME/fcitx5/state" ] && exit +[ ! -e "$XDG_DATA_HOME/fcitx5/ime_name" ] && exit + +[ `cat "$XDG_DATA_HOME/fcitx5/state"` = "1" ] && fcitx5-remote -c +[ `cat "$XDG_DATA_HOME/fcitx5/state"` = "2" ] && fcitx5-remote -o +cat "$XDG_DATA_HOME/fcitx5/ime_name" | xargs fcitx5-remote -s diff --git a/home/dot_local/share/bin/executable_ffmpeg-resize b/home/dot_local/share/bin/executable_ffmpeg-resize new file mode 100644 index 0000000..4270278 --- /dev/null +++ b/home/dot_local/share/bin/executable_ffmpeg-resize @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Re-encode a video to a target size in MB. +# Example: +# ./this_script.sh video.mp4 15 + +T_SIZE="$2" # target size in MB +T_FILE="${1%.*}-$2MB.mp4" # filename out + +# Original duration in seconds +O_DUR=$(\ + ffprobe \ + -v error \ + -show_entries format=duration \ + -of csv=p=0 "$1") + +# Original audio rate +O_ARATE=$(\ + ffprobe \ + -v error \ + -select_streams a:0 \ + -show_entries stream=bit_rate \ + -of csv=p=0 "$1") + +# Original audio rate in KiB/s +O_ARATE=$(\ + awk \ + -v arate="$O_ARATE" \ + 'BEGIN { printf "%.0f", (arate / 1024) }') + +# Target size is required to be less than the size of the original audio stream +T_MINSIZE=$(\ + awk \ + -v arate="$O_ARATE" \ + -v duration="$O_DUR" \ + 'BEGIN { printf "%.2f", ( (arate * duration) / 8192 ) }') + +# Equals 1 if target size is ok, 0 otherwise +IS_MINSIZE=$(\ + awk \ + -v size="$T_SIZE" \ + -v minsize="$T_MINSIZE" \ + 'BEGIN { print (minsize < size) }') + +# Give useful information if size is too small +if [[ $IS_MINSIZE -eq 0 ]]; then + printf "%s\n" "Target size ${T_SIZE}MB is too small!" >&2 + printf "%s %s\n" "Try values larger than" "${T_MINSIZE}MB" >&2 + exit 1 +fi + +# Set target audio bitrate +T_ARATE=$O_ARATE + + +# Calculate target video rate - MB -> KiB/s +T_VRATE=$(\ + awk \ + -v size="$T_SIZE" \ + -v duration="$O_DUR" \ + -v audio_rate="$O_ARATE" \ + 'BEGIN { print ( ( size * 8192.0 ) / ( 1.048576 * duration ) - audio_rate) }') + +# Perform the conversion +ffmpeg \ + -y \ + -i "$1" \ + -c:v libx264 \ + -b:v "$T_VRATE"k \ + -pass 1 \ + -an \ + -f mp4 \ + /dev/null \ +&& \ +ffmpeg \ + -i "$1" \ + -c:v libx264 \ + -b:v "$T_VRATE"k \ + -pass 2 \ + -c:a aac \ + -b:a "$T_ARATE"k \ + "$T_FILE" diff --git a/home/dot_local/share/bin/executable_folder2cd b/home/dot_local/share/bin/executable_folder2cd new file mode 100644 index 0000000..558c6ab --- /dev/null +++ b/home/dot_local/share/bin/executable_folder2cd @@ -0,0 +1,23 @@ +#!/bin/sh + +FILEEXT="flac" +set -e + +convert() { + wav="${1%.flac}-cd.wav" + echo "ffmpeg -loglevel warning -y -i \"$1\" -sample_fmt s16 -ar 44100 \"$wav\"" + ffmpeg -loglevel warning -y -i "$1" -sample_fmt s16 -ar 44100 "$wav" +} + +export -f convert +parallel -j4 convert ::: *.$FILEEXT + +FILES=`find . -name '*-cd.wav' -printf '%f\n' | sort -n` +echo "$FILES" | xargs -d"\n" -t wodim -sao -audio -pad speed=20 + +echo "wodim -eject" +wodim -eject + +echo "rm -f *-cd.wav" +rm -f *-cd.wav + diff --git a/home/dot_local/share/bin/executable_fontfix b/home/dot_local/share/bin/executable_fontfix new file mode 100644 index 0000000..1c9beaf --- /dev/null +++ b/home/dot_local/share/bin/executable_fontfix @@ -0,0 +1,39 @@ +#!/bin/python3 + +import os +import sys +from pathlib import Path + +from fontTools import ttLib + +PROPID_FAMILY = 1 +PROPID_SUBFAMILY = 2 +PROPID_FULLNAME = 4 +PROPID_PSNAME = 6 + +PLATFORM_MS = 1 +PLATFORM_MAC = 3 + +# see +# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html +# for magic numbers + +for folder in Path(".").iterdir(): + print(f"{folder}/") + family_name = str(folder.stem) + for file in folder.glob("*.ttf"): + subfamily_name = file.stem.removeprefix(family_name).strip() + with ttLib.TTFont(file) as ttf: + nametable = ttf["name"] + full_name = f"{family_name} {subfamily_name}" + postscript_name = f"{family_name}-{subfamily_name}".replace(" ", "") + nametable.setName(family_name, PROPID_FAMILY, PLATFORM_MS, 0, 0) + nametable.setName(family_name, PROPID_FAMILY, PLATFORM_MAC, 1, 1033) + nametable.setName(subfamily_name, PROPID_SUBFAMILY, PLATFORM_MS, 0, 0) + nametable.setName(subfamily_name, PROPID_SUBFAMILY, PLATFORM_MAC, 1, 1033) + nametable.setName(full_name, PROPID_FULLNAME, PLATFORM_MS, 0, 0) + nametable.setName(full_name, PROPID_FULLNAME, PLATFORM_MAC, 1, 1033) + nametable.setName(postscript_name, PROPID_PSNAME, PLATFORM_MS, 0, 0) + nametable.setName(postscript_name, PROPID_PSNAME, PLATFORM_MAC, 1, 1033) + ttf.save(file) + print(f" {file.name}: [{family_name} :: {subfamily_name}]") diff --git a/home/dot_local/share/bin/executable_fork b/home/dot_local/share/bin/executable_fork new file mode 100644 index 0000000..63e7541 --- /dev/null +++ b/home/dot_local/share/bin/executable_fork @@ -0,0 +1,2 @@ +#!/bin/sh +(setsid "$@" > /dev/null 2> /dev/null &) diff --git a/home/dot_local/share/bin/executable_fv b/home/dot_local/share/bin/executable_fv new file mode 100644 index 0000000..5ce4f2e --- /dev/null +++ b/home/dot_local/share/bin/executable_fv @@ -0,0 +1,2 @@ +#!/bin/sh +fzf --multi --print0 | exec xargs -r0 $EDITOR diff --git a/home/dot_local/share/bin/executable_gpg-git b/home/dot_local/share/bin/executable_gpg-git new file mode 100644 index 0000000..df0feca --- /dev/null +++ b/home/dot_local/share/bin/executable_gpg-git @@ -0,0 +1,4 @@ +#!/bin/sh +GPG_KEY_ID="$GPG_ID_GIT" # see ~/.profile +GPG_KEY_PASSPHRASE="$(pass "gpg/$GPG_KEY_ID.asc" | head -n1)" +gpg --batch --no-tty --pinentry-mode loopback --passphrase "$GPG_KEY_PASSPHRASE" "$@" diff --git a/home/dot_local/share/bin/executable_helium-browser b/home/dot_local/share/bin/executable_helium-browser new file mode 100644 index 0000000..96e1864 --- /dev/null +++ b/home/dot_local/share/bin/executable_helium-browser @@ -0,0 +1,5 @@ +#!/bin/sh +/usr/bin/helium-browser \ + --load-extension="$XDG_CACHE_HOME/mode/chromium" \ + --password-store=basic \ + "$@" diff --git a/home/dot_local/share/bin/executable_hide b/home/dot_local/share/bin/executable_hide new file mode 100644 index 0000000..cb49be0 --- /dev/null +++ b/home/dot_local/share/bin/executable_hide @@ -0,0 +1,4 @@ +#!/bin/sh +for file in "$@" ; do + mv "$file" ".$file" +done diff --git a/home/dot_local/share/bin/executable_icalcat b/home/dot_local/share/bin/executable_icalcat new file mode 100644 index 0000000..2e89afd --- /dev/null +++ b/home/dot_local/share/bin/executable_icalcat @@ -0,0 +1,12 @@ +#!/bin/sh +cat << "EOF" +BEGIN:VCALENDAR +VERSION:2.0 +EOF + +cat "$@" | sed -n -e '/^BEGIN:VEVENT$/,/^END:VEVENT$/p' + +cat << "EOF" +END:VCALENDAR +EOF + diff --git a/home/dot_local/share/bin/executable_installbd b/home/dot_local/share/bin/executable_installbd new file mode 100644 index 0000000..ae17002 --- /dev/null +++ b/home/dot_local/share/bin/executable_installbd @@ -0,0 +1,20 @@ +#!/bin/sh +discord_path="$(dirname "$(find "$XDG_CONFIG_HOME/discord" -name core.asar)")" +discord_version="$(echo "$discord_path" | tr '/' '\n' | tac | sed -n '/^[0-9.]\+$/p' | head -n1)" +betterdiscord_path="$XDG_CONFIG_HOME/BetterDiscord/data/betterdiscord.asar" +cache_file="$XDG_CACHE_HOME/bdversion" + +if [ "$discord_path" -nt "$betterdiscord_path" ] ; then + echo "download betterdiscord.asar" + curl -sLo - 'https://betterdiscord.app/Download/betterdiscord.asar' > "$betterdiscord_path" +fi +if ! grep "$(basename "$betterdiscord_path")" "$discord_path/index.js" > /dev/null ; then + echo "patch discord desktop core index.js" + printf 'require("%s");\n%s' "$betterdiscord_path" "$(cat "$discord_path/index.js")" > "$discord_path/index.js" +fi + +# store discord version used for this install +mkdir -p "$(dirname "$cache_file")" +echo "$discord_version" > "$cache_file" + +echo "done!" diff --git a/home/dot_local/share/bin/executable_java b/home/dot_local/share/bin/executable_java new file mode 100644 index 0000000..06fdb61 --- /dev/null +++ b/home/dot_local/share/bin/executable_java @@ -0,0 +1,7 @@ +#!/bin/sh +export _JAVA_AWT_WM_NONREPARENTING=1 +exec /usr/bin/java \ + -Djava.util.prefs.userRoot="$XDG_CONFIG_HOME/java" \ + -Dawt.useSystemAAFontSettings=on \ + -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel \ + "$@" diff --git a/home/dot_local/share/bin/executable_kbindicator b/home/dot_local/share/bin/executable_kbindicator new file mode 100644 index 0000000..6ffcd53 --- /dev/null +++ b/home/dot_local/share/bin/executable_kbindicator @@ -0,0 +1,19 @@ +#!/bin/sh +query_kb_layout() { + CONTROLLER="$(qdbus 'org.fcitx.Fcitx5' '/controller' 'org.fcitx.Fcitx.Controller1.CurrentInputMethod')" + case $CONTROLLER in + "keyboard-us") echo "英数" ;; + "keyboard-us-intl") echo "英数(国際)" ;; + "mozc") echo "日本語" ;; + *) ;; + esac +} + +query_kb_layout + +dbus-monitor --address "$(fcitx5-remote -a)" "member='SetCurrentIM',destination='org.fcitx.Fcitx5'" |\ + grep --line-buffered 'SetCurrentIM' |\ + while read -r line ; do + query_kb_layout + done + diff --git a/home/dot_local/share/bin/executable_khal b/home/dot_local/share/bin/executable_khal new file mode 100644 index 0000000..71e5392 --- /dev/null +++ b/home/dot_local/share/bin/executable_khal @@ -0,0 +1,16 @@ +#!/bin/sh +CFG="$XDG_CONFIG_HOME/khal/config" +if [ "$CFG" -ot "$XDG_CONFIG_HOME/khal/config.sh" ] ; then + cat - "$XDG_CONFIG_HOME/khal/base" << "EOF" > "$CFG" +# THIS FILE IS AUTO-GENERATED, EDIT config_gen OR base INSTEAD!!! + +EOF + "$XDG_CONFIG_HOME/khal/config_gen" >> "$CFG" +fi + +# aliases +[ "$1" = "i" ] && { shift ; set -- interactive "$@" ; } +[ "$1" = "l" ] && { shift ; set -- list "$@" ; } + +exec /usr/bin/khal "$@" + diff --git a/home/dot_local/share/bin/executable_khard b/home/dot_local/share/bin/executable_khard new file mode 100644 index 0000000..cb02889 --- /dev/null +++ b/home/dot_local/share/bin/executable_khard @@ -0,0 +1,12 @@ +#!/bin/sh +CFG="$XDG_CONFIG_HOME/khard/khard.conf" +if [ "$CFG" -ot "$XDG_CONFIG_HOME/khard/config.sh" ] ; then + cat - "$XDG_CONFIG_HOME/khard/base" << "EOF" > "$CFG" +# THIS FILE IS AUTO-GENERATED, EDIT config_gen OR base INSTEAD!!! + +EOF + "$XDG_CONFIG_HOME/khard/config_gen" >> "$CFG" +fi + +exec /usr/bin/khard "$@" + diff --git a/home/dot_local/share/bin/executable_labels2lrc b/home/dot_local/share/bin/executable_labels2lrc new file mode 100644 index 0000000..c8abc1c --- /dev/null +++ b/home/dot_local/share/bin/executable_labels2lrc @@ -0,0 +1,30 @@ +#!/bin/python3 + +import re +import sys + +for line in sys.stdin: + line = line.rstrip("\n") + fields = line.split("\t") + + if len(fields) < 3: + continue + + time = fields[0] + + # Equivalent of: + # gensub(/([0-9]+)\.([0-9]{,2})([0-9]*)/, "\\1\\2.\\3", "g", time) + time = re.sub(r'(\d+)\.(\d{0,2})(\d*)', r'\1\2.\3', time) + + # AWK rounds by adding 0.5 then truncating. + time = int(float(time) + 0.5) + + millis = time % 100 + time //= 100 + + seconds = time % 60 + time //= 60 + + minutes = time % 100 + + print(f"[{minutes:02d}:{seconds:02d}.{millis:02d}]{fields[2]}") diff --git a/home/dot_local/share/bin/executable_latex-doc b/home/dot_local/share/bin/executable_latex-doc new file mode 100644 index 0000000..6d785f1 --- /dev/null +++ b/home/dot_local/share/bin/executable_latex-doc @@ -0,0 +1,4 @@ +#!/bin/sh +set -e +cd /usr/share/doc/texlive/latex +fork xdg-open "$(find . -name '*.pdf' | fzf)" diff --git a/home/dot_local/share/bin/executable_lf b/home/dot_local/share/bin/executable_lf new file mode 100644 index 0000000..430ae0b --- /dev/null +++ b/home/dot_local/share/bin/executable_lf @@ -0,0 +1,23 @@ +#!/bin/sh +lf=/usr/bin/lf + +UB_PID=0 +UB_SOCKET="" +UB_PID_FILE="$(mktemp)" + +cleanup() { + exec 3>&- + ueberzugpp cmd -s "$UB_SOCKET" -a exit +} + +# don't try to use ueberzug over ssh +[ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] && exec $lf "$@" + +ueberzugpp layer --silent --no-stdin --use-escape-codes --pid-file "$UB_PID_FILE" >/dev/null +UB_PID="$(cat "$UB_PID_FILE")" +rm -f "$UB_PID_FILE" +UB_SOCKET="/tmp/ueberzugpp-$UB_PID.socket" +export UB_PID UB_SOCKET +trap cleanup HUP INT QUIT TERM EXIT +$lf "$@" 3>&- + diff --git a/home/dot_local/share/bin/executable_lights b/home/dot_local/share/bin/executable_lights new file mode 100644 index 0000000..69ea06c --- /dev/null +++ b/home/dot_local/share/bin/executable_lights @@ -0,0 +1,5 @@ +#!/bin/sh +cmd="$1" +[ -z "$cmd" ] && cmd="toggle" +curl -X POST "$HASS_SERVER/api/webhook/$cmd" + diff --git a/home/dot_local/share/bin/executable_lock b/home/dot_local/share/bin/executable_lock new file mode 100644 index 0000000..988c0ec --- /dev/null +++ b/home/dot_local/share/bin/executable_lock @@ -0,0 +1,4 @@ +#!/bin/sh +xset s 15 15 +slock +xset s default diff --git a/home/dot_local/share/bin/executable_lorem b/home/dot_local/share/bin/executable_lorem new file mode 100644 index 0000000..5ef3171 --- /dev/null +++ b/home/dot_local/share/bin/executable_lorem @@ -0,0 +1,12 @@ +#!/bin/sh + +lorem_text="$(cat << EOF +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Gravida dictum fusce ut placerat orci nulla pellentesque. Laoreet id donec ultrices tincidunt arcu. Tortor aliquam nulla facilisi cras fermentum odio eu feugiat. A scelerisque purus semper eget duis at tellus. A iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Arcu bibendum at varius vel pharetra vel turpis nunc eget. Euismod in pellentesque massa placerat duis. Lorem ipsum dolor sit amet consectetur adipiscing elit. Ultrices in iaculis nunc sed augue lacus. Vestibulum mattis ullamcorper velit sed. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Elit pellentesque habitant morbi tristique senectus et. Ullamcorper sit amet risus nullam eget felis eget nunc lobortis. Vestibulum sed arcu non odio. Vestibulum sed arcu non odio euismod lacinia. Maecenas pharetra convallis posuere morbi leo urna molestie at. Sit amet consectetur adipiscing elit duis tristique sollicitudin. Curabitur gravida arcu ac tortor dignissim convallis aenean et. Nunc sed blandit libero volutpat sed cras ornare arcu. Eu nisl nunc mi ipsum faucibus vitae aliquet nec. Vehicula ipsum a arcu cursus. Arcu felis bibendum ut tristique et. Lobortis scelerisque fermentum dui faucibus in ornare. In arcu cursus euismod quis viverra nibh cras pulvinar. Integer malesuada nunc vel risus. Elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus. Viverra nam libero justo laoreet. Felis bibendum ut tristique et. Neque volutpat ac tincidunt vitae semper quis. Semper feugiat nibh sed pulvinar proin gravida hendrerit. Arcu bibendum at varius vel pharetra vel turpis. Tincidunt arcu non sodales neque. Id aliquet risus feugiat in ante metus. Eget magna fermentum iaculis eu non diam. Tempor id eu nisl nunc mi ipsum. Bibendum enim facilisis gravida neque convallis a cras semper. Parturient montes nascetur ridiculus mus. Tortor pretium viverra suspendisse potenti nullam ac. Mauris vitae ultricies leo integer malesuada nunc. Integer eget aliquet nibh praesent. Lorem ipsum dolor sit amet consectetur. Sit amet consectetur adipiscing elit pellentesque habitant. Habitant morbi tristique senectus et netus et malesuada. Cursus metus aliquam eleifend mi in nulla posuere sollicitudin. Tincidunt dui ut ornare lectus sit amet est. Elementum curabitur vitae nunc sed velit dignissim sodales. Senectus et netus et malesuada fames ac turpis egestas sed. Scelerisque viverra mauris in aliquam sem fringilla ut. Nunc eget lorem dolor sed viverra ipsum nunc aliquet. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Id neque aliquam vestibulum morbi blandit cursus. Enim tortor at auctor urna nunc id cursus metus. Dignissim convallis aenean et tortor at risus viverra. Et malesuada fames ac turpis egestas. Id cursus metus aliquam eleifend mi in nulla posuere. Egestas dui id ornare arcu odio. At elementum eu facilisis sed odio. Ultrices vitae auctor eu augue ut lectus arcu bibendum at. Amet volutpat consequat mauris nunc congue nisi vitae. Enim lobortis scelerisque fermentum dui faucibus in ornare quam. Libero id faucibus nisl tincidunt eget. Amet risus nullam eget felis eget. Ultricies mi eget mauris pharetra. Magnis dis parturient montes nascetur ridiculus mus mauris vitae. Lectus magna fringilla urna porttitor rhoncus dolor purus. Elementum eu facilisis sed odio morbi quis commodo odio. Tincidunt vitae semper quis lectus. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque eu. Pretium viverra suspendisse potenti nullam ac. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Tortor consequat id porta nibh venenatis. Elit at imperdiet dui accumsan sit amet nulla. Sem viverra aliquet eget sit. At in tellus integer feugiat scelerisque varius morbi enim. Dictum fusce ut placerat orci nulla pellentesque. Sed risus pretium quam vulputate dignissim. Tincidunt dui ut ornare lectus sit amet est placerat in. Urna nec tincidunt praesent semper feugiat. +EOF +)" + +if [ -z "$1" ]; then + echo "$lorem_text" +else + echo "$lorem_text" | cut -f1-$1 --delimiter=" " +fi diff --git a/home/dot_local/share/bin/executable_lrc2labels b/home/dot_local/share/bin/executable_lrc2labels new file mode 100644 index 0000000..a23b299 --- /dev/null +++ b/home/dot_local/share/bin/executable_lrc2labels @@ -0,0 +1,7 @@ +#!/bin/gawk -f +match($0, /^\[([0-9]{2}):([0-9]{2}\.[0-9]{2})\](.*)/, group) { + time = group[1] * 60 + group[2] + lyric = group[3] + + printf("%.2f\t%.2f\t%s\n", time, time, lyric) +} diff --git a/home/dot_local/share/bin/executable_mbsync b/home/dot_local/share/bin/executable_mbsync new file mode 100644 index 0000000..3f6aa09 --- /dev/null +++ b/home/dot_local/share/bin/executable_mbsync @@ -0,0 +1,2 @@ +#!/bin/sh +/usr/bin/mbsync --config "$XDG_CONFIG_HOME/mbsyncrc" "$@" diff --git a/home/dot_local/share/bin/executable_mk b/home/dot_local/share/bin/executable_mk new file mode 100644 index 0000000..051235a --- /dev/null +++ b/home/dot_local/share/bin/executable_mk @@ -0,0 +1,87 @@ +#!/bin/sh +progname="$(basename "$0")" +showmode() { + ! [ -n "$FROM_PROMPT" ] && return + ! [ -t 1 ] && return + + mode=" ($1)" + col=$(( $(tput cols) - $(echo "$mode" | wc -L) + 1 )) + printf '\e[1A\e['$col'G\e[1;30m%s\e[0m\n' "$mode" +} + +make_tags() { + build_dir="${1-build}" + + if [ -e "$build_dir/domains.yaml" ] ; then + yaml2json "$build_dir/domains.yaml" | jq --raw-output '. as $r | $r.flash_order[] as $n | $r.domains[] | select(.name == $n) | .build_dir' | while IFS= read -r build_dir; do + echo "Processing: $build_dir" + done + fi + +} + +mode_west() { + showmode 'west' + if [ -z "$*" ] ; then + set -- build + [ -e sysbuild ] || [ -e sysbuild.conf ] && set -- "$@" --sysbuild + fi + west "$@" + ec=$? + + mktags build & + + exit $ec +} +path="." +for x in $(seq 10) ; do + [ -e "$path/.west" ] && mode_west "$@" + [ "$path" -ef "$path/.." ] && break + path="$path/.." +done + +mode_cmake() { + showmode 'cmake' + builddir="build" + + [ "$*" = "clean" ] && exec rm -rf "$builddir" + + export CMAKE_GENERATOR="Ninja" + + # re-run configuration if fresh or CMakeLists was changed + if [ ! -e "$builddir/build.ninja" ] || + [ "CMakeLists.txt" -nt "$builddir/build.ninja" ] ; then + cmake --log-level WARNING -B "$builddir" || exit $? + fi + + # build + cmake --build "$builddir" -- "$@" + ec=$? + + # generate vim tags (continue after mk exits) + mktags "$builddir" & + + exit $ec +} +[ -e "CMakeLists.txt" ] && mode_cmake "$@" + +mode_make() { + showmode 'make' + exec make "$@" +} +[ -e "makefile" ] && mode_make "$@" +[ -e "Makefile" ] && mode_make "$@" + +mode_latexmk() { + showmode 'latexmk' + + [ "$*" = "clean" ] && exec latexmk -c + + exec latexmk "$@" +} +[ -e "latexmkrc" ] && mode_latexmk "$@" +[ -e ".latexmkrc" ] && mode_latexmk "$@" + +echo "$progname: unable to determine project build system!" >&2 +exit 1 + diff --git a/home/dot_local/share/bin/executable_mktags b/home/dot_local/share/bin/executable_mktags new file mode 100644 index 0000000..2daf25c --- /dev/null +++ b/home/dot_local/share/bin/executable_mktags @@ -0,0 +1,61 @@ +#!/bin/python3 + +from subprocess import run, DEVNULL +from pathlib import Path +from dataclasses import dataclass +from argparse import ArgumentParser + +@dataclass +class Options: + build_dir: Path + +def parse_arguments() -> Options: + parser = ArgumentParser(prog="mktags", description="generate vim tags file from build directory") + parser.add_argument("build_dir", type=Path, help="build directory", nargs='?', default=Path("build")) + + options = parser.parse_args() + return Options(**vars(options)) + +def index_files(build_dir: Path) -> list[Path]: + lines = [line for line in run(("ninja", "-C", str(build_dir), "-t", "deps"), text=True, capture_output=True).stdout.splitlines()] + lines = [line.lstrip() for line in lines if line.startswith(" ")] + return [Path(line) for line in lines] + +def get_sysbuild_files(domains_yml: Path) -> list[Path]: + if not domains_yml.exists(): + return [] + + from yaml import safe_load + yaml = safe_load(domains_yml.read_text()) + + build_dirs = [next(Path(domain['build_dir']) for domain in yaml['domains'] if domain['name'] == domain_name) for domain_name in yaml['flash_order']] + + files: set[Path] = set() + for dir in build_dirs: + files.update(get_files(dir)) + + return list(files) + +def get_files(build_dir: Path) -> list[Path]: + files = [] + + files += get_sysbuild_files(build_dir.joinpath("domains.yaml")) + files += index_files(build_dir) + + return files + +def gen_tags(files: list[Path]) -> str: + filelist = "\n".join(str(file) for file in files) + return run(("ctags", "-L", "-", "-f", "-"), text=True, input=filelist, capture_output=True).stdout + +if __name__ == "__main__": + options = parse_arguments() + + files = get_files(options.build_dir) + + files = list(set(files)) + + tags = gen_tags(files) + + options.build_dir.joinpath("tags").write_text(tags) + diff --git a/home/dot_local/share/bin/executable_mozc-config-filter b/home/dot_local/share/bin/executable_mozc-config-filter new file mode 100644 index 0000000..522275a --- /dev/null +++ b/home/dot_local/share/bin/executable_mozc-config-filter @@ -0,0 +1,6 @@ +#!/bin/sh +yay_dir="$(yay -Pg | jq --raw-output .buildDir)" +config_proto="$(mktemp)" +git --git-dir="$yay_dir/mozc-ut/mozc" show HEAD:src/protocol/config.proto > "$config_proto" +protoc --proto_path /tmp --decode=mozc.config.Config "$config_proto" < "$1" +rm -f "$config_proto" diff --git a/home/dot_local/share/bin/executable_nginx-dev b/home/dot_local/share/bin/executable_nginx-dev new file mode 100644 index 0000000..40e73ad --- /dev/null +++ b/home/dot_local/share/bin/executable_nginx-dev @@ -0,0 +1,86 @@ +#!/bin/sh +folder="$PWD" +port=8080 +try_files='/$uri /$uri.html /$uri/index.html =404' +access_log='/dev/stdout' +cache_control=' + proxy_store off; + proxy_cache off; + add_header Last-Modified $date_gmt; + add_header Cache-Control "private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + if_modified_since off; + expires off; + etag off; +' + +usage() { + cat << EOF +usage: $(basename "$0") [options] [folder] + +options: + -p PORT host server on port PORT (default $port) + -t STR set try_files pattern to STR (default '$try_files') + -C enable server cache (disabled by default) + -v verbose mode (prints config before starting server) + -q quiet mode (disable access_log) + -x automatically open a browser + -h show this help +EOF +exit $1 +} + +ARGC=0 +while getopts hvp:Ct:qx OPT; do + [ $OPTIND -gt $ARGC ] && ARGC=$OPTIND + case $OPT in + h) usage 0 ;; + p) port="$OPTARG" ;; + t) try_files="$OPTARG" ;; + v) print_config=1 ;; + C) cache_control='' ;; + q) access_log="/dev/null" ;; + x) open_browser=1 ;; + \?|*) usage 1 ;; + esac +done +shift $(( $OPTIND - 1 )) + +[ $# -ge 1 ] && folder="$(readlink -f "$1")" + +config="$(mktemp)" +pidfile="$(mktemp)" +cat << EOF > "$config" +worker_processes 1; +daemon off; +pid $pidfile; + +events { + worker_connections 1024; +} + +http { + types_hash_max_size 4096; + include /etc/nginx/mime.types; + default_type application/octet-stream; + + $cache_control + + access_log $access_log; + + server { + listen $port; + listen [::]:$port; + + root $folder; + + location / { + try_files $try_files; + } + } +} +EOF +[ $print_config ] && cat "$config" +[ $open_browser ] && (xdg-open "http://localhost:$port" 1> /dev/null 2> /dev/null &) +nginx -c "$config" +rm -f "$config" "$pidfile" + diff --git a/home/dot_local/share/bin/executable_open b/home/dot_local/share/bin/executable_open new file mode 100644 index 0000000..7856488 --- /dev/null +++ b/home/dot_local/share/bin/executable_open @@ -0,0 +1,12 @@ +#!/bin/sh +case "$(file --mime-type -Lb "$1")" in + text/*) + exec $EDITOR -- "$@" + ;; + *) + for file in "$@"; do + fork xdg-open "$file" + done + ;; +esac + diff --git a/home/dot_local/share/bin/executable_panic b/home/dot_local/share/bin/executable_panic new file mode 100644 index 0000000..7455786 --- /dev/null +++ b/home/dot_local/share/bin/executable_panic @@ -0,0 +1,36 @@ +#!/bin/sh +silent() { + "$@" 1>/dev/null 2> /dev/null & +} + +on() { + # clear desktop + silent i3-msg focus output primary + silent i3-msg workspace 'panic1' + silent i3-msg focus output right + silent i3-msg workspace 'panic2' + + # stop playing media (if any) + silent mpc pause + silent playerctl -a pause + + # mute mic/headphones + silent pactl set-sink-mute @DEFAULT_SINK@ true + silent pactl set-source-mute @DEFAULT_SOURCE@ true +} + +off() { + # unmute mic/headphones + silent pactl set-sink-mute @DEFAULT_SINK@ false + silent pactl set-source-mute @DEFAULT_SOURCE@ false +} + +panicfile="$XDG_CACHE_HOME/panic" +if [ -e "$panicfile" ] ; then + rm "$panicfile" + off +else + touch "$panicfile" + on +fi + diff --git a/home/dot_local/share/bin/executable_pause b/home/dot_local/share/bin/executable_pause new file mode 100644 index 0000000..8eedbfb --- /dev/null +++ b/home/dot_local/share/bin/executable_pause @@ -0,0 +1,10 @@ +#!/bin/sh +ec=0 +if [ $# -ge 1 ] ; then + "$@" + ec=$? +fi +printf "Press enter to exit..." +read +exit $ec + diff --git a/home/dot_local/share/bin/executable_pdfsize b/home/dot_local/share/bin/executable_pdfsize new file mode 100644 index 0000000..14f940d --- /dev/null +++ b/home/dot_local/share/bin/executable_pdfsize @@ -0,0 +1,2 @@ +#!/bin/sh +pdfinfo -box "$1" | awk '/^Page size:/ { print $3 * 2.54 / 72.0 * 10 "mm" " x " $5 * 2.54 / 72.0 * 10 "mm" }' diff --git a/home/dot_local/share/bin/executable_pew b/home/dot_local/share/bin/executable_pew new file mode 100644 index 0000000..70a9673 --- /dev/null +++ b/home/dot_local/share/bin/executable_pew @@ -0,0 +1,3 @@ +#!/bin/sh + +kill -9 $(xprop | grep "_NET_WM_PID(CARDINAL)" | cut -d' ' -f3) diff --git a/home/dot_local/share/bin/executable_podcast2m3u b/home/dot_local/share/bin/executable_podcast2m3u new file mode 100644 index 0000000..c3b692e --- /dev/null +++ b/home/dot_local/share/bin/executable_podcast2m3u @@ -0,0 +1,33 @@ +#!/bin/sh +URL="$1" +TAB="$(printf '\t')" +curl -sLo- "$URL" |\ +xmlstarlet select --template \ + --match '/rss/channel/item' \ + --value-of './itunes:duration' \ + --output "$TAB" \ + --value-of './title' \ + --output "$TAB" \ + --value-of './enclosure/@url' \ + --nl |\ +awk -F "$TAB" ' +BEGIN { + printf("#EXTM3U\n") +} +function time2secs(time) { + seconds = 0 + gsub(/,/, ".", time) + els = split(time, el, ":") + if (els == 0) return seconds; + seconds += el[els--] + if (els == 0) return seconds; + seconds += el[els--] * 60 + if (els == 0) return seconds; + seconds += el[els--] * 60 * 60 + return seconds; +} +{ + printf("#EXTINF:%s,%s\n%s\n", time2secs($1), $2, $3) +} +' + diff --git a/home/dot_local/share/bin/executable_preview b/home/dot_local/share/bin/executable_preview new file mode 100644 index 0000000..819938b --- /dev/null +++ b/home/dot_local/share/bin/executable_preview @@ -0,0 +1,75 @@ +#!/bin/sh +[ -n "$1" ] && FILE="$1" || { + echo "error: no input file" + exit 1 +} +[ -n "$2" ] && WIDTH="$(( "$2" - 1 ))" || WIDTH="$(tput cols)" +[ -n "$3" ] && HEIGHT="$3" || HEIGHT="$(tput lines)" +[ -n "$4" ] && POS_X="$4" || POS_X="0" +[ -n "$5" ] && POS_Y="$5" || POS_Y="0" + +MIMETYPE="$(file --mime-type -Lb "$FILE")" +EXT="${FILE#*.}" + +if [ "$MIMETYPE" = "text/plain" ] ; then + [ "$EXT" = "md" ] && MIMETYPE="text/markdown" + [ "$EXT" = "rst" ] && MIMETYPE="text/x-rst" +fi +[ "$MIMETYPE" = "application/javascript" ] && MIMETYPE="text/javascript" + +render_manpage() { + exec groff -T utf8 -m man -rcR=1 -rIN=0 -rLL="${WIDTH}n" << EOF +.nr an-suppress-header-and-footer 1 +.TH +$(cat | preconv) +EOF +} + +case "$MIMETYPE" in + image/*) + if [ -z "$UB_SOCKET" ] ; then + echo "ueberzug not available" + else + ueberzugpp cmd \ + --socket "$UB_SOCKET" \ + --action add \ + --identifier PREVIEW \ + --file "$FILE" \ + --max-width "$WIDTH" --max-height "$HEIGHT" \ + --xpos "$POS_X" --ypos "$POS_Y" + exit 1 # <- disable cache + fi + ;; + text/markdown) + pandoc --from=gfm --to=man "$FILE" | render_manpage + ;; + text/x-rst) + pandoc --from=rst --to=man "$FILE" | render_manpage + ;; + text/*) + bat \ + --terminal-width="$WIDTH" \ + --paging=never \ + --color=always \ + -- "$FILE" + ;; + application/x-tar|\ + application/x-bzip|\ + application/x-bzip2|\ + application/gzip|\ + application/zip|\ + application/x-7z-compressed|\ + application/vnd.rar) + bsdtar -tf "$FILE" + ;; + application/json) + jq --color-output . "$FILE" + ;; + *) + echo "$MIMETYPE" + file -b "$FILE" | fold --width="$WIDTH" --spaces + ;; +esac + +exit 0 + diff --git a/home/dot_local/share/bin/executable_prompt b/home/dot_local/share/bin/executable_prompt new file mode 100644 index 0000000..7dde932 --- /dev/null +++ b/home/dot_local/share/bin/executable_prompt @@ -0,0 +1,33 @@ +#!/bin/sh +fmt_esc() { + printf "%s$1%s" "$eo" "$ec" +} + +fmt_segment() { + content="$1" + [ -z "$content" ] && return + printf '%s%s%s -> %s' "$(fmt_esc '\e[90m')" "${content}" "$(fmt_esc '\e[30m')" "$(fmt_esc '\e[0m')" +} + +fmt_environment() { + content="$1" + [ -z "$content" ] && return + printf '%s(%s%s%s)%s ' "$(fmt_esc '\e[30;40m')" "$(fmt_esc '\e[97m')" "$content" "$(fmt_esc '\e[30;40m')" "$(fmt_esc '\e[0m')" +} + +[ -n "$1" ] && fmt_environment "$1" +fmt_environment "$VIRTUAL_ENV_PROMPT" + +# only display hostname in prompt if connected over SSH +[ -n "$SSH_CLIENT" ] && fmt_segment "$(hostname)" + +# current working directory +here="$PWD" +[ "$here" = "$HOME" ] && here="~" +fmt_segment "$(basename "$here")" + +# git status +git rev-parse --is-inside-work-tree 1> /dev/null 2> /dev/null && fmt_segment "git $(git rev-parse --abbrev-ref HEAD 2> /dev/null)" + +# exit happily +exit 0 diff --git a/home/dot_local/share/bin/executable_qrclip b/home/dot_local/share/bin/executable_qrclip new file mode 100644 index 0000000..41bdab7 --- /dev/null +++ b/home/dot_local/share/bin/executable_qrclip @@ -0,0 +1,2 @@ +#!/bin/sh +maim -usb 4 -c 0,0,0 | zbarimg --raw --quiet - diff --git a/home/dot_local/share/bin/executable_reload b/home/dot_local/share/bin/executable_reload new file mode 100644 index 0000000..4b87658 --- /dev/null +++ b/home/dot_local/share/bin/executable_reload @@ -0,0 +1,2 @@ +#!/bin/sh +i3-msg exit diff --git a/home/dot_local/share/bin/executable_rofi b/home/dot_local/share/bin/executable_rofi new file mode 100644 index 0000000..d573764 --- /dev/null +++ b/home/dot_local/share/bin/executable_rofi @@ -0,0 +1,4 @@ +#!/bin/sh +[ -e "$XDG_CONFIG_HOME/gtk-4.0/env" ] && . "$XDG_CONFIG_HOME/gtk-4.0/env" +. "$XDG_CACHE_HOME/mode/state/vars" +exec /bin/rofi -no-default-config "$@" diff --git a/home/dot_local/share/bin/executable_scene b/home/dot_local/share/bin/executable_scene new file mode 100644 index 0000000..c7faff6 --- /dev/null +++ b/home/dot_local/share/bin/executable_scene @@ -0,0 +1,56 @@ +#!/bin/sh +CACHE_FILE="$XDG_CACHE_HOME/hass-scenes" +TAB="$(printf '\t')" + +update_cache() { + rm -f "$CACHE_FILE" + curl -s -X GET \ + -H "Authorization: Bearer $HASS_TOKEN" \ + -H "Content-Type: application/json" \ + "$HASS_SERVER/api/states" |\ + jq --raw-output ' + .[] | + select(.entity_id | startswith("scene.")) | + "\(.attributes.friendly_name)\t\(.entity_id)" + ' > "$CACHE_FILE" +} + +# update cache if it does not exist +[ ! -e "$CACHE_FILE" ] && update_cache + +# update the cache if requested explicitly +[ "$1" = "--update" ] && { + update_cache + exit +} + +# update the cache if it is older than +MAX_CACHE_AGE=$(( 60 * 60 * 24 )) # one day +[ $(( $(date +%s) - $MAX_CACHE_AGE )) -gt $(date -r "$CACHE_FILE" +%s) ] && update_cache + +if [ $# -eq 0 ] ; then + # pick a scene using rofi in dmenu mode + scene="$(cat "$CACHE_FILE" |\ + rofi \ + -dmenu \ + -display-columns 1 \ + -display-column-separator "$TAB" |\ + cut -d"$TAB" -f2 |\ + jq --raw-input)" +else + # non interactive scene pick + scene="$(cat "$CACHE_FILE" |\ + grep -w "$*" | head -n1 |\ + cut -d"$TAB" -f2 |\ + jq --raw-input)" +fi + +# exit if no scene was selected / found +[ -z "$scene" ] && exit 0 + +jq -n --argjson scene "$scene" '{"entity_id": $scene}' |\ + curl -s -X POST -d @- \ + -H "Authorization: Bearer $HASS_TOKEN" \ + -H "Content-Type: application/json" \ + "$HASS_SERVER/api/services/scene/turn_on" > /dev/null + diff --git a/home/dot_local/share/bin/executable_screenrecord b/home/dot_local/share/bin/executable_screenrecord new file mode 100644 index 0000000..1045a6e --- /dev/null +++ b/home/dot_local/share/bin/executable_screenrecord @@ -0,0 +1,8 @@ +#!/bin/sh +exec giph "$@" \ + --framerate 60 \ + --select \ + --bordersize 4 \ + --color 255,255,255 \ + "$(date +'%Y-%m-%d_%H-%M-%S.mp4')" + diff --git a/home/dot_local/share/bin/executable_screenwatch b/home/dot_local/share/bin/executable_screenwatch new file mode 100644 index 0000000..d556fac --- /dev/null +++ b/home/dot_local/share/bin/executable_screenwatch @@ -0,0 +1,11 @@ +#!/bin/sh +# repeatedly open terminal at $dev, even when $dev temporarily dissapears +dev="$1" +while inotifywait -qq -e create --include "$dev" "$(dirname "$dev")"; do + sleep 0.1 # wait until device is initialized + screen "$@" + + # break out of loop if device still exists when screen exits (manual screen exit) + [ -e "$dev" ] && break +done + diff --git a/home/dot_local/share/bin/executable_sdk10_compiledb b/home/dot_local/share/bin/executable_sdk10_compiledb new file mode 100644 index 0000000..6e62d47 --- /dev/null +++ b/home/dot_local/share/bin/executable_sdk10_compiledb @@ -0,0 +1,38 @@ +#!/bin/python3 + +from shlex import split, join +from sys import argv +from os import getcwd +import subprocess + +process = subprocess.run(argv[1:], stdout=subprocess.PIPE, stderr=None, env={"LANG": "C"}) + +dir_stack = [getcwd()] +expanded_output = [] + +for line in process.stdout.decode('utf-8').split('\n'): + expanded_args = [] + args = split(line) + + if line.startswith('make: Entering directory'): + dir_stack.append(args[-1]) + expanded_output.append(line) + continue + if line.startswith('make: Leaving directory'): + dir_stack.pop() + expanded_output.append(line) + continue + + for arg in args: + if not arg.startswith('@'): + expanded_args.append(arg) + continue + with open(dir_stack[-1] + '/' + arg[1:], 'r') as file: + expanded_args += split(file.read()) + expanded_output.append(subprocess.list2cmdline(expanded_args)) + +process = subprocess.Popen(["compiledb"], stdin=subprocess.PIPE, stdout=None, stderr=None, text=True) +process.stdin.write("\n".join(expanded_output)) +process.stdin.close() +process.wait() + diff --git a/home/dot_local/share/bin/executable_set-default b/home/dot_local/share/bin/executable_set-default new file mode 100644 index 0000000..d93f65c --- /dev/null +++ b/home/dot_local/share/bin/executable_set-default @@ -0,0 +1,32 @@ +#!/bin/sh +SCRIPT_NAME="$(basename "$0")" + +usage() { + code=0 + if [ -z "$1" ] ; then + cat << EOF +Set desktop entry ENTRY as default application for opening files with the same +type as FILE + +EOF + else + echo "error: $1" >&2 + code=1 + fi + cat << EOF +usage: + $SCRIPT_NAME ENTRY FILE [FILE] +EOF + exit $code +} + +[ $# -eq 0 ] && usage +DESKTOP_ENTRY="$1"; shift +[ -z "$DESKTOP_ENTRY" ] && usage "no desktop entry" +[ $# -lt 1 ] && usage "no reference file(s)" + +for file in "$@" ; do + mimetype="$(xdg-mime query filetype "$file")" + xdg-mime default "$DESKTOP_ENTRY" "$mimetype" +done + diff --git a/home/dot_local/share/bin/executable_setwacom b/home/dot_local/share/bin/executable_setwacom new file mode 100644 index 0000000..d7427a6 --- /dev/null +++ b/home/dot_local/share/bin/executable_setwacom @@ -0,0 +1,2 @@ +#!/bin/sh +xsetwacom set "Wacom Intuos PT S 2 Pen stylus" $@ diff --git a/home/dot_local/share/bin/executable_single2folder b/home/dot_local/share/bin/executable_single2folder new file mode 100644 index 0000000..b3b2d30 --- /dev/null +++ b/home/dot_local/share/bin/executable_single2folder @@ -0,0 +1,16 @@ +#!/bin/sh +file=$1 +foldername=$(basename "$file" .flac) + +echo "mkdir \"$foldername\"" +mkdir "$foldername" + +echo "mv \"$file\" \"$foldername\"" +mv "$file" "$foldername" + +echo "extract folder.png" +metaflac --export-picture-to="${foldername}/folder.png" "${foldername}/${file}" + +echo "make sure folder.png is a png" +magick "${foldername}/folder.png" "${foldername}/folder.png" + diff --git a/home/dot_local/share/bin/executable_spec b/home/dot_local/share/bin/executable_spec new file mode 100644 index 0000000..7d500dc --- /dev/null +++ b/home/dot_local/share/bin/executable_spec @@ -0,0 +1,2 @@ +#!/bin/sh +sox "$1" -n spectrogram -o - | feh --class floating - diff --git a/home/dot_local/share/bin/executable_subrename b/home/dot_local/share/bin/executable_subrename new file mode 100644 index 0000000..16d913f --- /dev/null +++ b/home/dot_local/share/bin/executable_subrename @@ -0,0 +1,54 @@ +#!/bin/sh +file_extension=".srt" +season=1 +episode=1 + +PROGNAME="$(basename "$0")" +USAGE="$( cat << EOF +usage: $PROGNAME [-h] [-s season] [-e episode] [-x extension] file1 [file2 ...] + +rename files to s01e01.srt, s01e02.srt, etc. + +options: + -s set season number (default: $season) + -e set episode number of first file (default: $episode) + -x set file extension for output files (default: $file_extension) + -h show help + +example: + subrename -x .ja.srt *.srt +EOF +)" +usage() { + echo "$USAGE" + exit 0 +} +stupid() { + echo "use $PROGNAME -h for help" + exit 1 +} + +ARGC=0 +while getopts e:s:x:h OPT; do + [ $OPTIND -gt $ARGC ] && ARGC=$OPTIND + case "$OPT" in + e) episode="$OPTARG" ;; + h) usage ;; + s) season="$OPTARG" ;; + x) file_extension="$OPTARG" ;; + \?|*) stupid ;; + esac +done +shift "$(( $OPTIND - 1 ))" + +if [ $# -eq 0 ] ; then + echo "error: no files provided" + stupid +fi + +for file in "$@" ; do + new_filename="$(printf 's%02de%02d%s\n' "$season" "$episode" "$file_extension")" + mv --verbose "$file" "$new_filename" + episode=$(( $episode + 1 )) +done + diff --git a/home/dot_local/share/bin/executable_time2tsv b/home/dot_local/share/bin/executable_time2tsv new file mode 100644 index 0000000..4cc369d --- /dev/null +++ b/home/dot_local/share/bin/executable_time2tsv @@ -0,0 +1,107 @@ +#!/bin/awk -f + +# ignore empty or comment lines +/^\s*#/ { next } +/^\s*$/ { next } + +{ + owner = "" + date = "" + duration = 0 + description = "" +} + +function max(a, b) { + return a > b ? a : b +} + +function duration2time(duration) { + temp = 0 + num = 0 + multiplier = 60 + + split(duration, char, "") + for (i=1; i <= length(duration); i++) { + if (char[i] == "h") { + temp += num * 60 * 60 + multiplier = 60 + num = 0 + continue + } + if (char[i] == "m") { + temp += num * 60 + multiplier = 1 + num = 0 + continue + } + if (char[i] == "s") { + temp += num + multiplier = 0 + num = 0 + continue + } + + num *= 10 + num += char[i] + } + if (num > 0) { + temp += num * multiplier + } + + return temp +} + +function stripnotes(desc) { + out = "" + nestlevel = 0 + + split(desc, char, "") + for (i=1; i <= length(desc); i++) { + if (char[i] == "(") { + nestlevel += 1 + continue + } + + if (char[i] == ")") { + nestlevel = max(0, nestlevel - 1) + continue + } + + if (nestlevel > 0) continue + out = out char[i] + } + + return out +} + +# strip leading whitespace +/^\s+/ { gsub(/^\s+/, "", $0) } + +# match owner +match($0, /^[[:alpha:]]+/) { + owner = substr($0, RSTART, RLENGTH) + gsub(/^[[:alpha:]]+:?\s*/, "", $0) +} + +# match date +match($0, /^[0-9-]{10}/) { + date = substr($0, RSTART, RLENGTH) + gsub(/^[0-9-]{10}:?\s*/, "", $0) +} + +# match time +match($0, /^\<([0-9]+h)?([0-9]{1,2}m)?([0-9]{1,2}s)?\>/) { + duration = duration2time(substr($0, RSTART, RLENGTH)) + gsub(/^\<([0-9]+h)?([0-9]{1,2}m)?([0-9]{1,2}s)?\>:?\s*/, "", $0) +} + +# description +{ + description = stripnotes($0) +} + +# output +{ + printf("%s\t%s\t%s\t%s\n", owner, date, duration, description) +} + diff --git a/home/dot_local/share/bin/executable_timefmt b/home/dot_local/share/bin/executable_timefmt new file mode 100644 index 0000000..c78fb95 --- /dev/null +++ b/home/dot_local/share/bin/executable_timefmt @@ -0,0 +1,24 @@ +#!/bin/sh +[ $# -eq 0 ] && sum="$(cat)" || sum="$1" +sum="$(echo "$sum" | tr -dc '[:digit:]')" +if [ -z "$sum" ] ; then + echo "error: no input number" + exit 1 +fi + +fmt() { + # printf '%d:%02d:%02d\n' $@ | sed -e 's/^0\{2,\}//' + printf '%02dh%02dm%02ds\n' $@ | sed -e 's/00s$//' -e 's/^\(00.\)\+//' -e 's/^0\+//' +} + +fmt $(bc <<EOF +sum = $sum +seconds = sum % 60 +sum = (sum - seconds) / 60 +minutes = sum % 60 +sum = (sum - minutes) / 60 +hours = sum +print hours," ",minutes," ",seconds +EOF +) + diff --git a/home/dot_local/share/bin/executable_timerep b/home/dot_local/share/bin/executable_timerep new file mode 100644 index 0000000..e09d6c1 --- /dev/null +++ b/home/dot_local/share/bin/executable_timerep @@ -0,0 +1,82 @@ +#!/bin/sh +TAB="$(printf '\t')" +time2tsv "$@" | sort -t"$TAB" -k4 | awk -F"$TAB" ' +{ + gsub(/^\s+/, "", $4) + gsub(/\s+$/, "", $4) + desc = $4 + if (desc != last_desc && last_desc != "") { + printf("%s\t%d\n", last_desc, sum) + sum = 0 + } + sum += $3 + last_desc = desc +} +END { + printf("%s\t%d\n", last_desc, sum) +} +' | awk -F"$TAB" ' +BEGIN { + split("", last_path) # define empty array +} + +function strip(string) { + gsub(/^\s+/, "", string) + gsub(/\s+$/, "", string) + return string +} + +function repeat(str, count, i) { + out = "" + for (i = 0; i < count; i++) { + out = str out + } + return out +} +function indent(depth, i) { + return repeat(" ", depth) +} + +function printpath(new_path, new, i) { + new = 0 + for (i = 1; i <= length(new_path); i++) { + if (last_path[i] != new_path[i]) new = 1 + if (new == 0) continue + printf("%s%s\n", indent(i-1), new_path[i]) + last_path[i] = new_path[i] + } +} + +function timefmt(time, fmt) { + cmd = sprintf("timefmt %s", time) + cmd | getline fmt + close(cmd) + return fmt +} + +{ + len = split($1, path, "::") + for (i = 1; i <= len; i++) + path[i] = strip(path[i]) + + task = path[len] + delete path[len] + depth = len - 1 + sum += $2 + duration = timefmt($2) + + printpath(path) + printf("%-67s %10s\n", indent(depth) task, duration) +} + +BEGIN { + printf("\033[4m%-67s\033[0m \033[4m%10s\033[0m\n", "Description", "Total") +} + +END { + "timefmt "sum | getline duration + printf("%67s \033[4m%10s\033[0m\n", "", "") + printf("%67s %10s\n", "", duration) +} +' + diff --git a/home/dot_local/share/bin/executable_timesum b/home/dot_local/share/bin/executable_timesum new file mode 100644 index 0000000..6284ca4 --- /dev/null +++ b/home/dot_local/share/bin/executable_timesum @@ -0,0 +1,4 @@ +#!/bin/sh +TAB="$(printf '\t')" +time2tsv "$@" | cut -d"$TAB" -f3 | paste -sd+ - | bc | timefmt + diff --git a/home/dot_local/share/bin/executable_toetsrooster2ical b/home/dot_local/share/bin/executable_toetsrooster2ical new file mode 100644 index 0000000..5de58cb --- /dev/null +++ b/home/dot_local/share/bin/executable_toetsrooster2ical @@ -0,0 +1,38 @@ +#!/bin/python3 + +import sys +import xlrd +from datetime import datetime +import json +from icalendar import Calendar, Event +from uuid import uuid4 as uuid +import pytz + +workbook = xlrd.open_workbook(sys.argv[1]) +sheet = workbook.sheet_by_index(0) +cal = Calendar() + +cal.add('prodid', 'toetsrooster2ical') +cal.add('version', '2.0') + +def time_to_tuple(timestr): + return (int(timestr[0:2]), int(timestr[3:5])) + +for toets in range(8, sheet.nrows): + toetsdata = sheet.row_values(toets) + event = Event() + + date = xlrd.xldate_as_tuple(toetsdata[10], workbook.datemode) + times = toetsdata[11].split(" - ") + + event.add('summary', toetsdata[4]) + event.add('dtstart', datetime(*date[0:3], *time_to_tuple(times[0]))) + event.add('dtend', datetime(*date[0:3], *time_to_tuple(times[1]))) + event.add('location', toetsdata[14]) + + cal.add_component(event) + +f = open('out.ics', 'wb') +f.write(cal.to_ical()) +f.close() + diff --git a/home/dot_local/share/bin/executable_vdirsyncer b/home/dot_local/share/bin/executable_vdirsyncer new file mode 100644 index 0000000..7869f19 --- /dev/null +++ b/home/dot_local/share/bin/executable_vdirsyncer @@ -0,0 +1,6 @@ +#!/bin/sh +CFG_TMP="$XDG_CONFIG_HOME/vdirsyncer/config" +mkfifo --mode 700 "$CFG_TMP" +"$XDG_CONFIG_HOME/vdirsyncer/config_gen" > "$CFG_TMP" & +/usr/bin/vdirsyncer --config "$CFG_TMP" "$@" +rm -f "$CFG_TMP" diff --git a/home/dot_local/share/bin/executable_venvgen b/home/dot_local/share/bin/executable_venvgen new file mode 100644 index 0000000..25f2c78 --- /dev/null +++ b/home/dot_local/share/bin/executable_venvgen @@ -0,0 +1,47 @@ +#!/bin/sh + +# check if the input is valid +for arg in "$@" ; do + case "$arg" in + *=*) ;; + *) + echo "error: missing assignment operator in argument ($arg)" >&2 + exit 1 + ;; + esac +done + +# shebang +printf '#!/bin/sh\n' + +# save old variables +for arg in "$@" ; do + name="${arg%%=*}" + eval "hasval=\${$name+x}" + [ -n "$hasval" ] && printf '_%s="${%s}"\n' "$name" "$name" +done + +# set new variables +for arg in "$@" ; do + name="${arg%%=*}" + value="${arg#*=}" + printf 'export %s=%q\n' "$name" "$value" +done + +# deactivate function +printf 'deactivate() {\n' +for arg in "$@" ; do + name="${arg%%=*}" + eval "hasval=\${$name+x}" + if [ -n "$hasval" ] ; then + printf '\t%s="${_%s}"\n' "$name" "$name" + printf '\tunset -v _%s\n' "$name" + else + printf '\tunset -v %s\n' "$name" + fi +done +printf '\thash -r 2>/dev/null\n' +printf '\tunset -f deactivate\n' +printf '}\n' +printf 'hash -r 2>/dev/null\n' + diff --git a/home/dot_local/share/bin/executable_vodchat b/home/dot_local/share/bin/executable_vodchat new file mode 100644 index 0000000..f233348 --- /dev/null +++ b/home/dot_local/share/bin/executable_vodchat @@ -0,0 +1,3 @@ +#!/bin/sh +input_file="$1" +jq --raw-output '.replayChatItemAction.actions[].addChatItemAction.item.liveChatTextMessageRenderer | "[" + (.timestampUsec | tonumber / 1e6 | todateiso8601) + "] " + .authorName.simpleText + ": " + .message.runs[].text' "$input_file" 2>/dev/null diff --git a/home/dot_local/share/bin/executable_wacommode b/home/dot_local/share/bin/executable_wacommode new file mode 100644 index 0000000..2563895 --- /dev/null +++ b/home/dot_local/share/bin/executable_wacommode @@ -0,0 +1,58 @@ +#!/bin/sh + +defaults () { + # smoothing + setwacom Suppress 2 + setwacom RawSample 5 + + # full pen area + setwacom Area 0 0 15200 9500 + + setwacom Rotate none +} + +notify() { + notify-send \ + --replace-id=99999 \ + --icon=/dev/null \ + --expire-time=1000 \ + -- \ + 'ワコム' "$*" +} + +SCREEN_1_GEOMETRY="$(xrandr -q | awk '$2 == "connected" && $3 == "primary" { print $4 }')" +SCREEN_2_GEOMETRY="$(xrandr -q | awk '$2 == "connected" && $3 != "primary" { print $3 }')" +ALL_GEOMETRY="$(xrandr -q | awk '$1 == "Screen" { print ; exit }' | grep -o '\<current\>[^,]\+' | sed -e 's/^current//' -e 's/ //g' -e 's/$/+0+0/')" + +topleft() { + notify "画面1、横" + + setwacom MapToOutput "$SCREEN_1_GEOMETRY" +} + +bottomleft() { + notify "画面2、縦" + + setwacom Rotate ccw + setwacom MapToOutput "$SCREEN_2_GEOMETRY" +} + +topright() { + notify "画面1、横、低遅延" + + setwacom Suppress 0 + setwacom RawSample 1 + + setwacom Area 0 1623 7600 5898 + setwacom MapToOutput "$SCREEN_1_GEOMETRY" +} + +bottomright() { + notify "全ての画面、横" + + setwacom Area 0 0 11875 7600 + setwacom MapToOutput "$ALL_GEOMETRY" +} + +defaults +$1 diff --git a/home/dot_local/share/bin/executable_wacomshortcuts b/home/dot_local/share/bin/executable_wacomshortcuts new file mode 100644 index 0000000..911e7ff --- /dev/null +++ b/home/dot_local/share/bin/executable_wacomshortcuts @@ -0,0 +1,12 @@ +#!/bin/sh + +# tablet buttons +xsetwacom set "Wacom Intuos PT S 2 Pad pad" Button 3 "key +super +alt +ctrl 1 -super -alt -ctrl" +xsetwacom set "Wacom Intuos PT S 2 Pad pad" Button 1 "key +super +alt +ctrl 2 -super -alt -ctrl" +xsetwacom set "Wacom Intuos PT S 2 Pad pad" Button 9 "key +super +alt +ctrl 3 -super -alt -ctrl" +xsetwacom set "Wacom Intuos PT S 2 Pad pad" Button 8 "key +super +alt +ctrl 4 -super -alt -ctrl" + +# pen buttons +setwacom Button 2 pan +setwacom PanScrollThreshold 200 + diff --git a/home/dot_local/share/bin/executable_wacomtouch b/home/dot_local/share/bin/executable_wacomtouch new file mode 100644 index 0000000..6c1e51a --- /dev/null +++ b/home/dot_local/share/bin/executable_wacomtouch @@ -0,0 +1,14 @@ +#!/bin/sh +# print if wacom tablet has touch on or off +bye() { + echo $1 + exit +} + +[ ! -e /dev/input/by-id/usb-Wacom_Co._Ltd._Intuos_PTS-if01-event-mouse ] && bye + +if evtest --query /dev/input/by-id/usb-Wacom_Co._Ltd._Intuos_PTS-if01-event-mouse EV_SW SW_MUTE_DEVICE; then + bye "touch on" +else + bye "touch off" +fi diff --git a/home/dot_local/share/bin/executable_xbindkeys b/home/dot_local/share/bin/executable_xbindkeys new file mode 100644 index 0000000..03a2c37 --- /dev/null +++ b/home/dot_local/share/bin/executable_xbindkeys @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/xbindkeys --file "$XDG_CONFIG_HOME/xbindkeys/main" "$@" diff --git a/home/dot_local/share/bin/executable_yt-vod b/home/dot_local/share/bin/executable_yt-vod new file mode 100644 index 0000000..0eb424d --- /dev/null +++ b/home/dot_local/share/bin/executable_yt-vod @@ -0,0 +1,17 @@ +#!/bin/sh +vid="$1" +if [ -z "$vid" ] ; then + echo "usage: $0 <stream ID>" + exit 1 +fi + +url="https://youtube.com/watch?v=$vid" + +# download chat +screen -d -m -S "yt-$vid-chat" -- pause yt-dlp --live-from-start --write-sub --no-download "$url" + +# download stream +screen -d -m -S "yt-$vid-vod" -- pause yt-dlp --live-from-start -S ext "$url" + +echo "started recording! (use screen -r yt-$vid-<tab> to stop)" + diff --git a/home/dot_local/share/bin/symlink_mode b/home/dot_local/share/bin/symlink_mode new file mode 100644 index 0000000..da230d2 --- /dev/null +++ b/home/dot_local/share/bin/symlink_mode @@ -0,0 +1 @@ +../mode/mode diff --git a/home/dot_local/share/bin/symlink_sh b/home/dot_local/share/bin/symlink_sh new file mode 100644 index 0000000..ff99e34 --- /dev/null +++ b/home/dot_local/share/bin/symlink_sh @@ -0,0 +1 @@ +/usr/bin/dash |