diff options
Diffstat (limited to '.local/share')
52 files changed, 710 insertions, 120 deletions
diff --git a/.local/share/Anki2/gldriver6 b/.local/share/Anki2/gldriver6 new file mode 100644 index 0000000..865faf1 --- /dev/null +++ b/.local/share/Anki2/gldriver6 @@ -0,0 +1 @@ +auto diff --git a/.local/share/applications/discord.desktop b/.local/share/applications/discord.desktop index 676b330..403a457 100644 --- a/.local/share/applications/discord.desktop +++ b/.local/share/applications/discord.desktop @@ -7,3 +7,4 @@ Exec=discord Icon=discord Type=Application Categories=Network;InstantMessaging; +MimeType=x-scheme-handler/betterdiscord; diff --git a/.local/share/applications/mozc-dictionary.desktop b/.local/share/applications/mozc-dictionary.desktop new file mode 100644 index 0000000..c4f6193 --- /dev/null +++ b/.local/share/applications/mozc-dictionary.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Mozc dictionary tool +Name[ja]=Mozc 辞書ツール +Name[nl]=Mozc woordenboekhulpprogramma +GenericName[ja]=日本語入力の辞書ツール +GenericName[nl]=Hulpprogramma voor woordenboek van Japanse invoer +GenericName=Japanese input method dictionary tool +Exec=/usr/lib/mozc/mozc_tool --mode=dictionary_tool +Icon=mozc +Type=Application +Categories=Settings; diff --git a/.local/share/applications/mozc-settings.desktop b/.local/share/applications/mozc-settings.desktop new file mode 100644 index 0000000..bcfde2d --- /dev/null +++ b/.local/share/applications/mozc-settings.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Mozc settings +Name[ja]=Mozc プロパティ +Name[nl]=Mozc instellingen +GenericName[ja]=日本語入力の設定 +GenericName[nl]=Instellingen voor Japanse invoermethode +GenericName=Japanese IME configuration +Exec=/usr/lib/mozc/mozc_tool --mode=config_dialog +Icon=mozc +Type=Application +Categories=Settings; diff --git a/.local/share/bin/= b/.local/share/bin/= index 59b9b45..8f3345d 100755 --- a/.local/share/bin/= +++ b/.local/share/bin/= @@ -1,2 +1,42 @@ -#!/bin/sh -python3 -c "from math import *; deg = pi / 180; print($*)" +#!/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) + +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/.local/share/bin/brave b/.local/share/bin/brave index 1dea360..5089377 100755 --- a/.local/share/bin/brave +++ b/.local/share/bin/brave @@ -1,8 +1,7 @@ #!/bin/sh -# the remote debugging is so brave can be hooked into by -# ~/.local/share/mode/reload.d/brave. this is probaby bad for security if -# you're not the only user on the system -# --remote-debugging-port=9222 \ +# - make brave automatically load the `mode` theme +# - don't use kwallet (i don't save passwords in chrome anyways) /usr/bin/brave \ --load-extension="$XDG_CACHE_HOME/mode/chromium" \ + --password-store=basic \ "$@" diff --git a/.local/share/bin/brightness b/.local/share/bin/brightness new file mode 100755 index 0000000..c1c6139 --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/ccpreview b/.local/share/bin/ccpreview index a835ab4..9f13acc 100755 --- a/.local/share/bin/ccpreview +++ b/.local/share/bin/ccpreview @@ -24,33 +24,51 @@ 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" -# preview window -mpv \ - --msg-level=input=no --no-config --input-conf=/dev/null \ - --no-osc --no-input-default-bindings --pause=no --force-seekable=no \ - \ - --no-cache --untimed --no-correct-pts \ +_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 \ - --video-sync=audio \ --audio-buffer=0 \ - --vd-lavc-threads=1 \ --cache-pause=no \ --interpolation=no \ - --video-latency-hacks=yes \ --stream-buffer-size=4k \ - \ - --demuxer-lavf-o-add=fflags=+nobuffer \ - --demuxer-lavf-analyzeduration=0 \ + --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 \ - \ - "$VIDEO_URL" --audio-file="$AUDIO_URL" + --speed=1.05 \ + "$VIDEO_URL" + +sleep infinity +kill -9 -- $JOBS diff --git a/.local/share/bin/dbg b/.local/share/bin/dbg new file mode 100755 index 0000000..424110b --- /dev/null +++ b/.local/share/bin/dbg @@ -0,0 +1,40 @@ +#!/bin/sh +progname="$(basename "$(readlink -f "$0")")" +die() { + ec="$1" + shift + echo "$@" + exit "$ec" +} + +GDB="arm-none-eabi-gdb" + +[ $# -lt 1 ] && die 1 "usage: $progname DEVICE [gdb args...]" +DEVICE="$1" +shift + +if [ $# -eq 0 ] ; then + # automatically add --se flag if executable can be found + exec="$(find . -maxdepth 3 -name '*.elf' | head -n1)" + [ -n "$exec" ] && set -- --se="$exec" +fi + +[ -n "$(echo "$*" | grep -i zephyr)" ] && GDB="arm-zephyr-eabi-gdb" + +fork JLinkGDBServerCLExe \ + -device "$DEVICE" \ + -select USB \ + -endian little \ + -if SWD \ + -speed auto \ + -singlerun \ + -noir \ + -nologtofile \ + -silent + +# append startup attach command to args +set -- --eval-command="target extended-remote :2331" "$@" + +# launch gdb and forward any other args to it +exec "$GDB" "$@" + diff --git a/.local/share/bin/dox-open b/.local/share/bin/dox-open new file mode 100755 index 0000000..493c435 --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/editor b/.local/share/bin/editor new file mode 100755 index 0000000..d4bf664 --- /dev/null +++ b/.local/share/bin/editor @@ -0,0 +1,2 @@ +#!/bin/sh +exec nvim -p "$@" diff --git a/.local/share/bin/fontfix b/.local/share/bin/fontfix new file mode 100755 index 0000000..1c9beaf --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/hide b/.local/share/bin/hide new file mode 100755 index 0000000..cb49be0 --- /dev/null +++ b/.local/share/bin/hide @@ -0,0 +1,4 @@ +#!/bin/sh +for file in "$@" ; do + mv "$file" ".$file" +done diff --git a/.local/share/bin/labels2lrc b/.local/share/bin/labels2lrc index 1491dae..38630c1 100755 --- a/.local/share/bin/labels2lrc +++ b/.local/share/bin/labels2lrc @@ -1,13 +1,17 @@ -#!/bin/sh -cat "$@" |\ - awk ' +#!/bin/gawk -f BEGIN { FS = "\t" } { - seconds = $1 - minutes = int(seconds / 60) - seconds = seconds % 60 - millis = (seconds * 100) % 100 + time = $1 + time = gensub(/([0-9]+)\.([0-9]{,2})([0-9]*)/, "\\1\\2.\\3", "g", time) + time = int(time + 0.5) + + millis = time % 100 + time = int(time / 100) + + seconds = time % 60 + time = int(time / 60) + + minutes = time % 100 + printf("[%02d:%02d.%02d]%s\n", minutes, seconds, millis, $3) } -' - diff --git a/.local/share/bin/lrc2labels b/.local/share/bin/lrc2labels new file mode 100755 index 0000000..a23b299 --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/mk b/.local/share/bin/mk index ab0f586..54b6908 100755 --- a/.local/share/bin/mk +++ b/.local/share/bin/mk @@ -1,11 +1,21 @@ #!/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" } +mode_west() { + showmode 'west' + [ -z "$*" ] && set -- build + exec west "$@" +} +[ -e "west.yml" ] && mode_west "$@" + mode_cmake() { showmode 'cmake' builddir="build" @@ -16,11 +26,17 @@ mode_cmake() { # 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" + [ "CMakeLists.txt" -nt "$builddir/build.ninja" ] ; then + cmake --log-level WARNING -B "$builddir" fi - exec cmake --build "$builddir" -- "$@" + # build + cmake --build "$builddir" -- "$@" || exit $? + + # generate vim tags (continue after mk exits) + ninja -C "$builddir" -t deps | sed -n 's/^ \{4\}//p' | sort -u | ctags -L - -f "$builddir/tags" & + + exit 0 } [ -e "CMakeLists.txt" ] && mode_cmake "$@" diff --git a/.local/share/bin/nginx-dev b/.local/share/bin/nginx-dev new file mode 100755 index 0000000..40e73ad --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/now b/.local/share/bin/now deleted file mode 100755 index 8fca44f..0000000 --- a/.local/share/bin/now +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -printf '%s\n' "$(khal --color list now 1h --notstarted --day-format '' --format '({start-time}) {calendar-color}{title}{reset}')" diff --git a/.local/share/bin/preview b/.local/share/bin/preview index 0225848..141d03c 100755 --- a/.local/share/bin/preview +++ b/.local/share/bin/preview @@ -1,12 +1,26 @@ #!/bin/sh -[ $# -ne 5 ] && exit 1 -FILE="$1" -WIDTH="$2" -HEIGHT="$3" -POS_X="$4" -POS_Y="$5" +[ -n "$1" ] && FILE="$1" || { + echo "error: no input file" + exit 1 +} +[ -n "$2" ] && WIDTH="$(( "$2" - 3 ))" || 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#*.}" + +[ "$EXT" = "md" ] && [ "$MIMETYPE" = "text/plain" ] && MIMETYPE="application/markdown" +[ "$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/*) @@ -27,11 +41,18 @@ case "$MIMETYPE" in application/x-tar|\ application/x-bzip|\ application/x-bzip2|\ + application/gzip|\ application/zip|\ application/x-7z-compressed|\ application/vnd.rar) bsdtar -tf "$FILE" ;; + application/markdown) + pandoc --from=gfm --to=man "$FILE" | render_manpage + ;; + application/json) + jq --color-output . "$FILE" + ;; *) echo "$MIMETYPE" file -b "$FILE" | fold --width="$WIDTH" --spaces diff --git a/.local/share/bin/rofi b/.local/share/bin/rofi index 2b2d0b6..d573764 100755 --- a/.local/share/bin/rofi +++ b/.local/share/bin/rofi @@ -1,4 +1,4 @@ #!/bin/sh [ -e "$XDG_CONFIG_HOME/gtk-4.0/env" ] && . "$XDG_CONFIG_HOME/gtk-4.0/env" -. "$XDG_CONFIG_HOME/rofi/colors" +. "$XDG_CACHE_HOME/mode/state/vars" exec /bin/rofi -no-default-config "$@" diff --git a/.local/share/bin/screenrecord b/.local/share/bin/screenrecord index 52c6e5b..1045a6e 100755 --- a/.local/share/bin/screenrecord +++ b/.local/share/bin/screenrecord @@ -1,3 +1,8 @@ #!/bin/sh -giph -f 60 -s -b 4 -c 255,255,255 "$(date +'%Y-%m-%d_%H-%M-%S.mp4')" +exec giph "$@" \ + --framerate 60 \ + --select \ + --bordersize 4 \ + --color 255,255,255 \ + "$(date +'%Y-%m-%d_%H-%M-%S.mp4')" diff --git a/.local/share/bin/sdk10_compiledb b/.local/share/bin/sdk10_compiledb new file mode 100755 index 0000000..6e62d47 --- /dev/null +++ b/.local/share/bin/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/.local/share/bin/set-default b/.local/share/bin/set-default new file mode 100755 index 0000000..d93f65c --- /dev/null +++ b/.local/share/bin/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/.local/share/gnupg/gpg-agent.conf b/.local/share/gnupg/gpg-agent.conf index b747e5e..4e3bb5d 100644 --- a/.local/share/gnupg/gpg-agent.conf +++ b/.local/share/gnupg/gpg-agent.conf @@ -1,2 +1,3 @@ allow-preset-passphrase max-cache-ttl 604800 +pinentry-program /usr/bin/pinentry-gtk diff --git a/.local/share/mode/mode b/.local/share/mode/mode index 3969fa1..dc188e9 100755 --- a/.local/share/mode/mode +++ b/.local/share/mode/mode @@ -1,10 +1,11 @@ -#!/bin/sh +#!/usr/bin/env sh progname="$(basename "$0")" data="$(dirname "$(readlink -f "$0")")" export data # path to directory containing reload.d, switch.d, etc. -run_cfggen=1 +run_switch=1 run_reload=1 +no_cfg=0 theme="" # absolute path to theme # print error message and exit with error @@ -22,7 +23,8 @@ usage: $progname [-chr] action|theme options: - -c, --no-cfggen disable updating of configuration files + -s, --no-switch disable running switch.d hooks + -c, --no-cfggen disable generation of templated configuration files -h, --help display this help text -r, --no-reload disable reloading of applications after applying theme @@ -40,6 +42,24 @@ examples: EOF } +# run a module file +run_mod() { + mod_name="$1" + + # modules must be executable + ! [ -x "$mod_name" ] && return + + # parse interpreter from shebang + interpreter="$(basename "$(command -v $(head -n1 "$mod_name" | sed -n 's/^#!\(.*\)/\1/p'))")" + if [ "$interpreter" = "sh" ] ; then + # source module if interpreter is POSIX sh (makes plugin functions available) + ( . "$mod_name" ) + else + # else, just run them + "$mod_name" + fi +} + # generate config files from theme file using scripts in switch.d switch() { [ -z "$theme" ] && stupid "error: no theme selected" @@ -56,20 +76,12 @@ switch() { # load theme colors + aux variables . "$theme" - # load plugins (available to switch.d scripts only) + # load plugins (TODO: plugins aren't loaded when only reloading) for plugin in "$data"/plug.d/* ; do . "$plugin" ; done # generate new config files / snippets (in parallel) for switch_function in "$data"/switch.d/* ; do - ! [ -x "$switch_function" ] && continue - interpreter="$(basename "$(command -v $(head -n1 "$switch_function" | sed -n 's/^#!\(.*\)/\1/p'))")" - if [ "$interpreter" = "sh" ] ; then - # source scripts if they are POSIX sh (makes plugin functions available) - ( . "$switch_function" ) & - else - # else, just run them - "$switch_function" & - fi + run_mod "$switch_function" & done # join all processes started above @@ -81,8 +93,7 @@ reload() { echo "reloading programs..." for reload_function in "$data"/reload.d/* ; do - ! [ -x "$reload_function" ] && continue - "$reload_function" & + run_mod "$reload_function" & done wait $(jobs -p) @@ -96,11 +107,13 @@ for arg in "$@" ; do # help -h|--help|help) usage && exit 0 ;; # only run reload scripts - reload) run_reload=1 run_cfggen=0 ;; + reload) run_reload=1 run_switch=0 ;; # prevent reload.d scripts from running -r|--no-reload) run_reload=0 ;; # prevent switch.d scripts from running - -c|--no-cfggen) run_cfggen=0 ;; + -s|--no-switch) run_switch=0 ;; + # prevent switch.d scripts from running + -c|--no-cfggen) no_cfg=1 ;; # restore previous theme stored as symlink (see switch.d/mode) restore) theme="$(readlink -f "$XDG_CACHE_HOME/mode/state/theme")" @@ -127,6 +140,9 @@ for arg in "$@" ; do esac done -[ $run_cfggen -eq 1 ] && switch +export no_cfg + +# main +[ $run_switch -eq 1 ] && switch [ $run_reload -eq 1 ] && reload diff --git a/.local/share/mode/plug.d/10_lib b/.local/share/mode/plug.d/10_lib index 61817bc..b3a0276 100644 --- a/.local/share/mode/plug.d/10_lib +++ b/.local/share/mode/plug.d/10_lib @@ -1,5 +1,46 @@ #!/bin/sh # utility library functions hex_to_rgb_array() { pastel format rgb "$1" | cut -c4- | tr '()' '[]' ; } + mix_rgb() { pastel mix --colorspace=RGB --fraction="$3" "$1" "$2" | pastel format hex ; } +getvar() { + key="$1" + eval "printf '%s' \"\$$key\"" +} + +setvar() { + key="$1" + value="$2" + eval "$key='$(printf '%s' "$value")'" +} + +themevar() { + key="$1" + if [ $# -eq 1 ] ; then + value="$(getvar "$key")" + else + value="$2" + setvar "$key" "$value" + fi + + vars="$vars +$(printf "export %s='%s'" "$key" "$value")" + eval "export $key" +} + +mkcd() { + mkdir -p "$1" + cd "$1" +} + +respawn_daemon() { + killall -q "$1" && fork "$@" +} + +silent_fail_if_no_commmand() { + for name in "$@" ; do + [ -z "$(command -v "$name")" ] && exit + done +} + diff --git a/.local/share/mode/plug.d/20_export_colors b/.local/share/mode/plug.d/20_export_colors index 017446d..0f53d1f 100644 --- a/.local/share/mode/plug.d/20_export_colors +++ b/.local/share/mode/plug.d/20_export_colors @@ -9,7 +9,7 @@ check_color() { echo "error: color $1 is not properly formatted (#RRGGBB)" stupid && exit 1 fi - eval "export $1" + themevar "$1" } for color in $(seq 0 15 | sed 's/^/color/') bg fg ; do check_color $color diff --git a/.local/share/mode/plug.d/20_export_mode b/.local/share/mode/plug.d/20_export_mode index 78432b6..c82c4e1 100644 --- a/.local/share/mode/plug.d/20_export_mode +++ b/.local/share/mode/plug.d/20_export_mode @@ -5,5 +5,5 @@ if [ "$mode" != 'dark' ] && [ "$mode" != 'light' ] ; then [ $? -eq 0 ] && mode=dark || mode=light echo "warn: theme $theme did not define \$mode as \"light\" or \"dark\", guessed $mode" >&2 fi -export mode +themevar mode diff --git a/.local/share/mode/plug.d/20_export_vim_theme b/.local/share/mode/plug.d/20_export_vim_theme index be76b8b..12304f3 100644 --- a/.local/share/mode/plug.d/20_export_vim_theme +++ b/.local/share/mode/plug.d/20_export_vim_theme @@ -3,4 +3,4 @@ if [ "$(find "$XDG_CONFIG_HOME/nvim" -name "$vim_theme_name.vim" | wc -l)" -eq 0 ] ; then echo "warn: vim theme $vim_theme_name does not appear to be installed" >&2 fi -export vim_theme_name +themevar vim_theme_name diff --git a/.local/share/mode/plug.d/50_accent b/.local/share/mode/plug.d/50_accent index 2a8a113..ceb3209 100644 --- a/.local/share/mode/plug.d/50_accent +++ b/.local/share/mode/plug.d/50_accent @@ -4,13 +4,12 @@ # do not generate accent color if already explicitly defined by theme [ -n "$accent" ] && return -[ "$mode" = "light" ] && { - accent="$color15" - accent_text="$color0" -} -[ "$mode" = "dark" ] && { - accent="$(mix_rgb $bg $color0 0.5)" - accent_text="$fg" -} +if [ "$mode" = "light" ] ; then + themevar accent "$color15" + themevar accent_text "$color0" +fi +if [ "$mode" = "dark" ] ; then + themevar accent "$(mix_rgb $bg $color0 0.5)" + themevar accent_text "$fg" +fi -export accent accent_text diff --git a/.local/share/mode/reload.d/dunst b/.local/share/mode/reload.d/dunst index 3c09a31..430320c 100755 --- a/.local/share/mode/reload.d/dunst +++ b/.local/share/mode/reload.d/dunst @@ -1,4 +1,3 @@ #!/bin/sh -killall dunst -fork dunst +respawn_daemon dunst diff --git a/.local/share/mode/reload.d/gtk b/.local/share/mode/reload.d/gtk index a6dbb34..767969d 100644 --- a/.local/share/mode/reload.d/gtk +++ b/.local/share/mode/reload.d/gtk @@ -2,9 +2,7 @@ # this is max jank but xfsettingsd does other things besides live gtk theme # reloading, and i don't like having it running constantly because it fucks # up fcitx5 and xbindkeys -( - fork xfsettingsd --replace - sleep 1 - killall xfsettingsd -) +fork xfsettingsd --replace +sleep 1 +killall -q xfsettingsd diff --git a/.local/share/mode/reload.d/i3 b/.local/share/mode/reload.d/i3 new file mode 100755 index 0000000..96212cf --- /dev/null +++ b/.local/share/mode/reload.d/i3 @@ -0,0 +1,2 @@ +#!/bin/sh +fork i3-msg reload diff --git a/.local/share/mode/reload.d/nvim b/.local/share/mode/reload.d/nvim index 84ae847..cfabcc7 100755 --- a/.local/share/mode/reload.d/nvim +++ b/.local/share/mode/reload.d/nvim @@ -1,4 +1,5 @@ #!/bin/sh +silent_fail_if_no_commmand nvr nvr --serverlist | while read -r nvim_socket ; do fork nvr --nostart --servername "$nvim_socket" -c 'source $XDG_CONFIG_HOME/nvim/mode.vim' done diff --git a/.local/share/mode/reload.d/polybar b/.local/share/mode/reload.d/polybar index af39394..1976811 100755 --- a/.local/share/mode/reload.d/polybar +++ b/.local/share/mode/reload.d/polybar @@ -1,3 +1,3 @@ #!/bin/sh -polybar-msg cmd restart > /dev/null +fork polybar-msg cmd restart diff --git a/.local/share/mode/reload.d/term b/.local/share/mode/reload.d/term index 5f02463..b711d56 100755 --- a/.local/share/mode/reload.d/term +++ b/.local/share/mode/reload.d/term @@ -26,5 +26,5 @@ escape_msgs="$(cat << EOF | tr -d '\n' EOF )" -find /dev/pts -exec sh -c "printf \"$escape_msgs\" > {}" \; 2> /dev/null +find /dev/pts -exec sh -c "printf '$escape_msgs' > {}" \; 2> /dev/null diff --git a/.local/share/mode/switch.d/anki b/.local/share/mode/switch.d/anki index c9caf5d..7572b00 100755 --- a/.local/share/mode/switch.d/anki +++ b/.local/share/mode/switch.d/anki @@ -1,4 +1,5 @@ #!/bin/sh +[ $no_cfg -eq 1 ] && return # this generates theme files compatible with Anki-redesign: # <https://ankiweb.net/shared/info/308574457> diff --git a/.local/share/mode/switch.d/chromium b/.local/share/mode/switch.d/chromium index 9048b80..5ed07fc 100755 --- a/.local/share/mode/switch.d/chromium +++ b/.local/share/mode/switch.d/chromium @@ -1,17 +1,18 @@ #!/bin/sh -PREFIX="$XDG_CACHE_HOME/mode/chromium" +[ $no_cfg -eq 1 ] && return -mkdir -p "$PREFIX" -rm -f "$PREFIX/Cached Theme.pak" +mkcd "$XDG_CACHE_HOME/mode/chromium" -magick -size 100x100 "xc:$bg" "$PREFIX/bg.png" -bg_alt=$(mix_rgb $color7 $bg 0.20) -fg_alt=$(mix_rgb $color15 $fg 0.60) +rm -f 'Cached Theme.pak' + +magick -size 100x100 "xc:$bg" 'bg.png' +bg_alt=$(mix_rgb $bg $color0 0.65) +fg_alt=$(mix_rgb $fg $color15 0.35) bg="$(hex_to_rgb_array "$bg")" fg="$(hex_to_rgb_array "$fg")" bg_alt="$(hex_to_rgb_array "$bg_alt")" fg_alt="$(hex_to_rgb_array "$fg_alt")" -cat << EOF > "$PREFIX/manifest.json" +cat << EOF > 'manifest.json' { "description": "colorscheme generated by mode", "manifest_version": 2, diff --git a/.local/share/mode/switch.d/discord b/.local/share/mode/switch.d/discord index f656783..dd7e5e3 100755 --- a/.local/share/mode/switch.d/discord +++ b/.local/share/mode/switch.d/discord @@ -1,5 +1,8 @@ #!/bin/sh -cat << EOF > "$XDG_CONFIG_HOME/BetterDiscord/themes/mode.theme.css" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/BetterDiscord/themes" +cat << EOF > 'mode.theme.css' /** * @name mode * @author mode diff --git a/.local/share/mode/switch.d/dunst b/.local/share/mode/switch.d/dunst index d4fd8dc..d7d9a2b 100755 --- a/.local/share/mode/switch.d/dunst +++ b/.local/share/mode/switch.d/dunst @@ -1,5 +1,8 @@ #!/bin/sh -cat "$XDG_CONFIG_HOME/dunst/base" - << EOF > "$XDG_CONFIG_HOME/dunst/dunstrc" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/dunst" +cat 'base' - << EOF > 'dunstrc' frame_color = "$accent" [urgency_low] diff --git a/.local/share/mode/switch.d/fcitx5 b/.local/share/mode/switch.d/fcitx5 index 4b35478..d9d0032 100755 --- a/.local/share/mode/switch.d/fcitx5 +++ b/.local/share/mode/switch.d/fcitx5 @@ -1,5 +1,7 @@ #!/bin/sh -cd "$XDG_DATA_HOME/fcitx5/themes/default" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_DATA_HOME/fcitx5/themes/default" rounding=6 size=$(( 2 * $rounding + 4 )) margin_h=6 diff --git a/.local/share/mode/switch.d/i3 b/.local/share/mode/switch.d/i3 new file mode 100755 index 0000000..713869e --- /dev/null +++ b/.local/share/mode/switch.d/i3 @@ -0,0 +1,14 @@ +#!/bin/sh +[ $no_cfg -eq 1 ] && return + +indicator="$color0" +mkcd "$XDG_CONFIG_HOME/i3" +cat << EOF > 'color.conf' +client.focused $fg $bg $fg $indicator $bg +client.focused_inactive $bg $bg $fg $indicator $bg +client.unfocused $bg $bg $fg $indicator $bg +client.urgent $bg $bg $fg $indicator $bg +client.placeholder $bg $bg $fg $indicator $bg +client.background $bg +EOF + diff --git a/.local/share/mode/switch.d/kitty b/.local/share/mode/switch.d/kitty new file mode 100755 index 0000000..eeb81d0 --- /dev/null +++ b/.local/share/mode/switch.d/kitty @@ -0,0 +1,27 @@ +#!/bin/sh +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/kitty" + +cat << EOF > 'color.conf' +background $bg +foreground $fg + +color0 $color0 +color1 $color1 +color2 $color2 +color3 $color3 +color4 $color4 +color5 $color5 +color6 $color6 +color7 $color7 +color8 $color8 +color9 $color9 +color10 $color10 +color11 $color11 +color12 $color12 +color13 $color13 +color14 $color14 +color15 $color15 +EOF + diff --git a/.local/share/mode/switch.d/mode b/.local/share/mode/switch.d/mode index 3b58fa6..8866486 100755 --- a/.local/share/mode/switch.d/mode +++ b/.local/share/mode/switch.d/mode @@ -1,8 +1,10 @@ #!/bin/sh -PREFIX="$XDG_CACHE_HOME/mode/state" -rm -rf "$PREFIX"/* -mkdir -p "$PREFIX" +[ $no_cfg -eq 1 ] && return -echo "$mode" > "$PREFIX/mode" -ln -sf "$theme" "$PREFIX/theme" +mkcd "$XDG_CACHE_HOME/mode/state" + +echo "$mode" > mode +rm theme +ln -sf "$theme" theme +echo "#!/bin/sh$vars" > vars diff --git a/.local/share/mode/switch.d/polybar b/.local/share/mode/switch.d/polybar index b7e752a..7087735 100755 --- a/.local/share/mode/switch.d/polybar +++ b/.local/share/mode/switch.d/polybar @@ -1,5 +1,8 @@ #!/bin/sh -cat << EOF > "$XDG_CONFIG_HOME/polybar/colors.ini" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/polybar" +cat << EOF > 'colors.ini' [color] bg = \${xrdb:background:$bg} fg = \${xrdb:foreground:$fg} diff --git a/.local/share/mode/switch.d/rofi b/.local/share/mode/switch.d/rofi deleted file mode 100755 index 19b9008..0000000 --- a/.local/share/mode/switch.d/rofi +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cat << EOF > "$XDG_CONFIG_HOME/rofi/colors" -export background="$bg" -export foreground="$fg" -export accent="$accent" -export accent_text="$accent_text" -EOF - diff --git a/.local/share/mode/switch.d/vim b/.local/share/mode/switch.d/vim index 6c83f9f..2220b1a 100755 --- a/.local/share/mode/switch.d/vim +++ b/.local/share/mode/switch.d/vim @@ -1,9 +1,10 @@ #!/bin/sh -PREFIX="$XDG_CONFIG_HOME/nvim/mode" -mkdir -p "$PREFIX" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/nvim/mode" # lightline -cat << EOF > "$PREFIX/lightline.vim" +cat << EOF > 'lightline.vim' let s:bg = [ '$bg', 'NONE' ] let s:fg = [ '$fg', 'NONE' ] let s:mode = [ '$color0', 'NONE' ] @@ -14,7 +15,7 @@ let s:test = [ '#ff00ff', 'NONE' ] let s:p = {'normal': {}, 'inactive': {}, 'insert': {}, 'replace': {}, 'visual': {}, 'tabline': {}} let s:p.normal.left = [ [ s:fg, s:mode ], [ s:faint, s:bg ] ] let s:p.normal.right = [ [ s:faint, s:bg ] ] -let s:p.normal.middle = [ [ s:none, s:none ] ] +let s:p.normal.middle = [ [ s:bg, s:bg ] ] let s:p.normal.error = [ [ s:test, s:test ] ] let s:p.normal.warning = [ [ s:test, s:test ] ] let s:p.inactive.left = copy(s:p.normal.left) @@ -32,7 +33,7 @@ let g:lightline#colorscheme#auto#palette = lightline#colorscheme#flatten(s:p) EOF # terminal colors -cat << EOF > "$PREFIX/termcolors.vim" +cat << EOF > 'termcolors.vim' let g:terminal_color_0 = '$color0' let g:terminal_color_1 = '$color1' let g:terminal_color_2 = '$color2' @@ -52,7 +53,7 @@ let g:terminal_color_15 = '$color15' EOF # color scheme -cat << EOF > "$PREFIX/colorscheme.vim" +cat << EOF > 'colorscheme.vim' colorscheme $vim_theme_name EOF diff --git a/.local/share/mode/switch.d/zathura b/.local/share/mode/switch.d/zathura index c0687df..42d6d90 100755 --- a/.local/share/mode/switch.d/zathura +++ b/.local/share/mode/switch.d/zathura @@ -1,5 +1,8 @@ #!/bin/sh -cat << EOF > "$XDG_CONFIG_HOME/zathura/colors" +[ $no_cfg -eq 1 ] && return + +mkcd "$XDG_CONFIG_HOME/zathura" +cat << EOF > 'colors' set completion-bg "$bg" set completion-fg "$fg" set completion-highlight-bg "$accent" diff --git a/.local/share/mode/themes/github-black b/.local/share/mode/themes/github-black new file mode 100644 index 0000000..34b507c --- /dev/null +++ b/.local/share/mode/themes/github-black @@ -0,0 +1,25 @@ +#!/bin/sh +mode=dark + +color0='#484f58' +color1='#ffa198' +color2='#56d364' +color3='#e3b341' +color4='#79c0ff' +color5='#d2a8ff' +color6='#56d4dd' +color7='#b1bac4' +color8='#6e7681' +color9='#ff7b72' +color10='#3fb950' +color11='#d29922' +color12='#58a6ff' +color13='#bc8cff' +color14='#39c5cf' +color15='#ffffff' + +bg='#000000' +fg='#e6edf3' + +vim_theme_name='ghdark' + diff --git a/.local/share/mode/themes/xcode-dark b/.local/share/mode/themes/xcode-dark new file mode 100644 index 0000000..eb75b80 --- /dev/null +++ b/.local/share/mode/themes/xcode-dark @@ -0,0 +1,24 @@ +#!/bin/sh +mode=dark + +color0='#43454b' +color1='#ff8a7a' +color2='#83c9bc' +color3='#d9c668' +color4='#4ec4e6' +color5='#ff85b8' +color6='#cda1ff' +color7='#ffffff' +color8='#838991' +color9='#ff8a7a' +color10='#b1faeb' +color11='#ffa14f' +color12='#6bdfff' +color13='#ff85b8' +color14='#e5cfff' +color15='#ffffff' + +bg='#1f1f24' +fg='#e6edf3' + +vim_theme_name='xcodedarkhc' diff --git a/.local/share/pass-extensions/duplicates.bash b/.local/share/pass-extensions/duplicates.bash index cb1cbbc..3ba47aa 100755 --- a/.local/share/pass-extensions/duplicates.bash +++ b/.local/share/pass-extensions/duplicates.bash @@ -5,21 +5,18 @@ pass_names="$(pass names -l)" [ $? -ne 0 ] && exit 1 pass_count="$(echo "$pass_names" | wc -l)" -if [ "$pass_count" -gt 10 ] ; then - cat << EOF >&2 -pass-duplicates needs to decrypt all your passwords one-by-one to cross-match -them. This is all done in-memory, and nothing is saved to disk. You appear to -have $pass_count passwords, so this may take some time... - -EOF -fi +pass_index=1 while read pass_name ; do hash="$(pass show "$pass_name" | head -n1 | sha1sum | cut -c1-40)" dupe_map["$pass_name"]="$hash" dupe_tally["$hash"]=$(( ${dupe_tally["$hash"]} + 1 )) + + printf '\rhashing... (%d/%d)' "$pass_index" "$pass_count" >&2 + pass_index=$(( $pass_index + 1 )) done < <(echo "$pass_names") +printf '\r\e[2K' >&2 unique_duplicates=0 total_shared=0 diff --git a/.local/share/pass-extensions/g.bash b/.local/share/pass-extensions/g.bash new file mode 100755 index 0000000..4ab3ace --- /dev/null +++ b/.local/share/pass-extensions/g.bash @@ -0,0 +1,2 @@ +#!/bin/bash +exec pass git "$@" |