From 838c330359ce58680c9d960f74f0cb39f4c1ebbb Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Tue, 5 Sep 2023 13:52:52 -0500 Subject: [PATCH] Pull in scripts --- bin/? | 8 +++ bin/N | 2 + bin/archive | 5 ++ bin/archupdate | 6 ++ bin/at | 21 ++++++ bin/bp | 5 ++ bin/check-domain-availability | 90 ++++++++++++++++++++++++ bin/check-port | 17 +++++ bin/clip | 15 ++++ bin/clipshot | 29 ++++++++ bin/copy-git-forge-url | 21 ++++++ bin/countdown | 15 ++++ bin/dns | 3 + bin/dns-cleaner | 0 bin/dns-deleter | 22 ++++++ bin/dns-deleter-matching | 11 +++ bin/dotfiles-clone-and-setup | 8 +++ bin/dotfiles-init | 56 +++++++++++++++ bin/dotfiles-link-environments | 39 ++++++++++ bin/dotfiles-make-env | 30 ++++++++ bin/dotfiles-setup | 78 ++++++++++++++++++++ bin/dotfiles-setup-for-root | 31 ++++++++ bin/editscrot | 3 + bin/email-via-mailgun-smtp | 72 +++++++++++++++++++ bin/emoji | 5 ++ bin/ezln | 6 ++ bin/field | 6 ++ bin/getip | 4 ++ bin/git-authors | 8 +++ bin/gitforge-url.ts | 73 +++++++++++++++++++ bin/glancepath | 11 +++ bin/good-morning | 21 ++++++ bin/has_command | 4 ++ bin/install-firefox-user-chrome-css.fish | 21 ++++++ bin/is_wayland | 4 ++ bin/k8s-yaml-diff | 8 +++ bin/k8s-yaml-sort | 17 +++++ bin/keyrepeat | 3 + bin/kubeline | 9 +++ bin/kubfc | 9 +++ bin/kubfn | 12 ++++ bin/launch | 19 +++++ bin/linewise | 10 +++ bin/maybe_source_env_file | 5 ++ bin/nd | 3 + bin/nf | 7 ++ bin/note | 2 + bin/nsync | 8 +++ bin/nvimdiff | 2 + bin/open-in-git-forge | 21 ++++++ bin/optimize-photo-for-web | 18 +++++ bin/pass-migrate-to-pass-otp | 6 ++ bin/pipeline | 41 +++++++++++ bin/poll | 12 ++++ bin/pr-for-commit | 10 +++ bin/readme.md | 4 ++ bin/remote | 11 +++ bin/resource-usage | 23 ++++++ bin/restartbar | 3 + bin/s | 3 + bin/scn | 3 + bin/screenshot | 6 ++ bin/script-opts | 3 + bin/scrup | 19 +++++ bin/scwd | 4 ++ bin/setbg | 8 +++ bin/simple-otp | 8 +++ bin/source_if_exists | 7 ++ bin/startbar | 3 + bin/stopbar | 8 +++ bin/sw | 17 +++++ bin/tdf | 2 + bin/tenv | 3 + bin/terminal-rendering-test | 25 +++++++ bin/termrec | 3 + bin/tls | 2 + bin/tmux-edit-buffer | 4 ++ bin/tmux-lyte-session | 11 +++ bin/tmux-save-buffer | 9 +++ bin/tmux-session-dir | 9 +++ bin/tmux-session-preview | 13 ++++ bin/tmuxswitcher | 22 ++++++ bin/unarchive | 9 +++ bin/unbackupify | 56 +++++++++++++++ bin/weather | 3 + bin/work-journal-entry | 4 ++ bin/yamldiff | 8 +++ daniel.nix | 6 +- flake.lock | 37 ++++++++++ flake.nix | 6 ++ machines/thinker.nix | 1 + 91 files changed, 1332 insertions(+), 3 deletions(-) create mode 100755 bin/? create mode 100755 bin/N create mode 100755 bin/archive create mode 100755 bin/archupdate create mode 100755 bin/at create mode 100755 bin/bp create mode 100755 bin/check-domain-availability create mode 100755 bin/check-port create mode 100755 bin/clip create mode 100755 bin/clipshot create mode 100755 bin/copy-git-forge-url create mode 100755 bin/countdown create mode 100755 bin/dns create mode 100755 bin/dns-cleaner create mode 100755 bin/dns-deleter create mode 100755 bin/dns-deleter-matching create mode 100644 bin/dotfiles-clone-and-setup create mode 100755 bin/dotfiles-init create mode 100755 bin/dotfiles-link-environments create mode 100755 bin/dotfiles-make-env create mode 100755 bin/dotfiles-setup create mode 100755 bin/dotfiles-setup-for-root create mode 100755 bin/editscrot create mode 100755 bin/email-via-mailgun-smtp create mode 100755 bin/emoji create mode 100755 bin/ezln create mode 100755 bin/field create mode 100755 bin/getip create mode 100755 bin/git-authors create mode 100755 bin/gitforge-url.ts create mode 100755 bin/glancepath create mode 100755 bin/good-morning create mode 100755 bin/has_command create mode 100755 bin/install-firefox-user-chrome-css.fish create mode 100755 bin/is_wayland create mode 100755 bin/k8s-yaml-diff create mode 100755 bin/k8s-yaml-sort create mode 100755 bin/keyrepeat create mode 100755 bin/kubeline create mode 100755 bin/kubfc create mode 100755 bin/kubfn create mode 100755 bin/launch create mode 100755 bin/linewise create mode 100755 bin/maybe_source_env_file create mode 100755 bin/nd create mode 100755 bin/nf create mode 100755 bin/note create mode 100755 bin/nsync create mode 100755 bin/nvimdiff create mode 100755 bin/open-in-git-forge create mode 100755 bin/optimize-photo-for-web create mode 100755 bin/pass-migrate-to-pass-otp create mode 100755 bin/pipeline create mode 100755 bin/poll create mode 100755 bin/pr-for-commit create mode 100644 bin/readme.md create mode 100755 bin/remote create mode 100755 bin/resource-usage create mode 100755 bin/restartbar create mode 100755 bin/s create mode 100755 bin/scn create mode 100755 bin/screenshot create mode 100755 bin/script-opts create mode 100755 bin/scrup create mode 100755 bin/scwd create mode 100755 bin/setbg create mode 100755 bin/simple-otp create mode 100755 bin/source_if_exists create mode 100755 bin/startbar create mode 100755 bin/stopbar create mode 100755 bin/sw create mode 100755 bin/tdf create mode 100755 bin/tenv create mode 100755 bin/terminal-rendering-test create mode 100755 bin/termrec create mode 100755 bin/tls create mode 100755 bin/tmux-edit-buffer create mode 100755 bin/tmux-lyte-session create mode 100755 bin/tmux-save-buffer create mode 100755 bin/tmux-session-dir create mode 100755 bin/tmux-session-preview create mode 100755 bin/tmuxswitcher create mode 100755 bin/unarchive create mode 100755 bin/unbackupify create mode 100755 bin/weather create mode 100755 bin/work-journal-entry create mode 100755 bin/yamldiff diff --git a/bin/? b/bin/? new file mode 100755 index 0000000..bbf6d34 --- /dev/null +++ b/bin/? @@ -0,0 +1,8 @@ +#!/usr/bin/env fish + +echo "Keys you never remember:" +echo +echo "C-t fuzzy find a file or directory to insert into your command" +echo "C-g fuzzy find a directory to cd to" + +# https://github.com/lotabout/skim/blob/master/shell/key-bindings.fish diff --git a/bin/N b/bin/N new file mode 100755 index 0000000..5ec9178 --- /dev/null +++ b/bin/N @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +fn="${1}"; shift; nf "${fn}.md" "$@" \ No newline at end of file diff --git a/bin/archive b/bin/archive new file mode 100755 index 0000000..0b478e6 --- /dev/null +++ b/bin/archive @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +archive_name="$(basename "${1}").tar.zstd" +tar --zstd -cvf "${archive_name}" "${@}" +echo "Archive created at: ${archive_name} " diff --git a/bin/archupdate b/bin/archupdate new file mode 100755 index 0000000..ec3c4b5 --- /dev/null +++ b/bin/archupdate @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +yay -Syu --nodiffmenu --nocleanmenu --noeditmenu + +# TODO: update kernel with a flag? +# yes | pacman -Syu && kexec -l --initrd=/boot/initramfs-linux.img /boot/vmlinuz-linux && kexec -e diff --git a/bin/at b/bin/at new file mode 100755 index 0000000..1c8a1f3 --- /dev/null +++ b/bin/at @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +usage() { + echo "at - waits until after the specified datetime" + echo "Usage:" + echo " at && command..." + echo + echo "Examples:" + echo " at 15:00:00 && echo \"it is 3 o'clock\"" +} + +[[ -z "$1" ]] && { echo "Error: No DATE argument provided." >&2; usage; exit 1; } + +d="$(date -d "${@}" +%s)" +while [[ "$d" -ge "$(date +%s)" ]]; do + _dt=$((d - $(date +%s))) + days=$((_dt / 86400)) + echo -ne "\rTime Remaining: ${days}d $(date -u --date @$((_dt)) +%H:%M:%S) "; + sleep 0.1 +done +exit 0 \ No newline at end of file diff --git a/bin/bp b/bin/bp new file mode 100755 index 0000000..d3c155e --- /dev/null +++ b/bin/bp @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +printf '\e[?2004h' +printf '\e[?2004l' +echo bp off + diff --git a/bin/check-domain-availability b/bin/check-domain-availability new file mode 100755 index 0000000..5afce64 --- /dev/null +++ b/bin/check-domain-availability @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# TODO: +# + trap exit signals to cleanup all temp files and cancel all jobs +# + run in batches to prevent spawning way too many processes +# + detect when piping into another application and suppress colors? +# + temp file control (or none for no disk space)? +# + command line options or env vars? +# + --tlds "com,net,org" +# + --max-concurrent-whois-jobs +# + --avail-regex and --timeout-regex + +# suggested usage: ./check_domain | tee /tmp/chkdmn && sort /tmp/chkdmn + +# constants +AVAIL_REGEX='^No match|^NOT FOUND|^Not fo|AVAILABLE|^No Data Fou|has not been regi|No entri' +TIMEOUT_REGEX='^Timeout' + +COLOR_RESET="\x1b[0m" COLOR_GREEN="\x1b[32m" +COLOR_YELLOW="\x1b[33m" +COLOR_RED="\x1b[31m" + +TLDS=( \ + '.com' '.net' '.org' '.eu' '.in' '.it' '.sk' '.ac' '.ae' '.af' '.ag' '.al' \ + '.am' '.as' '.at' '.ax' '.be' '.bi' '.bo' '.by' '.bz' '.cc' '.cd' '.cf' '.cg' \ + '.ch' '.ci' '.cl' '.cm' '.cn' '.co' '.cr' '.cx' '.cz' '.dk' '.dm' '.do' '.ec' \ + '.ee' '.es' '.fi' '.fm' '.fo' '.ga' '.gd' '.gf' '.gg' '.gl' '.gp' '.gq' '.gr' \ + '.gs' '.gt' '.gy' '.hk' '.hm' '.hn' '.ht' '.id' '.im' '.in' '.io' '.ir' '.is' \ + '.je' '.ke' '.kg' '.kz' '.la' '.lc' '.li' '.lt' '.lu' '.lv' '.ly' '.me' '.mg' \ + '.mk' '.ml' '.mn' '.mq' '.ms' '.mu' '.mw' '.mx' '.na' '.ne' '.ng' '.nl' '.nu' \ + '.nz' '.pe' '.ph' '.pk' '.pl' '.pr' '.pt' '.pw' '.qa' '.ro' '.rs' '.ru' '.rw' \ + '.sb' '.sc' '.sd' '.se' '.sh' '.si' '.sl' '.sr' '.st' '.su' '.sx' '.sg' '.tk' \ + '.tl' '.to' '.tv' '.tw' '.ug' '.vc' '.ve' '.vg' '.vn' '.vu' '.ws' \ + ) + +# check dependencies +if command -v whois >/dev/null 2>&1; then + : +else + echo "You need to install whois before proceeding!" + exit 2 +fi + +# check arguments +if [ "$#" == "0" ]; then + echo "You need to supply at least one argument!" + exit 1 +fi + +# main function +check_domain() { + local tmp + local domain + + if [ "$#" == "0" ]; then + echo "No domain specified." + return + fi + + domain="$1" + + # create a unique temporary file + tmp=$(mktemp "${domain}_XXX") + + # dump whois output into temp file + whois "$domain" > "$tmp" 2>&1 + + # check contents and output appropriately + if grep -E -q "$AVAIL_REGEX" "$tmp" > /dev/null 2>&1; then + echo -e "$COLOR_GREEN$domain / probably available$COLOR_RESET" + elif grep -E -q "$TIMEOUT_REGEX" "$tmp" > /dev/null 2>&1; then + echo -e "$COLOR_YELLOW$domain / timed out$COLOR_RESET" + else + echo -e "$COLOR_RED$domain / unavailable$COLOR_RESET" + fi + + # cleanup + rm "$tmp" +} + +# iterate all provided domain names combined with all TLDs and check them +# concurrently +elements=${#TLDS[@]} +while (( "$#" )); do + for (( i=0;i&2 + exit 1 +fi + +if [[ $1 = u ]] || [[ $1 = udp ]] || \ + [[ $1 = U ]] || [[ $1 = UDP ]]; then + shift + set -x + sudo nmap -sU "$1" -p "$2" +else + set -x + nmap "$1" -p "$2" +fi diff --git a/bin/clip b/bin/clip new file mode 100755 index 0000000..0eab0ac --- /dev/null +++ b/bin/clip @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# TODO: detect MIME type? +# TODO: figure out how/why these programs "wait" -- can a `clip-once` script exist building on this? + # wl-copy `-o`, xclip `-l 1`? + +if [ "$(uname)" == "Linux" ]; then + if is_wayland; then + wl-copy -n "$@" + else + xclip -i -sel c "$@" + fi +elif [ "$(uname)" == "Darwin" ]; then + pbcopy "$@" +fi diff --git a/bin/clipshot b/bin/clipshot new file mode 100755 index 0000000..62f4ba7 --- /dev/null +++ b/bin/clipshot @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -x + +umask 077 +d="$(date +"%Y-%m-%d_%H-%M-%S")" +fn="$SCROTS_PATH/clipshot_$d.png" +mkdir -p "$SCROTS_PATH" + +dim="$(slurp -d -b \#00000066 -c \#ffffffff)" +if [ "$?" -eq 0 ]; then + grim -g "$dim" - | wl-copy -t image/png + wl-paste -n > "$fn" + echo "$fn" +else + exit 1 +fi + +# TODO: implement for X and other OSs? + +# pkill unclutter +# sleep 0.1 +# import "$fn" +# < "$fn" xclip -t image/png -i -selection clipboard +# < "$fn" xclip -t image/png -i -selection primary +# < "$fn" xclip -t image/png -i -selection secondary +# < "$fn" xclip -t image/png -i -selection buffer-cut +# unclutter & +# echo "$fn" diff --git a/bin/copy-git-forge-url b/bin/copy-git-forge-url new file mode 100755 index 0000000..287a94f --- /dev/null +++ b/bin/copy-git-forge-url @@ -0,0 +1,21 @@ +#!/usr/bin/env sh + +usage() { + echo "copy-git-forge-url <$FILE>[#L$LINE_NUMBERS]" + echo " Copies a link to the git forge's web interface for the current branch to the clipboard" + echo + echo " Examples:" + echo " \$ copy-git-forge-url readme.md#L12" +} + +if [ "$#" -lt 1 ]; then + usage + exit 1 +fi + +url="$(gitforge-url.ts "$1")" +case "$(uname)" in + Linux*) echo "$url" | clip;; + Darwin*) echo "$url" | clip;; + *) echo "OS not supported"; exit 1; +esac \ No newline at end of file diff --git a/bin/countdown b/bin/countdown new file mode 100755 index 0000000..d6f00da --- /dev/null +++ b/bin/countdown @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +[[ $# -lt 1 ]] && { echo "No argument provided." >&2 ; exit 1; } + +d=$(($(date +%s) + $1)); +echo "Countdown started at $(date)" + +while [[ "$d" -ge "$(date +%s)" ]]; do + _dt=$((d - $(date +%s))) + days=$((_dt / 86400)) + echo -ne "\r${days}d $(date -u --date @$((_dt)) +%H:%M:%S) "; + sleep 0.1 +done + +echo -ne "\rCountdown finished $(date)\n" diff --git a/bin/dns b/bin/dns new file mode 100755 index 0000000..0a1c7f1 --- /dev/null +++ b/bin/dns @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +getent hosts "$@" diff --git a/bin/dns-cleaner b/bin/dns-cleaner new file mode 100755 index 0000000..e69de29 diff --git a/bin/dns-deleter b/bin/dns-deleter new file mode 100755 index 0000000..3df9dd8 --- /dev/null +++ b/bin/dns-deleter @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +hostname="${1}"; shift || { + echo "No hostname arg to delete provided." + exit 1 +} +API="https://api.netlify.com/api/v1" +TOKEN="$(pass netlify | grep -i token | tr -d ' ' | cut -d ':' -f 2)" +counter=0 +curl -sL "$API/dns_zones/lyte_dev/dns_records?access_token=$TOKEN" | \ + jq -r '.[] | select(.hostname=="'"$hostname"'") | .hostname+": "+.id' | \ + while read -r l; do + counter=$((counter+1)) + ID="$(echo $l | awk '{print $2}')" + URL="$API/dns_zones/lyte_dev/dns_records/$ID?access_token=$TOKEN" + curl -vvv -X DELETE -sL "$URL" 2>&1 | grep 'ratelimit-remaining' & + echo "counter: $counter" + jq 'del(.[] | select(.id == "'$ID'"))' /tmp/zone.json > /tmp/zone2.json + mv /tmp/zone2.json /tmp/zone.json + [ $counter -gt 450 ] && break + done +wait diff --git a/bin/dns-deleter-matching b/bin/dns-deleter-matching new file mode 100755 index 0000000..cf6c334 --- /dev/null +++ b/bin/dns-deleter-matching @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +API="https://api.netlify.com/api/v1" +TOKEN="$(pass netlify | grep -i token | tr -d ' ' | cut -d ':' -f 2)" +while read -r l; do + set -x -e + ID="$(echo $l | awk '{print $2}')" + URL="$API/dns_zones/lyte_dev/dns_records/$ID?access_token=$TOKEN" + curl -X DELETE -sL "$URL" +done +wait diff --git a/bin/dotfiles-clone-and-setup b/bin/dotfiles-clone-and-setup new file mode 100644 index 0000000..5d90580 --- /dev/null +++ b/bin/dotfiles-clone-and-setup @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +command -v git >/dev/null 2>&1 || { echo "git not installed"; exit 1; } +command -v fish >/dev/null 2>&1 || { echo "fish not installed"; exit 2; } + +mkdir -p "$HOME/.config" +git clone https://git.lyte.dev/lytedev/dotfiles.git "$HOME/.config/lytedev-dotfiles" +exec "$HOME/.config/lytedev-dotfiles/common/bin/dotfiles-setup" diff --git a/bin/dotfiles-init b/bin/dotfiles-init new file mode 100755 index 0000000..3fe9240 --- /dev/null +++ b/bin/dotfiles-init @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +export dfp +export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +export ENV_PATH="$XDG_CONFIG_HOME/lytedev-env" +export CURDIR + +mkdir -p "$ENV_PATH" +mkdir -p "$XDG_CONFIG_HOME" +dfp="$(realpath "$(dirname "$0")"/../..)" + +# may not be running from inside the dotfiles repo, may have been curl'd down solo, so we need to check +if [[ ! -d "$dfp/.git" ]]; then + echo "Not running from inside the dotfiles git repo, so we need to download it first!" + # each os needs instructions to install git, then we can clone the repo and proceed + if ! command -v git; then + if head /etc/os-release --lines 1 | grep 'Arch Linux' > /dev/null 2>&1; then + if [[ "$EUID" -ne 0 ]]; then + if ! command -v sudo; then + echo "Error: No sudo command available to try and install 'git'" + exit 1 + else + sudo pacman -Sy --needed git + fi + else + pacman -Sy --needed git + fi + fi + fi + dfp="$XDG_CONFIG_HOME/lytedev-dotfiles" + git clone https://git.lyte.dev/lytedev/dotfiles.git "$dfp" +fi + +# auto-link any OS-specific environments +if head /etc/os-release --lines 1 | grep 'NixOS$' > /dev/null 2>&1; then + ln -s "$dfp/os/linux/nix" "$ENV_PATH/os-linux-nix" > /dev/null 2>&1 +elif head /etc/os-release --lines 1 | grep 'Arch Linux' > /dev/null 2>&1; then + ln -s "$dfp/os/linux/arch" "$ENV_PATH/os-linux-arch" > /dev/null 2>&1 +fi + +# perform any pre-requisite setup (includes OS-specific setup scripts since we +# just included those) +for s in "$ENV_PATH"/*; do + f="$s/dotfiles-init.d.sh" + if [ -f "$f" ]; then + echo "dotfiles-init: Running $f..." + CURDIR="$s" "$f" + fi +done + +# perform final dotfiles setup +echo "dotfiles-init: Running setup..." +"$dfp/common/bin/dotfiles-setup" + +# TODO: setup personal files? (ssh keys, gpg keys, password stores, notes) +# these are probably best handled in a dotfiles-init.d.sh script in a particular layer diff --git a/bin/dotfiles-link-environments b/bin/dotfiles-link-environments new file mode 100755 index 0000000..3fe54d9 --- /dev/null +++ b/bin/dotfiles-link-environments @@ -0,0 +1,39 @@ +#!/usr/bin/env fish + +has_command sk || begin + echo "sk not installed (skim fuzzy finder)" + exit 1 +end + +mkdir -p $ENV_PATH + +function filter_existing_directory + while read -l line + test -d $DOTFILES_PATH/$line && echo $line + end +end + +function reject_empty_lines + while read -l line + test $line = "" || echo $line + end +end + +function link + while read -l line + set safe_fn (string replace -a / - $line) + echo "Linking $ENV_PATH/$safe_fn to $DOTFILES_PATH/$line" + rm -f $ENV_PATH/$safe_fn + ln -s $DOTFILES_PATH/$line $ENV_PATH/$safe_fn + end +end + +cat $DOTFILES_PATH/common/envs | + filter_existing_directory | + sk --multi \ + --prompt "Select applicable environments (multi-select w/ TAB): " \ + --preview-window="up:50%:noborder" \ + --preview="ls -la --color=always $DOTFILES_PATH/{}" | + string trim | + reject_empty_lines | + link diff --git a/bin/dotfiles-make-env b/bin/dotfiles-make-env new file mode 100755 index 0000000..ca07e0a --- /dev/null +++ b/bin/dotfiles-make-env @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +echo "Not implemented yet!"; exit 1 + +edfp="$ENV_PATH/$1" +mkdir -p "$edfp/" +mkdir -p "$edfp/.hidden/bash.d/" +mkdir -p "$edfp/bin/" +mkdir -p "$edfp/x/" +mkdir -p "$edfp/sway/waybar" +mkdir -p "$edfp/sway/config.d" +mkdir -p "$HOME/.bin/" + +touches=( + "$edfp/bash" + "$edfp/x/init" + "$edfp/x/profile" + "$edfp/x/resources" + "$edfp/vim" + "$edfp/bspwm" + "$edfp/polybar" + "$edfp/app-launcher" + "$edfp/workdock" +) + +for t in "${touches[@]}"; do + touch "$t" +done + +chmod 700 -R "$edfp" diff --git a/bin/dotfiles-setup b/bin/dotfiles-setup new file mode 100755 index 0000000..5accd42 --- /dev/null +++ b/bin/dotfiles-setup @@ -0,0 +1,78 @@ +#!/usr/bin/env fish + +# This script's purpose is to setup the dotfiles configuration for an existing +# and provisioned machine. For provisioning, see `./dotfiles-init`. + +set dfp (realpath (dirname (status -f))/../..) +set lock_file $HOME/.using-lytedev-dotfiles.lock + +if not test -f $lock_file + echo "This will delete existing files. Make sure you know what you're doing." + echo 'Are you sure you want to continue? [y/N]' + read response + set response (string lower $response) + if string match $response y + echo "agreed" > "$lock_file" + else + exit 1 + end +end + +set -q XDG_CONFIG_HOME || set XDG_CONFIG_HOME $HOME/.config +set h $HOME; set c $XDG_CONFIG_HOME +if test -d $c/lytedev-env + echo "Warning: no environment-specific configuration detected!" +end + +function l -a dot -a target -d "Symlink a dotfile configuration file or directory" + if test -L $target || test -f $target || test -d $target + command rm -rf "$target" + end + # check if the directory that will contain the link exists + set -l d (dirname $target) + test -d $d || mkdir -p $d + ln -s (pwd)/$dot $target + echo Linked $dot to $target +end + +pushd $dfp +test -d ~/.tmux/pluginx/tpm || \ + git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm +l common/zellij $c/zellij +l common/tmux/conf $h/.tmux.conf +l common/bat $c/bat +l common/bash/rc $h/.bashrc +l common/wezterm $c/wezterm +l common/kitty $c/kitty +l common/weechat $h/.weechat +l common/scim/rc $h/.scimrc +l common/scim/lua $h/.scim/lua +l common/nnn $c/nnn +l common/kak $c/kak +l common/helix $c/helix +l common/gitui $c/gitui +l common/gpg/agent.conf $h/.gnupg/gpg-agent.conf +chmod og-rwx ~/.gnupg +l common/htop/rc $c/htop/htoprc +l common/kitty $c/kitty +l common/alacritty $c/alacritty +l common/pgcli $c/pgcli +l common/mutt/rc $h/.muttrc +l common/git/config $h/.gitconfig +l common/elixir/iex.exs $h/.iex.exs +l common/blender/userpref.blend $c/blender/2.93/config/userpref.blend +l common/lemonade/config.toml $c/lemonade.toml +l common/tig/rc $h/.tigrc +popd + +for s in $c/lytedev-env/*/dotfiles-setup.d.fish + source $s $dfp $h $c +end + +set -q ENV_PATH || set ENV_PATH $XDG_CONFIG_HOME/lytedev-env +set -q DOTFILES_PATH || set DOTFILES_PATH $XDG_CONFIG_HOME/lytedev-dotfiles +command rm -f $ENV_PATH/empty +ln -s $DOTFILES_PATH/common/empty-env $ENV_PATH/empty + +echo "Dotfiles Installed! Don't forget to setup environments and change the user's shell as needed!" +exec fish diff --git a/bin/dotfiles-setup-for-root b/bin/dotfiles-setup-for-root new file mode 100755 index 0000000..3d63b5c --- /dev/null +++ b/bin/dotfiles-setup-for-root @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +if [[ $UID -ne 0 ]]; then + echo "Re-running with 'sudo -E'..." + sudo -E "$0" "$@" + exit +fi + +dfp=$(cd "$(dirname "${BASH_SOURCE[0]}" )/../../" && pwd) +source "${dfp}/env/common/setup_helpers.bash" + +cp "$dfp/apps/de/sway/dm-entry" "/usr/share/wayland-sessions/lsway.desktop" + +links=( + # display manager files + "apps/de/sway/init" "/usr/bin/sway-lytedev" + + # udev rules + # TODO: how does this work in nix? + "apps/udev-rules/gcadapter" "/etc/udev/rules.d/51-gcadapter.rules" + + # tmpfiles + # TODO: does this even do anything anymore? + "apps/tmpfiles/disable-lid-wakeup" "/etc/tmpfiles.d/disable-lid-wakeup.conf" + + # lightdm + "apps/de/gnome/gdm-tap-to-click" "/etc/dconf/db/gdm.d/06-tap-to-click" +) + +_dotfiles_setup_run_setup "$HOME/.using-lytedev-etcfiles.lock" "${links[@]}" + diff --git a/bin/editscrot b/bin/editscrot new file mode 100755 index 0000000..1fe6f6c --- /dev/null +++ b/bin/editscrot @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +opener="$(command -v xdg-open 2>&1 >/dev/null && echo "xdg-open" || echo "open")" +exec nohup "$opener" "$NICE_HOME/img/scrots/$(ls -t "$NICE_HOME/img/scrots/" | head -n1)" >/dev/null 2>&1 & diff --git a/bin/email-via-mailgun-smtp b/bin/email-via-mailgun-smtp new file mode 100755 index 0000000..86aff63 --- /dev/null +++ b/bin/email-via-mailgun-smtp @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +err() { + errpre="" + errpost="" + if test -t 1; then + ncolors=$(tput colors) + if test -n "$ncolors" && test "$ncolors" -ge 8; then + errpre="$(tput setaf 1)" + errpost="$(tput setaf 7)" + fi + fi + >&2 echo "${errpre}ERROR: $*${errpost}"; usage; exit 1 +} + +warn() { + pre="" + post="" + if test -t 1; then + ncolors=$(tput colors) + if test -n "$ncolors" && test "$ncolors" -ge 8; then + pre="$(tput setaf 3)" + post="$(tput setaf 7)" + fi + fi + >&2 echo "${pre}WARNING: $*${post}" +} + +usage() { >&2 cat <&2 echo "Finished reading body. Sending email..." + +swaks --auth \ + --server smtp.mailgun.org \ + --au "$username" \ + --ap "$password" \ + --to "$recipient" \ + --h-Subject: "$subject" \ + --body "$body" \ No newline at end of file diff --git a/bin/emoji b/bin/emoji new file mode 100755 index 0000000..7955e0a --- /dev/null +++ b/bin/emoji @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +r="$(< "$HOME/.emoji.txt" sk --height 40%)" +echo "$r" | awk '$0=$1' | tr -d '\n' | clip +echo "Copied $r emoji to your clipboard" diff --git a/bin/ezln b/bin/ezln new file mode 100755 index 0000000..acd54b6 --- /dev/null +++ b/bin/ezln @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +SOURCE="$(realpath "$1")" # this one exists +DEST="$(realpath -m "$2")" # this is the link to what exists +mkdir -p "$(dirname "$2")" +ln -s "$SOURCE" "$DEST" diff --git a/bin/field b/bin/field new file mode 100755 index 0000000..d2bf241 --- /dev/null +++ b/bin/field @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +has_command gawk || { echo "No gawk." >&2 ; exit 1; } +index="${1:-1}" +[ "$#" -lt 1 ] || shift +gawk "$@" '{print $'"${index}"'}' diff --git a/bin/getip b/bin/getip new file mode 100755 index 0000000..94c6eaa --- /dev/null +++ b/bin/getip @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +curl -s --connect-timeout 3 --max-time 10 --retry 5 --retry-delay 0 \ + --retry-max-time 40 "$@" ifconfig.co/json | jq diff --git a/bin/git-authors b/bin/git-authors new file mode 100755 index 0000000..ef75b2a --- /dev/null +++ b/bin/git-authors @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +git ls-tree -r -z --name-only HEAD -- "$1" \ + | xargs -0 -n1 git blame --line-porcelain HEAD \ + | grep "^author " \ + | sort \ + | uniq -c \ + | sort -nr diff --git a/bin/gitforge-url.ts b/bin/gitforge-url.ts new file mode 100755 index 0000000..fab29dc --- /dev/null +++ b/bin/gitforge-url.ts @@ -0,0 +1,73 @@ +#!/usr/bin/env -S deno run --allow-read --allow-run --allow-net + +import * as path from "https://deno.land/std@0.181.0/path/mod.ts"; + +// output the best guess URL for viewing the file at the current git revision in +// the git forge's web interface + +// TODO: --help, -h menu + +const file = Deno.args[0]; + +if (!file) { + console.error("No file argument provided"); + Deno.exit(1); +} + +async function cmdOutput(cmd: string[]) { + return new TextDecoder().decode( + await Deno.run({ + cmd: cmd, + stdout: "piped", + }) + .output(), + ).trim(); +} + +type ForgeType = "gitlab" | "github" | "gitea"; + +function getForgeType(hostname: string): ForgeType { + if (hostname == "git.lyte.dev") { + return "gitea"; + } else if (hostname.endsWith("github.com")) { + return "github"; + } else { + return "gitlab"; + } +} + +function getUrl(repoRoot: string, remote: string, commit: string) { + try { + // try http remote + console.log(new URL(remote)); + throw new Error("HTTP(S) remotes not implemented"); + } catch { + const hostname = remote.split("@").slice(-1)[0].split(":")[0]; + const forgeType = getForgeType(hostname); + let repoPath = remote.split(":")[1]; + if (repoPath.endsWith(".git")) { + repoPath = repoPath.slice(0, -4); + } + let fileRepoPath = path.resolve(file); + if (fileRepoPath.startsWith(repoRoot)) { + fileRepoPath = fileRepoPath.slice(repoRoot.length + 1); // for the trailing slash + } else { + throw new Error(`File ${fileRepoPath} is not in repo at ${repoRoot}`); + } + switch (forgeType) { + case "gitlab": + return `https://${hostname}/${repoPath}/-/blob/${commit}/${fileRepoPath}`; + case "gitea": + return `https://${hostname}/${repoPath}/src/commit/${commit}/${fileRepoPath}`; + case "github": + return `https://${hostname}/${repoPath}/blob/${commit}/${fileRepoPath}`; + } + } +} + +// TODO: cd to dir +const repoRoot = await cmdOutput(["git", "rev-parse", "--show-toplevel"]); +const remote = await cmdOutput(["git", "remote", "get-url", "origin"]); +const commit = await cmdOutput(["git", "rev-parse", "HEAD"]); +const url = getUrl(repoRoot, remote, commit); +console.log(url); diff --git a/bin/glancepath b/bin/glancepath new file mode 100755 index 0000000..17e07bb --- /dev/null +++ b/bin/glancepath @@ -0,0 +1,11 @@ +#!/usr/bin/env -S awk -f +{ + split(substr($0, 2), p, "/"); + for (k in p) { + if (k == length(p)) { + printf "/%s", p[k] + } else { + printf "/%.3s", p[k] + } + } +} diff --git a/bin/good-morning b/bin/good-morning new file mode 100755 index 0000000..73eb7aa --- /dev/null +++ b/bin/good-morning @@ -0,0 +1,21 @@ +#!/usr/bin/env fish + +# create a messages file for subscripts to write to or manipulate for ending +# output +set message_file (mktemp) + +for f in (fd good-morning.d.fish $HOME/.config/lytedev-env --max-depth 2) + # run scripts for any linked environments with a hooked script + source $f $message_file +end + + +# output the messages file's contents +echo +command cat $message_file +echo + +# since this script almost always runs in its own window which dies after +# finishing, give the user a chance to read the output +echo "When you're ready, hit enter to finish!" +read diff --git a/bin/has_command b/bin/has_command new file mode 100755 index 0000000..48bb2d6 --- /dev/null +++ b/bin/has_command @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +[ "$#" -lt 1 ] && { echo "No arguments provided" >&2 ; exit 1; } +command -v "$1" >/dev/null 2>&1 diff --git a/bin/install-firefox-user-chrome-css.fish b/bin/install-firefox-user-chrome-css.fish new file mode 100755 index 0000000..94cab31 --- /dev/null +++ b/bin/install-firefox-user-chrome-css.fish @@ -0,0 +1,21 @@ +#!/usr/bin/env fish + +set profile_dirs $HOME/.mozilla/firefox/*.dev-edition-default $HOME/.mozilla/firefox/*.default-release +if test (uname) = Darwin + set profile_dirs $HOME/Library/Application\ Support/Firefox/Profiles/*.dev-edition-default $HOME/.mozilla/firefox/*.default-release +end + +for p in $profile_dirs + mkdir -p $p/chrome + set user_chrome_css_file $p/chrome/userChrome.css + echo '/* Generated by '(status -f)' -- do not edit manually! */' > $user_chrome_css_file + cat $DOTFILES_PATH/common/firefox/userChrome.d.css >> $user_chrome_css_file + echo >> $user_chrome_css_file + for file_part in $ENV_PATH/*/firefox/userChrome.d.css + cat $file_part >> $user_chrome_css_file + echo >> $user_chrome_css_file + end + echo Built $user_chrome_css_file +end + +echo Make sure you set 'toolkit.legacyUserProfileCustomizations.stylesheets' to true in about:config diff --git a/bin/is_wayland b/bin/is_wayland new file mode 100755 index 0000000..0bdd24b --- /dev/null +++ b/bin/is_wayland @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +exit 0 +# loginctl show-session "$(loginctl | grep "$(whoami)" | head -n 1 | field 1)" -p Type | grep -i wayland >/dev/null diff --git a/bin/k8s-yaml-diff b/bin/k8s-yaml-diff new file mode 100755 index 0000000..4170390 --- /dev/null +++ b/bin/k8s-yaml-diff @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +[ "$#" -lt 2 ] && echo "Need two filenames." && exit 1 + +f1="$1"; shift +f2="$1"; shift + +nvim -d <(k8s-yaml-sort "$f1") <(k8s-yaml-sort "$f2") diff --git a/bin/k8s-yaml-sort b/bin/k8s-yaml-sort new file mode 100755 index 0000000..9766ba9 --- /dev/null +++ b/bin/k8s-yaml-sort @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +[ "$#" -lt 1 ] && echo "Need a filename." && exit 1 +< "$1" yq -s . | jq -S ' + sort_by(.metadata.name) | + sort_by(.kind) | + .[] | .spec.template.spec.containers |= + if . == null then empty + else + map( + if . == null then empty + else .env |= sort_by(.name) + | .volumeMounts |= sort_by(.name) + end + ) + end + ' diff --git a/bin/keyrepeat b/bin/keyrepeat new file mode 100755 index 0000000..12686fc --- /dev/null +++ b/bin/keyrepeat @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +xset r rate 250 80 diff --git a/bin/kubeline b/bin/kubeline new file mode 100755 index 0000000..226cc6b --- /dev/null +++ b/bin/kubeline @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +c="$(kubectl config current-context | tr -d "\n")" +if [ -n "$c" ]; then + printf "%s" "$c" +fi +a="$(kubectl config view --minify --output 'jsonpath={..namespace}')" +if [ -n "$a" ]; then + printf ".%s" "$a" +fi diff --git a/bin/kubfc b/bin/kubfc new file mode 100755 index 0000000..b925485 --- /dev/null +++ b/bin/kubfc @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +kubectl config get-contexts --no-headers | \ + uniq | \ + sort | \ + tr -s ' ' | \ + sed -E 's/^\*?[[:space:]]*//g' | \ + cut -d ' ' -f1 | \ + sk | \ + xargs -I{} kubectl config use-context '{}' diff --git a/bin/kubfn b/bin/kubfn new file mode 100755 index 0000000..5221a16 --- /dev/null +++ b/bin/kubfn @@ -0,0 +1,12 @@ +#!/usr/bin/env sh +has_command kubectl || { + echo "kubectl command not found" + exit 1 +} + +kubectl get namespaces --show-labels | \ + uniq | \ + sort | \ + cut -d ' ' -f1 | \ + sk | \ + xargs -I{} kubectl config set-context --current --namespace='{}' diff --git a/bin/launch b/bin/launch new file mode 100755 index 0000000..58a78ea --- /dev/null +++ b/bin/launch @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +LAUNCHER_HISTORY_FILE="$HOME/.local/share/lytelaunch/launch.log" +mkdir --parents "$(dirname "$LAUNCHER_HISTORY_FILE")" +touch "$LAUNCHER_HISTORY_FILE" +app="$( + < "$LAUNCHER_HISTORY_FILE" \ + awk 'NF{NF--};1' | \ + cat - <(dmenu_path) | \ + sort | uniq -c | sort -nr | \ + sd -fm '^\s+' '' | \ + cut -d' ' -f2- | \ + grep "\S" | \ + sk + )" +# if no app is selected, just exit +test -z "$app" && exit 1 +echo "$app $(date +%s)" >> "$LAUNCHER_HISTORY_FILE" +echo "$app" diff --git a/bin/linewise b/bin/linewise new file mode 100755 index 0000000..4780293 --- /dev/null +++ b/bin/linewise @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +if [[ -n "${1+x}" ]]; then + while read -r line; do + <<< "${line}" "$@" + done +else + echo "No reader program provided." + exit 1 +fi diff --git a/bin/maybe_source_env_file b/bin/maybe_source_env_file new file mode 100755 index 0000000..d79a8b8 --- /dev/null +++ b/bin/maybe_source_env_file @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +f="$1"; shift +[ -f "$f" ] && source "$f" "$@" +true diff --git a/bin/nd b/bin/nd new file mode 100755 index 0000000..3c73c80 --- /dev/null +++ b/bin/nd @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +fn="${1}"; shift; N "$(date +%Y-%m-%d)_${fn}" "$@" diff --git a/bin/nf b/bin/nf new file mode 100755 index 0000000..9eaef3f --- /dev/null +++ b/bin/nf @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +SUBDIR="${2:-./}" +mkdir -p "$NOTES_PATH/$SUBDIR" +cd "$NOTES_PATH/$SUBDIR" || exit 1 +"$EDITOR" "$NOTES_PATH/$SUBDIR/$1" +cd - || exit 1 diff --git a/bin/note b/bin/note new file mode 100755 index 0000000..0715d73 --- /dev/null +++ b/bin/note @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +fn="${1}"; shift; N "$(date +%Y-%m-%d)_${fn}" "$@" diff --git a/bin/nsync b/bin/nsync new file mode 100755 index 0000000..5e70fcc --- /dev/null +++ b/bin/nsync @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# TODO: warn on merge conflicts? +cd "${NOTES_PATH}" || exit +git add -A +git commit -m Updates +git fetch && git merge origin/master && git push +cd - || exit diff --git a/bin/nvimdiff b/bin/nvimdiff new file mode 100755 index 0000000..9650db8 --- /dev/null +++ b/bin/nvimdiff @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +nvim -d "$@" diff --git a/bin/open-in-git-forge b/bin/open-in-git-forge new file mode 100755 index 0000000..30e4549 --- /dev/null +++ b/bin/open-in-git-forge @@ -0,0 +1,21 @@ +#!/usr/bin/env sh + +usage() { + echo "open-in-git-forge <$FILE>[#L$LINE_NUMBERS]" + echo " Opens the URL in your browser to the git forge's web interface for the current branch for $FILE" + echo + echo " Examples:" + echo " \$ open-in-git-forge readme.md#L12" +} + +if [ "$#" -lt 1 ]; then + usage + exit 1 +fi + +url="$(gitforge-url.ts "$1")" +case "$(uname)" in + Linux*) xdg-open "$url";; + Darwin*) open "$url";; + *) echo "OS not supported"; exit 1; +esac \ No newline at end of file diff --git a/bin/optimize-photo-for-web b/bin/optimize-photo-for-web new file mode 100755 index 0000000..dfd05d7 --- /dev/null +++ b/bin/optimize-photo-for-web @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +mogrify \ + -filter Triangle \ + -define filter:support=2 \ + -resize 2000x2000\> \ + -unsharp 0.25x0.08+8.3+0.045 \ + -dither None \ + -posterize 136 \ + -quality 82 \ + -define jpeg:fancy-upsampling=off \ + -define png:compression-filter=5 \ + -define png:compression-level=9 \ + -define png:compression-strategy=1 \ + -define png:exclude-chunk=all \ + -interlace none \ + -colorspace sRGB \ + "$1" diff --git a/bin/pass-migrate-to-pass-otp b/bin/pass-migrate-to-pass-otp new file mode 100755 index 0000000..a6979aa --- /dev/null +++ b/bin/pass-migrate-to-pass-otp @@ -0,0 +1,6 @@ +#!/usr/bin/env fish + +set entry $argv[1] +set otp_secret (pass $entry | awk -F': ' '/^otp/{gsub(/\s/,"",$2);print $2}') +set otp_uri "otpauth://totp/totp-secret?secret=$otp_secret&issuer=$entry" +echo $otp_uri | pass otp append $entry diff --git a/bin/pipeline b/bin/pipeline new file mode 100755 index 0000000..6b62334 --- /dev/null +++ b/bin/pipeline @@ -0,0 +1,41 @@ +#!/usr/bin/env sh + +SAVED_PIPELINE_DIR="$DOTFILES_PATH/env/common/data/pipelines" +mkdir -p "$SAVED_PIPELINE_DIR" + +if [ -n "${1+x}" ]; then + pdir="$SAVED_PIPELINE_DIR/$1"; shift + mkdir -p "$pdir" + if [ -z ${1+x} ]; then + td="$(mktemp -p "$pdir" -d "tmp_pipeline.XXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$td'" EXIT + else + td="$pdir/$1"; shift + mkdir -p "$td" + fi + transform="$pdir/transform" +else + td="$(mktemp --tmpdir -d pipeline.XXXXXXXX)" + transform="$td/transform" + # shellcheck disable=SC2064 + trap "rm -rf '$td'" EXIT +fi + +[ ! -e "$transform" ] && \ + printf "#!/usr/bin/env bash\n# you must save this buffer manually\n# for %s\n +base64" "${td}" > "$transform" + +in="$td/in"; [ -n "${1+x}" ] && in="${1}" && shift +out="$td/out"; [ -n "${1+x}" ] && out="${1}" && shift + +# TODO: if no logging, log="/dev/null" +log="$td/log" +touch "$log" + +chmod +x "$transform" + +# TODO: saved inputs? +echo "Hello World" > "$in" + +env PIPELINE_IN="$in" PIPELINE_TRANSFORM="$transform" PIPELINE_OUT="$out" nvim --cmd "source $DOTFILES_PATH/apps/neovim/scripts/pipeline.vim" diff --git a/bin/poll b/bin/poll new file mode 100755 index 0000000..63a7210 --- /dev/null +++ b/bin/poll @@ -0,0 +1,12 @@ +#!/usr/bin/env fish + +# make sure our stuff gets loaded so aliases will work +source ~/.config/fish/config.fish + +while true + clear + sleep 2 & + echo (tput setaf 0)(date) polled (tput setaf 4)"'"$argv"'"(tput setaf 7) + eval $argv + wait +end \ No newline at end of file diff --git a/bin/pr-for-commit b/bin/pr-for-commit new file mode 100755 index 0000000..685c41c --- /dev/null +++ b/bin/pr-for-commit @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +GITHUB_UPSTREAM="$(git remote -vv | awk '{$0=$2}')" + +git log --merges --ancestry-path --oneline "$1"..master \ + | grep -i 'pull request' \ + | tail -n1 \ + | awk '{$0=$5}' \ + | cut -c2- \ + | xargs -I % open https://github.com/"$GITHUB_UPSTREAM"/"${PWD##*/}"/pull/% diff --git a/bin/readme.md b/bin/readme.md new file mode 100644 index 0000000..dd2afc2 --- /dev/null +++ b/bin/readme.md @@ -0,0 +1,4 @@ +This directory contains scripts and stuff I want in my PATH whether NixOS, some +other Linux, or macOS. + +For OS-specific executables, see the OS-specific subdirectories. diff --git a/bin/remote b/bin/remote new file mode 100755 index 0000000..98490c6 --- /dev/null +++ b/bin/remote @@ -0,0 +1,11 @@ +#!/usr/bin/env moon + +arg_spec = { + {"target", "REMOTE_MACHINE", "remote"} + {"mpr", "MOSH_PORT_RANGE", "60000:61000"} + {"sargs", "SSH_ARGS", "-XY"} + {"margs", "MOSH_ARGS", ""} +} + +args = {v[1], os.getenv(v[2]) or arg[i] or v[3] for i, v in ipairs(arg_spec)} +os.execute "mosh -p '#{args.mpr}' '#{args.target}' --ssh='ssh #{args.sargs}' #{args.margs}" diff --git a/bin/resource-usage b/bin/resource-usage new file mode 100755 index 0000000..90fac80 --- /dev/null +++ b/bin/resource-usage @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# TODO: radeontop can continuously dump to a file, would be fast to just keep +# last line and have this run in the background +gpu_usage="$(radeontop -l 1 -d - | rg --color never -o "gpu (\d+.\d+)" -r '$1')" +gpu_temp="$(sensors | rg 'amdgpu.*mem:\s+\+(\d+\.\d+)' --multiline-dotall --multiline -o -r '$1')" + +# NOTE: this is all cpu usage since boot: +# cpu_usage_data_snapshot="$(cat /proc/stat | head -n 1 | cut -d ' ' -f 2- | sd '^\s+' '')" +# function cpu_usage_data() { +# echo "$cpu_usage_data_snapshot" +# } +# cpu_usage="$(bc -l <<< "100-(100*($(cpu_usage_data | awk '{printf $4}').0/$(cpu_usage_data | sd " " "+" | bc).0))")" + +mpstat_samples=2 +mpstat_sample_seconds=1 +cpu_idle="$(mpstat --dec=2 "$mpstat_sample_seconds" "$mpstat_samples" | tail -n 1 | field 12)" +cpu_usage="$(echo "100.0-$cpu_idle" | bc -l)" +cpu_temp="0.0" + +printf "GPU [USAGE: %6.2f%%] [THERMALS: %6.2f°C]\n" "$gpu_usage" "$gpu_temp" +printf "CPU [USAGE: %6.2f%%] [THERMALS: %6.2f°C]\n" "$cpu_usage" "$cpu_temp" + diff --git a/bin/restartbar b/bin/restartbar new file mode 100755 index 0000000..26da65d --- /dev/null +++ b/bin/restartbar @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +stopbar && startbar & diff --git a/bin/s b/bin/s new file mode 100755 index 0000000..37660b0 --- /dev/null +++ b/bin/s @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +N _scratch diff --git a/bin/scn b/bin/scn new file mode 100755 index 0000000..418774d --- /dev/null +++ b/bin/scn @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +EDITOR="sc-im" nf "$@" diff --git a/bin/screenshot b/bin/screenshot new file mode 100755 index 0000000..0dc661b --- /dev/null +++ b/bin/screenshot @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +SCROT_DIR="$NICE_HOME/img/scrots" +mkdir -p "$SCROT_DIR/" +FILENAME="$SCROT_DIR/screenshot_$(date +%Y-%m-%d_%H-%M-%S).png" +grim -t png "$@" "${FILENAME}" >/dev/null && echo "Saved screenshot to: ${FILENAME}" diff --git a/bin/script-opts b/bin/script-opts new file mode 100755 index 0000000..54cf829 --- /dev/null +++ b/bin/script-opts @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +# TODO: helper for taking a data structure and building bash args? diff --git a/bin/scrup b/bin/scrup new file mode 100755 index 0000000..6aabed8 --- /dev/null +++ b/bin/scrup @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -x + +remote_dir="scrots" +url_prefix="https://files.lyte.dev/$remote_dir" + +u="$(uuid -v4)" +d="$(date +%Y-%m-%d_%H-%M-%S)" + +fn="$(clipshot)" +if [ $? -eq 0 ]; then + echo "Scrot captured. Uploading..." + upload "${fn}" "scrup-$u-$d.png" "$remote_dir" + echo "$url_prefix/scrup-$u-$d.png" | clip + notify-send "Scrot uploaded. URL in clipboard." +else + exit 1 +fi diff --git a/bin/scwd b/bin/scwd new file mode 100755 index 0000000..7363f62 --- /dev/null +++ b/bin/scwd @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +addon=""; [ -n "$1" ] && addon="-${1}" +echo "${PWD}" > "${DOTFILES_PATH}/.cwd${addon}.tmp" diff --git a/bin/setbg b/bin/setbg new file mode 100755 index 0000000..0541dd6 --- /dev/null +++ b/bin/setbg @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +index="${2}" +wp_file="${HOME}/.wallpaper${index}" +rm -f "${wp_file}" +echo "Setting ${1} as ${wp_file}" +ln -s "$(realpath "${1}")" "${wp_file}" +"${HOME}/.fehbg" diff --git a/bin/simple-otp b/bin/simple-otp new file mode 100755 index 0000000..889fdc4 --- /dev/null +++ b/bin/simple-otp @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# TODO: check for oathtool + +key="$1"; shift +args=("$@") + +oathtool --totp=sha1 -b "$key" "${args[@]}" diff --git a/bin/source_if_exists b/bin/source_if_exists new file mode 100755 index 0000000..6ef4611 --- /dev/null +++ b/bin/source_if_exists @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +[ "$#" -lt 1 ] && { echo "No arguments provided" >&2 ; exit 1; } + +# shellcheck disable=SC1090 +f="$1"; shift +{ [ -f "$f" ] && source "$f" "$@"; } || { echo "$f does not exist" >&2 ; exit 3; } diff --git a/bin/startbar b/bin/startbar new file mode 100755 index 0000000..c1c1bc1 --- /dev/null +++ b/bin/startbar @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +"${DOTFILES_PATH}/apps/de/polybar/run" diff --git a/bin/stopbar b/bin/stopbar new file mode 100755 index 0000000..af24e17 --- /dev/null +++ b/bin/stopbar @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# TODO: get the proper monitor! +BAR_MONITOR="$(polybar --list-monitors | tail -n 1 | sed -n 's/^\s*\(.*\):.*$/\1/p')" +bspc config -m "${BAR_MONITOR}" bottom_padding "0" +bspc config -m "${BAR_MONITOR}" top_padding "0" +killall -q polybar +while pgrep -x polybar >/dev/null; do sleep 1; done diff --git a/bin/sw b/bin/sw new file mode 100755 index 0000000..753bb46 --- /dev/null +++ b/bin/sw @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +d="$(date +%s)" +_dt=$(($(date +%s) - d)) +echo "Stopwatch started $(date)" + +trap 'echo -ne "\nStopwatch stopped at $(date)\n" && exit 0' SIGINT + +while true; do + _dt=$(($(date +%s) - d)) + days=$((_dt / 86400)) + echo -ne "\r${days}d $(date -u --date @$((_dt)) +%H:%M:%S) " + sleep 0.1 +done + +# TODO: add "lap" capabilities? + diff --git a/bin/tdf b/bin/tdf new file mode 100755 index 0000000..e712a4a --- /dev/null +++ b/bin/tdf @@ -0,0 +1,2 @@ +#!/usr/bin/env fish +tmux-lyte-session dotfiles $DOTFILES_PATH diff --git a/bin/tenv b/bin/tenv new file mode 100755 index 0000000..fee13a1 --- /dev/null +++ b/bin/tenv @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +d="$(command ls "$ENV_PATH" | sk)" && \ + tmux-lyte-session "env-$d" "$ENV_PATH/$d" diff --git a/bin/terminal-rendering-test b/bin/terminal-rendering-test new file mode 100755 index 0000000..667e0a5 --- /dev/null +++ b/bin/terminal-rendering-test @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# sources: +# https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i +# https://askubuntu.com/questions/27314/script-to-display-all-terminal-colors + +indent=" " +padding=" " +reset="\e[0;39;49m" + +for s in {0..8}; do # text styles + for t in {30..37}; do # text color + for b in {40..47}; do # background + echo -ne "${indent}\e[$s;$t;${b}m${padding}\\\e[$s;$t;${b}m${padding}${reset}" + done + echo + done + echo +done +echo -e "Emoji: 😱😍😬🎉" +echo -e "Possible Ligatures:" +echo -r " --> -> == != === ------> ** ++ |> <* := :: |] [| ===>" +echo -r " >= <= =>= ->- >>- <<- <***> =: <. <.> .> ~> ~~> ~~~~>" +echo -r " (* |- -| =!= :> |} {| >=> <=< ++++ ___" +echo diff --git a/bin/termrec b/bin/termrec new file mode 100755 index 0000000..d4a6e62 --- /dev/null +++ b/bin/termrec @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +asciinema rec -i 2 --stdin diff --git a/bin/tls b/bin/tls new file mode 100755 index 0000000..2ef55ac --- /dev/null +++ b/bin/tls @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +tmux list-sessions diff --git a/bin/tmux-edit-buffer b/bin/tmux-edit-buffer new file mode 100755 index 0000000..c24e6b9 --- /dev/null +++ b/bin/tmux-edit-buffer @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +f="$(tmux-save-buffer)" +tmux new-window "$EDITOR $f" diff --git a/bin/tmux-lyte-session b/bin/tmux-lyte-session new file mode 100755 index 0000000..8a82474 --- /dev/null +++ b/bin/tmux-lyte-session @@ -0,0 +1,11 @@ +#!/usr/bin/env fish + +set session_name $argv[1] +set dir (set -q argv[2] && echo $argv[2] || pwd) + +if set -q TMUX + tmux switch -t $session_name +else + tmux new-session -D -s "$session_name" -c "$dir" $argv[3..-1] &>/dev/null || \ + tmux attach -t "$session_name" -c "$dir" +end diff --git a/bin/tmux-save-buffer b/bin/tmux-save-buffer new file mode 100755 index 0000000..45698c8 --- /dev/null +++ b/bin/tmux-save-buffer @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +d="$(date +%Y-%m-%d_%H-%M-%S)" +f="${USER_LOGS_PATH}/${d}.tmux-buffer.log" +mkdir -p "$(dirname "$f")" +touch "$f" +chmod 600 "$f" +tmux capture-pane -pS -1000000000 > "$f" +echo "$f" diff --git a/bin/tmux-session-dir b/bin/tmux-session-dir new file mode 100755 index 0000000..105327b --- /dev/null +++ b/bin/tmux-session-dir @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +# if inside a session, use the current session +# if not, a session must be specified after the dir +d="${1}" +[ -z "$d" ] && d="#{pane_current_path}" +target_session="${2}" +[ -n "$TMUX" ] && target_session="." +tmux attach-session -t "$target_session" -c "$d" diff --git a/bin/tmux-session-preview b/bin/tmux-session-preview new file mode 100755 index 0000000..0684b1c --- /dev/null +++ b/bin/tmux-session-preview @@ -0,0 +1,13 @@ +#!/usr/bin/env sh + +session_data="$1" +session_id="$(echo "$session_data" | cut -d':' -f1)" + +S="$(tmux ls -F'#{session_id} #{session_name}: #{T:tree_mode_format}' | grep ^"$session_id")" +session_info="${S##$s}" +session_name="$(echo "$session_info" | cut -d ':' -f1)" + +echo "RAW: $1" +echo "S: $S" +echo "INFO: $session_info" +echo "NAME: $session_name" diff --git a/bin/tmuxswitcher b/bin/tmuxswitcher new file mode 100755 index 0000000..bd51f9c --- /dev/null +++ b/bin/tmuxswitcher @@ -0,0 +1,22 @@ +#!/usr/bin/env sh + +fmt='#{session_id}:|#S|(#{session_attached} attached)' +t="tmux switch-client -t" +[ -z "$TMUX" ] && t="tmux attach-session -t" + +sess="$({ tmux display-message -p -F "$fmt" && tmux list-sessions -F "$fmt"; } \ + | awk '!seen[$1]++' \ + | column -t -s'|' \ + | sk -q '$' --reverse --prompt 'switch session: ' -1 --preview "tmux-session-preview {}" \ + | cut -d':' -f1)" + +[ -z "$sess" ] && exit 1 + +$t "$sess" + + + +# | while read w; do + # set W (tmux lsw -t"{}" -F'#{window_id}#{T:tree_mode_format}' | grep ^"$w") + # echo " ﬌ ${W##$w}" + # end diff --git a/bin/unarchive b/bin/unarchive new file mode 100755 index 0000000..b02272e --- /dev/null +++ b/bin/unarchive @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +archive_name="${1}"; shift +to_dir="$(basename "$archive_name")" +mkdir -p "${to_dir}" +pushd "${to_dir}" || ( echo "${to_dir} does not exist" ; exit 1 ) +tar --zstd -xvf "${archive_name}" +echo "Unarchived to: ${to_dir}" +popd || exit 2 diff --git a/bin/unbackupify b/bin/unbackupify new file mode 100755 index 0000000..bfd2c20 --- /dev/null +++ b/bin/unbackupify @@ -0,0 +1,56 @@ +#!/usr/bin/env fish + +# deps: fish, zstd, gpg, ssh + +set -q HOST || set HOST (head -n 1 /etc/hostname | tr -d '\n') + +# use the backup-host in the ~/.ssh/config as the default backup remote host +set -q BACKUP_REMOTE_HOST || set BACKUP_REMOTE_HOST backup-host + +# use a user-specific dir by default to backup to +set -q BACKUP_REMOTE_DIR || set BACKUP_REMOTE_DIR "/storage/"(whoami)"/backups/$HOST" + +set BACKUP_FILE_EXT .tar.zstd.gpg + +set target $argv[1] +if test $target = '--list-backup-files' + ssh $BACKUP_REMOTE_HOST "command ls -1 $BACKUP_REMOTE_DIR" + exit 0 +else if test (count $argv) -lt 1 + echo "No remote backup filename provided (use --list-backup-files to show)" + exit 1 +end + +ssh $BACKUP_REMOTE_HOST "echo 1" &>/dev/null || begin + echo "Cannot ssh to $BACKUP_REMOTE_HOST" + exit 6 +end + +ssh $BACKUP_REMOTE_HOST "test -d $BACKUP_REMOTE_DIR/$target" || begin + echo "Remote directory $BACKUP_REMOTE_DIR/$target does not exist on $BACKUP_REMOTE_HOST (use --list-backup-files to show)" + exit 5 +end + +# TODO: autocomplete? +# TODO: checksum? +# TODO: progress indicator? + +set local_dir (echo $target | awk -F. '{print $1}') +mkdir $local_dir || begin + echo "Local unbackup directory '$local_dir' exists" + exit 2 +end + +pushd $local_dir >/dev/null + + ssh $BACKUP_REMOTE_HOST "cat $BACKUP_REMOTE_DIR/$target" | + gpg --decrypt 2>/dev/null | + zstd --ultra -T2 -22 -dc | + tar -xf - || begin + echo "Failed to stream backup" + exit 4 + end + +popd >/dev/null + +echo "Restored to $local_dir" diff --git a/bin/weather b/bin/weather new file mode 100755 index 0000000..332009f --- /dev/null +++ b/bin/weather @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +curl 'wttr.in/@h.lyte.dev?format=%l%20%T:%20%t%20%C%20%w%20%h' diff --git a/bin/work-journal-entry b/bin/work-journal-entry new file mode 100755 index 0000000..77414f1 --- /dev/null +++ b/bin/work-journal-entry @@ -0,0 +1,4 @@ +#!/usr/bin/env fish +N work/divvy/(date +%Y-%m-%d) && \ + pushd $NOTES_PATH && git add -A && \ + git commit -m "Edit work journal entry for "(date +%Y-%m-%d) && nsync diff --git a/bin/yamldiff b/bin/yamldiff new file mode 100755 index 0000000..fdecc6f --- /dev/null +++ b/bin/yamldiff @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +[ "$#" -lt 2 ] && echo "Need two filenames." && exit 1 + +f1="$1"; shift; echo "$f1" >&2 +f2="$1"; shift; echo "$f2" >&2 + +nvim -d <(yq . "$f1" | jq -S .) <(yq . "$f2" | jq -S .) diff --git a/daniel.nix b/daniel.nix index a80f959..4eac11c 100644 --- a/daniel.nix +++ b/daniel.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, ... }: { +{ pkgs, lib, inputs, ... }: { # TODO: email access? # accounts.email.accounts = { # google = { @@ -14,7 +14,7 @@ home.stateVersion = "23.05"; home.packages = [ - + inputs.rtx.packages.rtx ]; programs.password-store = { @@ -130,7 +130,7 @@ }; verbs = [ - { invocation = "edit"; shortcut = "e"; execution = "$EDITOR +{line} {file}"; } + { invocation = "edit"; shortcut = "e"; execution = "$EDITOR {file}"; } ]; }; }; diff --git a/flake.lock b/flake.lock index 0109a7d..6137f09 100644 --- a/flake.lock +++ b/flake.lock @@ -122,6 +122,21 @@ "type": "github" } }, + "flake-utils_3": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "helix": { "inputs": { "crane": "crane", @@ -221,9 +236,31 @@ "helix": "helix", "home-manager": "home-manager", "nixpkgs": "nixpkgs_2", + "rtx": "rtx", "sops-nix": "sops-nix" } }, + "rtx": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1693923183, + "narHash": "sha256-TH2JC+Cjw+ed1O33QKGq+lonIKlu6pHuY1jtrZh/FMM=", + "owner": "jdx", + "repo": "rtx", + "rev": "f333ac5f8e8de399fcb3ce40576baeef0271081b", + "type": "github" + }, + "original": { + "owner": "jdx", + "repo": "rtx", + "type": "github" + } + }, "rust-overlay": { "inputs": { "flake-utils": [ diff --git a/flake.nix b/flake.nix index f0e16f1..b92c1d9 100644 --- a/flake.nix +++ b/flake.nix @@ -34,6 +34,11 @@ url = "github:helix-editor/helix"; inputs.nixpkgs.follows = "nixpkgs"; }; + + rtx = { + url = "github:jdx/rtx"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { self, ... }@inputs: { @@ -42,6 +47,7 @@ normalUefiBtrfs = import ./machines/musicbox-disks.nix; }; homeConfigurations = + # TODO: per arch? let system = "x86_64-linux"; pkgs = inputs.nixpkgs.legacyPackages.${system}; diff --git a/machines/thinker.nix b/machines/thinker.nix index 08d762b..315e4f2 100644 --- a/machines/thinker.nix +++ b/machines/thinker.nix @@ -182,6 +182,7 @@ in git-lfs grim inputs.helix.packages."x86_64-linux".helix + inputs.rtx.packages."x86_64-linux".rtx hexyl htop inkscape