summaryrefslogtreecommitdiff
path: root/.local/bin
diff options
context:
space:
mode:
Diffstat (limited to '.local/bin')
-rwxr-xr-x.local/bin/automountd12
-rwxr-xr-x.local/bin/backup33
-rwxr-xr-x.local/bin/clearx51
-rwxr-xr-x.local/bin/desktop/beautify102
-rwxr-xr-x.local/bin/desktop/brightness32
-rwxr-xr-x.local/bin/desktop/detect-keys3
-rwxr-xr-x.local/bin/desktop/dmenu-syncthing-devices25
-rwxr-xr-x.local/bin/desktop/dmenu-unicode11
-rwxr-xr-x.local/bin/desktop/dmenu-zeal27
-rwxr-xr-x.local/bin/desktop/edit-graphical-buffer17
-rwxr-xr-x.local/bin/desktop/i3exit54
-rwxr-xr-x.local/bin/desktop/i3exit-script18
-rwxr-xr-x.local/bin/desktop/librewolf-open39
-rwxr-xr-x.local/bin/desktop/mlock22
-rwxr-xr-x.local/bin/desktop/remap146
-rwxr-xr-x.local/bin/desktop/remapd6
-rwxr-xr-x.local/bin/desktop/setdp36
-rwxr-xr-x.local/bin/desktop/show-i3-keybindings11
-rwxr-xr-x.local/bin/desktop/toggle-xeyes7
-rwxr-xr-x.local/bin/desktop/torbrowser30
-rwxr-xr-x.local/bin/desktop/volctl50
-rwxr-xr-x.local/bin/development/dev179
-rwxr-xr-x.local/bin/development/getcomproot14
-rwxr-xr-x.local/bin/development/gitpush10
-rwxr-xr-x.local/bin/development/gitw18
-rwxr-xr-x.local/bin/development/ipy4
-rwxr-xr-x.local/bin/development/ipytest23
-rwxr-xr-x.local/bin/development/nx148
-rwxr-xr-x.local/bin/development/opout12
-rwxr-xr-x.local/bin/development/pipsearch4
-rwxr-xr-x.local/bin/development/py4
-rwxr-xr-x.local/bin/development/pyh12
-rwxr-xr-x.local/bin/development/texclear9
-rwxr-xr-x.local/bin/fcode23
-rwxr-xr-x.local/bin/fdict25
-rwxr-xr-x.local/bin/fgrp27
-rwxr-xr-x.local/bin/filter52
-rwxr-xr-x.local/bin/fm22
-rwxr-xr-x.local/bin/fmd26
-rwxr-xr-x.local/bin/fpm148
-rwxr-xr-x.local/bin/fsend47
-rwxr-xr-x.local/bin/fw10
-rwxr-xr-x.local/bin/help99
-rwxr-xr-x.local/bin/launch-gtypist101
-rwxr-xr-x.local/bin/lessopen.sh9
-rwxr-xr-x.local/bin/loop45
-rwxr-xr-x.local/bin/lsinputs12
-rwxr-xr-x.local/bin/mnt39
-rwxr-xr-x.local/bin/open48
-rwxr-xr-x.local/bin/preview59
-rwxr-xr-x.local/bin/search62
-rwxr-xr-x.local/bin/searchdb35
-rwxr-xr-x.local/bin/setbg18
-rwxr-xr-x.local/bin/shortcuts35
-rwxr-xr-x.local/bin/shorts/adbs3
-rwxr-xr-x.local/bin/shorts/append-to-history5
-rwxr-xr-x.local/bin/shorts/bs7
-rwxr-xr-x.local/bin/shorts/conv10
-rwxr-xr-x.local/bin/shorts/diffdirs6
-rwxr-xr-x.local/bin/shorts/font2svg3
-rwxr-xr-x.local/bin/shorts/preview-bat3
-rwxr-xr-x.local/bin/shorts/preview-highlight3
-rwxr-xr-x.local/bin/shorts/refcitx6
-rwxr-xr-x.local/bin/shorts/sc3
-rwxr-xr-x.local/bin/shorts/scrcpy-k8
-rwxr-xr-x.local/bin/shorts/ssha5
-rwxr-xr-x.local/bin/shorts/sync-server12
-rwxr-xr-x.local/bin/shorts/syncdrive3
-rwxr-xr-x.local/bin/shorts/synchs7
-rwxr-xr-x.local/bin/shorts/synctab19
-rwxr-xr-x.local/bin/shorts/xdg-terminal-exec3
-rwxr-xr-x.local/bin/shorts/xprint8
-rwxr-xr-x.local/bin/sshadd17
-rwxr-xr-x.local/bin/statusbar/cpu_usage55
-rwxr-xr-x.local/bin/statusbar/i3bandwidth105
-rwxr-xr-x.local/bin/statusbar/i3battery66
-rwxr-xr-x.local/bin/statusbar/i3cpu34
-rwxr-xr-x.local/bin/statusbar/i3cpubars44
-rwxr-xr-x.local/bin/statusbar/i3cpuload68
-rwxr-xr-x.local/bin/statusbar/i3memory33
-rwxr-xr-x.local/bin/statusbar/i3weather26
-rwxr-xr-x.local/bin/statusbar/i3wifi37
-rwxr-xr-x.local/bin/statusbar/memory_percent57
-rwxr-xr-x.local/bin/statusbar/memory_usage56
-rwxr-xr-x.local/bin/ttyl37
-rwxr-xr-x.local/bin/unix26
-rwxr-xr-x.local/bin/web/fpl39
-rwxr-xr-x.local/bin/web/savesite35
-rwxr-xr-x.local/bin/web/w3mman335
-rwxr-xr-x.local/bin/web/ytf10
-rwxr-xr-x.local/bin/web/ytplaylist34
-rwxr-xr-x.local/bin/web/ytv3
92 files changed, 3342 insertions, 0 deletions
diff --git a/.local/bin/automountd b/.local/bin/automountd
new file mode 100755
index 0000000..f09871f
--- /dev/null
+++ b/.local/bin/automountd
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+pathtoname() {
+ udevadm info -p /sys/"$1" | awk -v FS== '/DEVNAME/ {print $2}'
+}
+
+stdbuf -oL -- udevadm monitor --udev -s block | while read -r -- _ _ event devpath _; do
+ if [ "$event" = add ]; then
+ devname=$(pathtoname "$devpath")
+ udisksctl mount --block-device "$devname" --no-user-interaction
+ fi
+done
diff --git a/.local/bin/backup b/.local/bin/backup
new file mode 100755
index 0000000..8f6e00d
--- /dev/null
+++ b/.local/bin/backup
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+sudo cryptsetup open /dev/sdb1 backup
+sudo mount --mkdir /dev/mapper/backup /mnt/backup
+backup="/mnt/backup/$(hostname)"
+[ -d "$backup" ] ||
+ { echo "$0: directory doesn't exist: $backup" >&2; exit 1; }
+
+cd ~ || exit
+rsync -Plru --delete \
+ .config \
+ .git \
+ .gnupg \
+ .local \
+ .librewolf \
+ .ssh \
+ bin \
+ DCIM \
+ Dev \
+ Documents \
+ Downloads \
+ GDrive \
+ Music \
+ Phone \
+ Pictures \
+ repos \
+ Videos \
+ "$backup/home/$USER/"
+
+find . -maxdepth 1 \( -type f -o -type l \) -exec rsync -Plu {} "$backup/home/$USER" \;
+
+echo "Backing up /etc directory..."
+sudo rsync -Plruq --delete /etc "$backup"
diff --git a/.local/bin/clearx b/.local/bin/clearx
new file mode 100755
index 0000000..225c208
--- /dev/null
+++ b/.local/bin/clearx
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+help() { echo "clearx - execute command in clear screen
+
+USAGE:
+ clearx [OPTION]... <command>
+
+OPTIONS:
+ -n no prompt when exiting
+ -h show this help message"; }
+
+err() { printf 'clearx: %s\n' "$@" >&2; exit 1; }
+while getopts 'nh' o; do case "$o" in
+ n) nflag=0 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+cmds="$*"
+[ "$nflag" = 0 ] ||
+ cmds="$cmds; printf '\n%s' 'Press <Enter> to continue: '; read -r arg"
+
+tmuxcmds="tmux set status off; $cmds; tmux set status on;"
+set_screen() {
+ [ -z "$TMUX" ] &&
+ err '$TMUX not set, only tmux is supported for screen program'
+ tmux new-window -n clearx "$tmuxcmds"
+}
+new_screen() { tmux new-session -s clearx "$tmuxcmds"; }
+
+terminal_emulator() {
+ [ -z "$DISPLAY" ] && return 1
+ #err 'clearx: terminal_emulator: $DISPLAY not set'
+ case "$TERMINAL" in
+ '') echo 'clearx: $TERMINAL not set' && exit 1 ;;
+ alacritty) export TERMINAL="alacritty" ;;
+ esac
+ wmctrl -r :ACTIVE: -b remove,fullscreen
+ $TERMINAL -e sh -c "sleep 0.2; $cmds" &
+ sleep 0.2 && wmctrl -r :ACTIVE: -b add,fullscreen
+}
+
+case "$TERM" in
+ '') err '$TERM not set' ;;
+ *screen*) set_screen ;;
+ *linux*) setfont ter-132n && new_screen ;;
+ *256*) terminal_emulator || new_screen ;;
+ *) err "no action for \$TERM: $TERM"
+esac
diff --git a/.local/bin/desktop/beautify b/.local/bin/desktop/beautify
new file mode 100755
index 0000000..e535129
--- /dev/null
+++ b/.local/bin/desktop/beautify
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+## properties of script
+
+## set home screen and lock screen wallpaper
+HOMEWALL="${XDG_DATA_HOME:-$HOME/.local/share}/wallpapers/artix-wampire.png"
+LOCKWALL="${XDG_DATA_HOME:-$HOME/.local/share}/wallpapers/artix-wampire.png"
+
+## choose random wallpaper from a directory
+# WALLPAPERS="$HOME/.local/share/wallpapers"
+## requires 'setbg' script found in lukesmithxyz github repo
+setbg_link="https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/setbg"
+## path to download script files like setbg
+BIN="$HOME/.local/bin"
+
+# Location to put lock screen wallpaper for lock program
+LOCKWALL_LOC="/tmp/lockWall"
+
+## list of programs to be installed/uninstalled
+PROGRAMS="eza dust conky picom xwallpaper cxxmatrix"
+## some additional programs that I think are essential are installed below
+## these will be not removed during uninstall
+
+
+help() { echo "beautify - beautify you desktop environment
+
+USAGE:
+ beautify [OPTION]...
+
+OPTIONS:
+ -h show this help message
+
+ -i install programs for beautification
+ -u uninstall beautification programs
+ -x clear beautifications
+
+ The above group of options are conflicting.
+ Passing any one of them will disable the others.
+
+This is very much a personal script and is meant to be configured directly.
+I have only made it work with arch linux and the pacman package manager."; }
+
+err() { printf 'beautify: %s\n' "$@" >&2; exit 1; }
+while getopts 'iuxh' o; do case "$o" in
+ i) opflag=0 ;;
+ u) opflag=1 ;;
+ x) opflag=2 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+case "$opflag" in
+ 0)
+ PROGRAMS="$PROGRAMS neovim tmux dunst highlight starship"
+ sudo pacman -Syu --noconfirm
+ for pkg in $PROGRAMS; do
+ if ! pacman -Q "$pkg" >/dev/null; then
+ yay -S --noconfirm "$pkg"
+ fi
+ done
+
+ mkdir -pv ~/.local/bin
+ wget -c "$setbg_link" -o "${BIN}/setbg" && chmod +x "${BIN}/setbg"
+ ;;
+
+ 1)
+ for pkg in $PROGRAMS; do
+ if pacman -Q "$pkgs" >/dev/null; then
+ sudo pacman -Rns --noconfirm "$pkg"
+ fi
+ done
+ rm -f "$setbg"
+ ;;
+
+ 2)
+ i3-msg 'gaps inner all set 0'
+ xwallpaper --clear
+ rm -f "$LOCKWALL_LOC"
+ killall -q -o 1s conky picom beautify
+ ;;
+esac
+
+[ -n "$opflag" ] && exit
+
+if [ "${LOCKWALL%.png}" = "$LOCKWALL" ]; then
+ temp="/tmp/$(basename "${LOCKWALL%.*}.png")"
+ convert "$LOCKWALL" "$temp"
+ cp -f "$temp" "$LOCKWALL_LOC"
+ rm -f "$temp"
+else
+ cp -f "$LOCKWALL" "$LOCKWALL_LOC"
+fi
+
+i3-msg 'gaps inner all set 10'
+xwallpaper --zoom "$HOMEWALL"
+pidof -q conky || conky
+pidof -q picom || picom -b
+
+if [ -e "$WALLPAPERS" ]; then
+ while sleep 1m; do setbg "$WALLPAPERS"; done
+fi
diff --git a/.local/bin/desktop/brightness b/.local/bin/desktop/brightness
new file mode 100755
index 0000000..11733f4
--- /dev/null
+++ b/.local/bin/desktop/brightness
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+help() { echo "brightness - change screen brightness
+USAGE: brightness <up|down>"; }
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+
+brightness="$(brightnessctl --machine-readable | cut -d, -f4 | tr -d %)"
+step="$(( brightness / 10 + 1))"
+
+case "$1" in
+ up) brightnessctl --quiet set +${step}% ;;
+ down) brightnessctl --quiet set ${step}%- ;;
+ *) help >&2; exit 1 ;;
+esac
+
+brightness="$(brightnessctl --machine-readable | cut -d, -f4)"
+
+if [ -n "$TMUX" ]; then
+ tmux display "Brightness: $brightness"
+ exit
+fi
+
+notify() { [ -n "$DISPLAY" ] && notify-send -r 45234 "$1" "$2"; }
+case "${brightness%\%}" in
+ [0-9]) notify "💡 Brightness: $brightness" ;;
+ [1-7][0-9]) notify "🔅 Brightness: $brightness" ;;
+ [89][0-9]) notify "🔆 Brightness: $brightness" ;;
+ 100) notify "🔆 MAX Brightness: $brightness" ;;
+ *) notify "brightness" "can't determine brightness"
+esac
+exit 0
diff --git a/.local/bin/desktop/detect-keys b/.local/bin/desktop/detect-keys
new file mode 100755
index 0000000..da00dad
--- /dev/null
+++ b/.local/bin/desktop/detect-keys
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+xev | awk -F'[ )]+' '/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", $5, $8 }'
diff --git a/.local/bin/desktop/dmenu-syncthing-devices b/.local/bin/desktop/dmenu-syncthing-devices
new file mode 100755
index 0000000..bb93f6d
--- /dev/null
+++ b/.local/bin/desktop/dmenu-syncthing-devices
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+pidof -q syncthing || {
+ echo "ERROR: Syncthing is not running" >&2
+ exit 2
+}
+
+get_devices() {
+ for device_id in $(syncthing cli config devices list); do
+ printf '%-10s %s\n' \
+ "$(syncthing cli config devices "$device_id" name get)" \
+ "$device_id"
+ done | nl -w1 -s'. '
+}
+
+device="$(get_devices | dmenu -l 10 -p "Syncthing devices")"
+device_id="${device##* }"
+[ -z "$device_id" ] && exit 1
+
+if [ -n "$1" ]; then
+ xdotool type "$device_id"
+else
+ printf '%s\n' "$device_id" | xclip -selection clipboard
+ notify-send "📋 Copied to clipboard" "$device_id"
+fi
diff --git a/.local/bin/desktop/dmenu-unicode b/.local/bin/desktop/dmenu-unicode
new file mode 100755
index 0000000..16e1cfc
--- /dev/null
+++ b/.local/bin/desktop/dmenu-unicode
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+chosen=$(cat ~/.local/share/chars/* | dmenu -i -l 25 -fn :size=20)
+
+[ -z "$chosen" ] && exit
+
+if [ -n "$1" ]; then
+ printf "%s" "${chosen#* }" | cut -d\; -f1 | tr -d '\n' | xclip -selection clipboard
+else
+ printf "%s" "${chosen%% *}" | xclip -selection clipboard
+fi
diff --git a/.local/bin/desktop/dmenu-zeal b/.local/bin/desktop/dmenu-zeal
new file mode 100755
index 0000000..608be89
--- /dev/null
+++ b/.local/bin/desktop/dmenu-zeal
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+cd ~/.local/share/Zeal/Zeal || exit
+
+selection="$(echo "Shell
+C/C++
+Java
+Python
+$(find . -maxdepth 1 -type d ! -name 'docsets' |
+ tail +2 | cut -c3- | sed 's/^/ds:/')
+" | dmenu -i -p "Select docset group")"
+
+case "$selection" in
+ Shell) key="bash,zsh,linux" ;;
+ C/C++) key="c,cpp,linux" ;;
+ Java) key="java,javaspec" ;;
+ Python) key="python,numpy,matplotlib" ;;
+ ds:*)
+ ln -sfT "${selection#ds:}" docsets
+ killall -q zeal; zeal
+ exit
+ ;;
+ *) exit 2 ;;
+esac
+
+query="$(dmenu -p "Enter query")"
+zeal "$key:$query"
diff --git a/.local/bin/desktop/edit-graphical-buffer b/.local/bin/desktop/edit-graphical-buffer
new file mode 100755
index 0000000..10eac8f
--- /dev/null
+++ b/.local/bin/desktop/edit-graphical-buffer
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+sleep 0.5
+xdotool key --clearmodifiers ctrl+a ctrl+c
+content="$(xclip -o -sel clipboard)"
+
+tempfile=/tmp/scratch-buffer/$$.txt
+mkdir -pv /tmp/scratch-buffer
+echo "$content" | tee "$tempfile" > "$tempfile.bak"
+${TERMINAL:-xdg-terminal-exec} -c dropdown_buffer -e nvim "$tempfile"
+
+diff "$tempfile" "$tempfile.bak" >/dev/null || {
+ xclip -sel clipboard < "$tempfile"
+ xdotool key --clearmodifiers ctrl+a ctrl+v
+}
+
+rm -f "$tempfile" "$tempfile.bak"
diff --git a/.local/bin/desktop/i3exit b/.local/bin/desktop/i3exit
new file mode 100755
index 0000000..0be387c
--- /dev/null
+++ b/.local/bin/desktop/i3exit
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# with openrc use loginctl
+[ "$(cat /proc/1/comm)" = "systemd" ] && logind=systemctl || logind=loginctl
+
+command="$1"
+system_control() {
+ if [ "$(loginctl show-session --property=NCurrentSessions --value)" -gt 2 ]; then
+ notify-send --replace-id=4252 \
+ "i3exit" "Multiple users are logged in\nCant't $command"
+ exit
+ fi
+ eval "$@"
+}
+
+lockWall="$HOME/.local/share/lockWall"
+lock_desktop() {
+ [ -f "$lockWall" ] &&
+ i3lock --tiling --image="$lockWall" ||
+ i3lock --color=001177
+ pkill ssh-agent
+}
+
+case "$command" in
+ lock)
+ lock_desktop
+ xset dpms force off
+ ;;
+ logout)
+ switch-session
+ i3-msg exit
+ ;;
+ switch_user)
+ dm-tool switch-to-greeter
+ ;;
+ suspend)
+ lock_desktop; $logind suspend
+ ;;
+ hibernate)
+ system_control lock_desktop && $logind hibernate
+ ;;
+ reboot)
+ system_control $logind reboot
+ ;;
+ shutdown)
+ system_control $logind poweroff
+ ;;
+ *)
+ echo "== ! i3exit: missing or invalid argument ! =="
+ echo "Try again with: lock | logout | switch_user | suspend | hibernate | reboot | shutdown"
+ exit 2
+esac
+
+exit 0
diff --git a/.local/bin/desktop/i3exit-script b/.local/bin/desktop/i3exit-script
new file mode 100755
index 0000000..b27f0f5
--- /dev/null
+++ b/.local/bin/desktop/i3exit-script
@@ -0,0 +1,18 @@
+#!/bin/bash
+# TODO: copy and configure the i3 script to take parametres
+# possibly make it as syst-power
+
+# snippet for blur effect on lock screen
+
+
+# DEPEDNDENCIES: i3lock imagemagic scrot
+
+PICTURE=/tmp/i3lock.png
+SCREENSHOT="scrot $PICTURE"
+
+BLUR="5x4"
+
+$SCREENSHOT
+convert $PICTURE -blur $BLUR $PICTURE
+i3lock -i $PICTURE
+rm $PICTURE
diff --git a/.local/bin/desktop/librewolf-open b/.local/bin/desktop/librewolf-open
new file mode 100755
index 0000000..4bb2d70
--- /dev/null
+++ b/.local/bin/desktop/librewolf-open
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+window="LibreWolf"
+running() { windows=$(wmctrl -l)
+ test "${windows#*"$window"}" != "$windows"; }
+press() { sleep 0.1; xdotool keyup Super
+ xdotool key --clearmodifiers "$@"; }
+
+if ! running; then
+ notify-send "Starting $window..."
+ start="$(date +%s.%3N)"
+ setsid -f librewolf -P "${FFPROFILE:-default-release}"
+ for _ in $(seq 1000); do sleep 0.1; running && break; done
+ end="$(date +%s.%3N)"
+ time="$(echo "$end - $start" | bc)"
+ notify-send "$window" "Started in ${time}s"
+ started=1
+fi
+
+wmctrl -a "$window" ||
+ { notify-send "ffbrowser" "ERROR: librewolf window not found"; exit 1; }
+[ "$started" = 1 ] || press ctrl+t
+
+query="$*"
+if [ "$query" != "${query#http*://}" ]; then
+ press ctrl+l
+elif [ -e "$query" ]; then
+ query="$(readlink -f "$query")"; press ctrl+l
+else
+ # workaround for ctrl+k not working at initial startup
+ [ "$started" = 1 ] && sleep 0.5
+ press ctrl+k
+fi
+
+if [ -n "$query" ]; then
+ xdotool type "$query"
+ press Return
+fi
+
diff --git a/.local/bin/desktop/mlock b/.local/bin/desktop/mlock
new file mode 100755
index 0000000..67da8a3
--- /dev/null
+++ b/.local/bin/desktop/mlock
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+command -v xtrlock || exit
+
+[ "$(xrandr --current | grep -c "\S* connected \S\+.* (")" -gt 1 ] && {
+ xtrlock -b -f
+ xset dpms force off
+ exit
+}
+
+TERMINAL="alacritty -t matrixlock"
+if command -v cxxmatrix; then
+ $TERMINAL -e cxxmatrix &
+elif command -v cmatrix; then
+ $TERMINAL -e sh -c 'sleep 0.5 && cmatrix' &
+else
+ xtrlock -b -f; exit
+fi
+
+xtrlock -f
+sleep 0.2
+wmctrl -r matrixlock -b add,fullscreen
diff --git a/.local/bin/desktop/remap b/.local/bin/desktop/remap
new file mode 100755
index 0000000..3635464
--- /dev/null
+++ b/.local/bin/desktop/remap
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+# This script cannot run without the X server (GUI)
+# So exit if DISPLAY is not set
+[ -z "$DISPLAY" ] && {
+ notify-send remap "ERROR: DISPLAY not set"
+ exit
+}
+
+timeout="${KEY_RELEASE_TIMEOUT:-500}"
+
+help() { echo "remap - remap modifier keys for easy access
+
+USAGE:
+ remap [OPTION]...
+
+OPTIONS:
+ -x reset keys
+ -t toggle (remap/reset)
+ -s show remap status
+ -i show info of all key remaps
+ -h show this help message"; }
+
+key_info() { echo "
+ +-----------------+-----------------------------------+
+ | Before | After |
+ +-----------------+-----------------+-----------------+
+ | Key | On Hold | On Tap |
+ +-----------------+-----------------+-----------------+
+ | Tab | Super | Tab |
+ | Caps Lock | Ctrl | Esc |
+ | Space | Shift | Space |
+ | Left Ctrl | Ctrl | Caps Lock |
+ | Escape | Tab | Tab |
+ +-----------------+-----------------+-----------------+
+
+Note:
+ By default, 'On Tap' will timeout at 500 miliseconds. In other words,
+ if you release a key after timeout, the key will not be generated.
+ You can increase it's value by setting the \$KEY_RELEASE_TIMEOUT environment
+ variable. This is useful in case you don't have a fast typing speed.
+
+If you want to change more keys or want a different configuration, you
+can edit the remap_keys() function inside this script.
+ "; }
+
+while getopts 'rxtsih' o; do case "$o" in
+ x) action=x ;;
+ t) action=t ;;
+ s) action=s ;;
+ i) key_info >&2; exit ;;
+ h) help >&2; exit ;;
+ *) printf "remap: invalid argument -- '%s'\n" "$OPTARG" ;;
+esac; done
+
+status_file="/tmp/.remap.lock"
+keymap_file="/tmp/.xmodmap.defaults"
+[ -f "$keymap_file" ] || xmodmap -pke > "$keymap_file"
+
+msg() {
+ [ "$VERBOSE_REMAP" != 1 ] && return
+ printf "remap: %s\n" "$@"
+ # notify-send "remap" "$*"
+}
+
+remap_keys() {
+ msg "remapping keys..."
+ # Fast key repeats
+ xset r rate 300 50
+
+ # New key behaviour on Hold
+ # lines after ! are comments
+ xmodmap - <<-EOF
+ ! Hold Caps_Lock -> Control_R
+ remove lock = Caps_Lock
+ remove Control = Control_R
+ ! keysym Control_R = Caps_Lock
+ keysym Caps_Lock = Control_R
+ ! add lock = Caps_Lock
+ add Control = Control_R
+ keycode any = Caps_Lock
+
+ ! Hold space -> Shift_R
+ remove shift = Shift_R
+ keycode 65 = Shift_R
+ add shift = Shift_R
+ keycode any = space
+
+ ! Hold Tab -> Super_L
+ ! ! Escape -> Tab
+ remove mod4 = Super_L
+ keycode 23 = Super_L
+ keycode any = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ ! keycode 133 = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ add mod4 = Super_L
+ ! keycode 230 = Escape
+ ! keycode 9 = Tab ISO_Left_Tab Tab ISO_Left_Tab
+ EOF
+
+ # New key behaviour on Tap
+ killall xcape 2>/dev/null
+ xcape -t "$timeout" -e "Super_L=Tab"
+ xcape -t "$timeout" -e "Control_R=Escape"
+ xcape -t "$timeout" -e "Shift_L=Caps_Lock"
+ xcape -t "$timeout" -e "Shift_R=space"
+ date > "$status_file"
+ xset led 3
+ msg "keys remapped"
+}
+
+
+reset_keys() {
+ msg "resetting keys..."
+ xset r rate
+ killall xcape 2>/dev/null
+ setxkbmap -layout us
+ xmodmap "$keymap_file"
+
+ [ -f "$status_file" ] && rm "$status_file"
+ xset -led 3
+ msg "keys reset"
+}
+
+toggle_remap() {
+ if [ -f "$status_file" ]; then
+ reset_keys
+ else
+ remap_keys
+ fi
+}
+
+remap_status() {
+ if [ -f "$status_file" ]; then
+ printf "Keys are remapped since "
+ cat "$status_file"
+ else
+ echo "Keys are NOT remapped"
+ fi
+}
+
+case "$action" in
+ s) remap_status ;;
+ x) reset_keys ;;
+ t) toggle_remap ;;
+ *) remap_keys ;;
+esac
diff --git a/.local/bin/desktop/remapd b/.local/bin/desktop/remapd
new file mode 100755
index 0000000..851d7d2
--- /dev/null
+++ b/.local/bin/desktop/remapd
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+while :; do
+ remap
+ grep -qP -m1 '[^un]bind.+\/[^:]+\(usb\)' <(udevadm monitor -u -t seat -s input -s usb)
+done
diff --git a/.local/bin/desktop/setdp b/.local/bin/desktop/setdp
new file mode 100755
index 0000000..48c6a7a
--- /dev/null
+++ b/.local/bin/desktop/setdp
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+displays="$(xrandr | grep "^\S* connected" | cut -d\ -f1)"
+display_count="$(echo "$displays" | wc -l)"
+
+[ "$display_count" -gt 2 ] &&
+ { echo "Too many displays to configure" >&2; exit 1; }
+
+set --
+
+
+if [ "$display_count" = 2 ]; then
+
+ for display in $displays; do
+ case "$display" in
+ eDP*) export PRIMARY="$display"; set -- "$@" --output "$display" --mode 1920x1080 --primary --pos 0x270 ;;
+ HDMI*) set -- "$@" --output "$display" --mode 1920x1080 --pos 1920x0 --scale "1.25x1.25" ;;
+ esac
+ done
+
+else
+
+ for display in $displays; do
+ case "$display" in
+ eDP*) set -- "$@" --output "$display" --primary --mode 1920x1080 --scale "1.1x1.1" ;;
+ HDMI*) set -- "$@" --output "$display" --mode 1366x768 --scale "1.25x1.25" ;;
+ LVDS*) set -- "$@" --output "$display" --primary ;;
+ DP*) set -- "$@" --output "$display" --primary --scale "1.1x1.1" ;;
+ esac
+ done
+
+fi
+
+
+eval "xrandr --auto $*"
+
diff --git a/.local/bin/desktop/show-i3-keybindings b/.local/bin/desktop/show-i3-keybindings
new file mode 100755
index 0000000..45d0626
--- /dev/null
+++ b/.local/bin/desktop/show-i3-keybindings
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ -n "$TERM" ]; then
+ grep '^bindsym' ~/.config/i3/config | sort |
+ sed 's/^bindsym \(\S*\)\s\+\(.*\)$/\1|\2/; s/\$super+/  /; s/Shift+/וּ /; s/$alt+/Alt /; s/Ctrl+/Ctrl /' |
+ column --table --separator='|' | less -r
+else
+ grep '^bindsym' ~/.config/i3/config | sort |
+ sed 's/^bindsym \(\S*\)\s\+\(.*\)$/\1|\2/; s/\$super+/  /; s/Shift+/Shift /; s/$alt+/Alt /; s/Ctrl+/Ctrl /' |
+ column --table --separator='|' | yad --text-info
+fi
diff --git a/.local/bin/desktop/toggle-xeyes b/.local/bin/desktop/toggle-xeyes
new file mode 100755
index 0000000..af5c590
--- /dev/null
+++ b/.local/bin/desktop/toggle-xeyes
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if pidof -q xeyes; then
+ killall xeyes
+else
+ setsid -f xeyes
+fi
diff --git a/.local/bin/desktop/torbrowser b/.local/bin/desktop/torbrowser
new file mode 100755
index 0000000..27e365b
--- /dev/null
+++ b/.local/bin/desktop/torbrowser
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+help() { echo "torbrowser - open or search in tor browser
+USAGE: torbrowser <open|search> [query]"; }
+
+cmd="$1"
+case "$cmd" in
+ open) extra_cmds='' ;;
+ search) extra_cmds='press ctrl+k' ;;
+ *) help >&2; exit 1 ;;
+esac
+
+query="$2"
+window="Tor Browser"
+windows=$(wmctrl -l)
+if [ "${windows##*"$window"}" = "$windows" ]; then
+ # query="$(dmenu -p "search in tor browser")" || exit
+ torbrowser-launcher && sleep 3
+fi
+
+press() {
+ xdotool keyup ctrl shift alt super meta BackSpace Tab Escape Return
+ xdotool key "$1"
+}
+
+wmctrl -a "$window"
+press ctrl+t
+$extra_cmds
+xdotool type "$query"
+press Return
diff --git a/.local/bin/desktop/volctl b/.local/bin/desktop/volctl
new file mode 100755
index 0000000..7d0edb9
--- /dev/null
+++ b/.local/bin/desktop/volctl
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+help() { echo "volctl - change system volume
+USAGE: volctl <toggle|up|down>"; }
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+
+case "$1" in
+ toggle) wpctl set-mute @DEFAULT_SINK@ toggle ;;
+ up) wpctl set-volume @DEFAULT_SINK@ 5%+ ;;
+ down) wpctl set-volume @DEFAULT_SINK@ 5%- ;;
+ *) help >&2; exit 1 ;;
+esac
+
+vol="$(wpctl get-volume @DEFAULT_SINK@ | tr -d .)"
+vol="${vol#Volume: }"
+
+notify() {
+ if [ -n "$DISPLAY" ]; then
+ notify-send -t 3000 -r 93475 "$1"
+ else
+ printf 'volume : '
+ wpctl get-volume @DEFAULT_SINK@
+ fi
+}
+
+if [ "$vol" != "${vol% \[MUTED\]}" ]; then
+ vol="${vol% \[MUTED\]}"
+ muted=1
+else
+ muted=0
+fi
+
+vol="$(printf '%.0f' "$vol")"
+
+msg=""
+if [ "$vol" -gt "100" ]; then icon="📢"; msg=" Boosted"
+elif [ "$vol" = "100" ]; then icon="🔊"; msg=" Maxed"
+elif [ "$vol" -gt "70" ]; then icon="🔊"
+elif [ "$vol" -gt "30" ]; then icon="🔉"
+elif [ "$vol" -gt "0" ]; then icon="🔈"
+else icon="🔇"
+fi
+
+if [ "$muted" -eq 1 ]; then
+ notify "🔇 Volume Muted ($vol%)"
+else
+ notify "$icon Volume$msg: $vol%"
+fi
+
diff --git a/.local/bin/development/dev b/.local/bin/development/dev
new file mode 100755
index 0000000..76f1772
--- /dev/null
+++ b/.local/bin/development/dev
@@ -0,0 +1,179 @@
+#!/bin/sh
+
+err() { [ "$DEV_SUPRESS_ERRORS" = 1 ] ||
+ printf "dev: %s\n" "$@" >&2; exit 5; }
+
+[ "$#" -lt 2 ] && { err "dev - execute action based on file
+USAGE: dev <ACTION> <FILE> [ARGS...]"; }
+
+action="$1"
+file="$2"
+basename="${file##*/}"
+shift 2
+
+[ -e "$file" ] || err "$file: No such file or directory"
+
+# auxilary functions
+findweb() { find "$@" -or -name '*.html'; }
+
+
+
+### #################################################################
+### BEGIN TASKS
+### #################################################################
+
+sh_lint() { shellcheck -x "$file"; }
+sh_run() { $(sed -n '1s|^#!/.*/\(.*\)|\1|p' "$file") "$file" "$@"; }
+zsh_run() { zsh "$file" "$@"; }
+awk_run() { awk -f "$file" "$@"; }
+pl_run() { perl "$file" "$@"; }
+
+md_run() { glow --pager --style dark "$file"; }
+md_test() { pandoc -t pdf "$file" | zathura -; }
+tex_compile() { pdflatex -output-directory="$(dirname "$file")" "$file"; }
+tex_clean() { find "$(dirname "${1}")" -regex \
+ '.*\(_minted.*\|.*\.\(4tc\|xref\|tmp\|pyc\|pyg\|pyo\|fls\|vrb\|fdb_latexmk\|bak\|swp\|aux\|log\|synctex\(busy\)\|lof\|lot\|maf\|idx\|mtc\|mtc0\|nav\|out\|snm\|toc\|bcf\|run\.xml\|synctex\.gz\|blg\|bbl\)\)' -delete; }
+html_format() { tidy -q "$file" 2>/dev/null; }
+html_lint() { tidy -q "$file" >/dev/null; }
+html_run() { w3m "$file"; }
+js_test() { node "$file"; }
+json_format() { jq . "$file"; }
+php_run() { php "$file" "$@"; }
+
+c_compile() { make "${file%.c}"; }
+c_run() { "$(realpath "${file%.c}")" "$@"; }
+c_clean() { rm -v "${file%.c}"; }
+
+go_format() { gofmt "$file"; }
+go_lint() { gofmt -d "$file"; }
+go_compile() { go build "$file"; }
+go_run() { "$(realpath "${file%.go}")" "$@"; }
+go_test() { go run "$file" "$@"; }
+go_serve() { findweb . -name '*.go' | entr -r sh -c "printf '\n\n$ go run *.go\n'; go run *.go"; }
+
+c_test() {
+ out="${file%.c}"
+ # ARGS="$(sed -nE -e 's|.*#include\s*<(.*)>|-l\1|gp' "$file" |
+ # paste -d' ' -s)"
+ # echo "$ clang -o $out $file $ARGS"
+ # clang -o "$out" "$file" $ARGS && "$out" "$@"
+ make "$out" && echo && "$(realpath "$out")" "$@"
+}
+
+cpp_test() {
+ out="$(realpath "${file%.cpp}")"
+ if [ -f GNUmakefile ] || [ -f makefile ] || [ -f Makefile ]; then
+ make && "${out%/*}/main" "$@"
+ else
+ g++ -o "$out" "$file" && "$out" "$@"
+ fi
+}
+
+ino_test() {
+ [ -t 1 ] || set -- --no-color
+ if [ -c /dev/ttyACM0 ]; then
+ arduino-cli compile --fqbn arduino:avr:uno "$file" "$@"
+ arduino-cli upload --fqbn arduino:avr:uno --port /dev/ttyACM0 "$file" "$@"
+ if [ -t 1 ]; then
+ picocom /dev/ttyACM0
+ else
+ stty -F /dev/ttyACM0 raw 9600
+ cat /dev/ttyACM0
+ fi
+ else
+ arduino-cli compile --fqbn arduino:avr:uno --output-dir . "$file" "$@"
+ rm -- *.eep *.elf *.bin *.with_bootloader.hex
+ fi
+}
+
+java_test() {
+ if [ -f build.xml ]; then
+ ant
+ build="$(find . -name 'classes' -or -name 'build' | tail -1)"
+ class="$({ cd "$build" &&
+ find . -name "$(basename "$file" .java).class"; } |
+ tail -1 | cut -c 3- | sed 's|.class||g' | tr '/' '.')"
+ else
+ mkdir -pv build
+ build="$(dirname "$file")/build"
+ class="$(basename "$file" .java)"
+ javac -d "$build" "$file"
+ fi
+ java -cp "$build:lib/*" "$class"
+}
+
+kt_test() {
+ out="${file%.*}.jar"
+ bash /opt/android-studio/plugins/Kotlin/kotlinc/bin/kotlinc "$file" -include-runtime -d "$out"
+ java -jar "$out"
+ rm "$out"
+}
+
+py_serve() { findweb . -name '*.py' | entr -r python "$file"; }
+# py_lint() {
+# [ -t 1 ] && printf '\033[33m'
+# pycodestyle "$file" >&2
+# [ -t 1 ] && printf '\033[0;39m'
+# }
+
+py_run() {
+ python "$file" "$@"
+ # if [ -x "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" ]; then
+ # "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" "$file" "$@"
+ # else
+ # python "$file" "$@"
+ # fi
+}
+
+### #################################################################
+### END TASKS
+### #################################################################
+
+
+
+filetype=$(file --brief --mime-type "$file")
+case $filetype in
+ text/x-c) filetype_ext="c" ;;
+ text/x-script.python) filetype_ext="py" ;;
+ text/x-shellscript) filetype_ext="sh" ;;
+ text/html) filetype_ext="html" ;;
+ application/javascript) filetype_ext="js" ;;
+ text/x-php) filetype_ext="php" ;;
+ text/x-awk) filetype_ext="awk" ;;
+esac
+
+if [ "${basename#*.}" != "${basename}" ]; then
+ file_ext="${basename##*.}"
+else
+ [ -z "$filetype_ext" ] && err "no file type association for $filetype"
+ NO_BASENAME=1
+fi
+
+execute_task() {
+ [ "$NO_BASENAME" != 1 ] && {
+ file_task="${file_ext}_${action}"
+ [ "${tasks#*"[$file_task]"}" != "$tasks" ] &&
+ { $file_task; local ret=$?; local tasked=1; }
+ }
+ [ "$tasked" != 1 ] && {
+ filetype_task="${filetype_ext}_${action}"
+ [ "${tasks#*"[$filetype_task]"}" != "$tasks" ] &&
+ { $filetype_task; local ret=$?; local tasked=1; }
+ }
+ [ "$tasked" != 1 ] && return 1
+ [ "$ret" != 0 ] && printf "\nshell returned %s\n" "$ret" >&2
+ return 0
+}
+
+tasks="$(sed -n "/^### BEGIN TASKS$/,/^### END TASKS$/ s/\(^[a-zA-Z0-9_]\+\)().*/[\1]/p" "$0")"
+
+if [ "$action" = test ]; then
+ execute_task && exit
+ for action in lint compile run; do
+ execute_task && tested=1
+ done
+ [ "$tested" != 1 ] && err "no tests for .${file_ext:-$filetype_ext} file"
+ exit 0
+fi
+
+execute_task || err "no $action action for .${file_ext:-$filetype_ext} file"
diff --git a/.local/bin/development/getcomproot b/.local/bin/development/getcomproot
new file mode 100755
index 0000000..16e946a
--- /dev/null
+++ b/.local/bin/development/getcomproot
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# author: Luke Smith
+#
+# A helper script for LaTeX/groff files used by `compiler` and `opout`.
+# The user can add the root file of a larger project as a comment as below:
+# % root = mainfile.tex
+# And the compiler script will run on that instead of the opened file.
+
+texroot="$(grep -i "^.\+\s*root\s*=\s*\S\+" "$1")"
+texroot="${texroot##*=}"
+texroot="${texroot//[\"\' ]}"
+
+[ -f "$texroot" ] && readlink -f "$texroot" || exit 1
diff --git a/.local/bin/development/gitpush b/.local/bin/development/gitpush
new file mode 100755
index 0000000..97aa43b
--- /dev/null
+++ b/.local/bin/development/gitpush
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$(git config --get remote.origin.url)" in
+ *csstudent41*) sshadd ~/.ssh/github.com_id_ed25519 ;;
+ *labstudent41*) sshadd ~/.ssh/labstudent41_id_ed25519 ;;
+esac
+
+git add --all
+git commit # --allow-empty-message
+git push -u origin
diff --git a/.local/bin/development/gitw b/.local/bin/development/gitw
new file mode 100755
index 0000000..881c81c
--- /dev/null
+++ b/.local/bin/development/gitw
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# git-web: open the url of current git repositary in a web browser.
+# USAGE: gitw [remote]
+# 'remote' is set to origin if not provided.
+
+err() { printf "gitw: %s\n" "$@" >&2; exit 1; }
+
+git rev-parse --is-inside-work-tree >/dev/null || exit
+
+remote="${1:-origin}"
+url="$(git remote get-url "$remote" |
+ sed "s|^git@\(\S\+\):|https://\1/|")" || exit
+
+[ -z "$url" ] || [ "$remote" = "$url" ] &&
+ err "remote has no url: $remote"
+
+xdg-open "$url"
diff --git a/.local/bin/development/ipy b/.local/bin/development/ipy
new file mode 100755
index 0000000..1f39550
--- /dev/null
+++ b/.local/bin/development/ipy
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+unset PYTHONSTARTUP
+"${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/ipython" "$@"
diff --git a/.local/bin/development/ipytest b/.local/bin/development/ipytest
new file mode 100755
index 0000000..17a5a55
--- /dev/null
+++ b/.local/bin/development/ipytest
@@ -0,0 +1,23 @@
+#!/bin/sh
+# create a 'dev' firefox profile and use it in selenium
+
+[ -z "$FF_DEV_PROFILE" ] && [ -d ~/.librewolf ] &&
+ FF_DEV_PROFILE="$(find ~/.librewolf/ -maxdepth 1 -type d -name '????????.dev')"
+
+[ -z "$FF_DEV_PROFILE" ] && [ -d ~/.librewolf ] &&
+ FF_DEV_PROFILE="$(find ~/.mozilla/ -maxdepth 1 -type d -name '????????.dev')"
+
+ipy -i -c "
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+
+options = webdriver.FirefoxOptions()
+options.binary_location = '/usr/bin/librewolf'
+options.profile = webdriver.FirefoxProfile(\"$FF_DEV_PROFILE\")
+
+d = webdriver.Firefox(options=options)
+d.get(\"${1:-http://127.0.0.1}\")
+
+import atexit
+atexit.register(d.quit)
+"
diff --git a/.local/bin/development/nx b/.local/bin/development/nx
new file mode 100755
index 0000000..862be99
--- /dev/null
+++ b/.local/bin/development/nx
@@ -0,0 +1,148 @@
+#!/bin/sh
+
+help() {
+ echo "nx - create new script"
+ echo "USAGE: nx <script_name>"
+}
+
+err() { printf '%s: %s\n' "$0" "$@" >&2; exit 1; }
+warn() {
+ printf '%s: %s [Y/n] ' "$0" "$@" >&2; read -r arg
+ case "$arg" in ''|y|Y) ;; *) exit ;; esac
+}
+
+while getopts 'h' o; do case "$o" in
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help && exit 1
+[ "$#" -gt 1 ] && err "too many arguments. Only one expected"
+
+
+new_script() {
+ cat << EOF > "$1"
+#!/bin/sh
+
+help() { echo "$1 -
+
+USAGE:
+ $1 [OPTION]...
+
+OPTIONS:
+ -h show this help message"; }
+
+err() { printf '$1: %s\n' "\$@" >&2; exit 1; }
+while getopts 'h' o; do case "\$o" in
+ h) help; exit ;;
+ *) err "invalid option -- '\$OPTARG'" ;;
+esac done
+shift \$((OPTIND - 1))
+
+[ "\$#" -lt 1 ] && help >&2 && exit 1
+
+EOF
+
+ chmod u+x -- "$1" || exit
+}
+
+
+new_c_file() {
+ cat << EOF > "$1"
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello\n");
+
+ return 0;
+}
+EOF
+}
+
+
+new_cpp_file() {
+ cat << EOF > "$1"
+#include <iostream>
+
+using namespace std;
+
+int main()
+{
+ cout << "Hello" << endl;
+
+ cin.get();
+ return 0;
+}
+EOF
+}
+
+
+new_py_file() {
+ cat << EOF > "$1"
+import timeit
+
+print("Finished in %fs" % timeit.timeit())
+EOF
+}
+
+
+new_java_file() {
+ PATTERN="Scanner"
+ VIMCMDS="normal!2n\n noh"
+ cat << EOF > "$1"
+import java.util.Scanner;
+
+class ${1%.java} {
+ public static void main(String args[]) {
+ Scanner sc = new Scanner(System.in);
+
+ System.out.println("Finished!");
+ sc.close
+ }
+}
+EOF
+}
+
+
+file="$1"
+
+new_file() {
+ case "$file" in
+ *.c) new_c_file "$file" ;;
+ *.cpp) new_cpp_file "$file" ;;
+ *.py) new_py_file "$file" ;;
+ *.java) new_java_file "$file" ;;
+ *) new_script "$file" ;;
+ esac
+}
+
+if [ -f "$file" ]; then
+ [ ! -w "$file" ] && chmod u+rw "$file"
+ if [ -s "$file" ]; then
+ warn "'$file' already exists, edit existing file?" || exit
+ else
+ warn "an empty file '$file' already exists, fill and edit?" &&
+ new_file "$file"
+ fi
+elif [ -e "$file" ]; then
+ err "'$file' already exists and is a non-regular file"
+else
+ new_file "$file"
+fi
+
+ls -lF --color -- "$file"
+
+case "$EDITOR" in
+ '') echo "$0: \$EDITOR variable not set" >&2 && exit 1 ;;
+ vi|*vim*)
+ VIMCONF="$(mktemp)"; export VIMCONF
+ [ -n "$VIOPTS" ] && echo "set $VIOPTS" >> "$VIMCONF"
+ [ -n "$PATTERN" ] && echo "/$PATTERN" >> "$VIMCONF"
+ [ -n "$VIMCMDS" ] && echo "$VIMCMDS" >> "$VIMCONF"
+ $EDITOR -S "$VIMCONF" "$file"
+ rm -f "$VIMCONF"
+ ;;
+ *) $EDITOR "$file" ;;
+esac; exit
diff --git a/.local/bin/development/opout b/.local/bin/development/opout
new file mode 100755
index 0000000..3adc8fd
--- /dev/null
+++ b/.local/bin/development/opout
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+basename="${1%.*}"
+err() { printf "opout: %s\n" "$@" >&2; exit 1; }
+
+case "${*}" in
+ '') err "filename required" ;;
+ *.tex|*.sil|*.m[dse]|*.[rR]md|*.mom|*.[0-9]) target="$(getcomproot "$1" || echo "$1")" ; setsid -f "${OPENER:-xdg-open}" "${target%.*}".pdf >/dev/null 2>&1 ;;
+ *.html) setsid -f xdg-open "$basename".html >/dev/null 2>&1 ;;
+ *.sent) setsid -f sent "$1" >/dev/null 2>&1 ;;
+ *) err "file extension unmatched"
+esac
diff --git a/.local/bin/development/pipsearch b/.local/bin/development/pipsearch
new file mode 100755
index 0000000..0d1d495
--- /dev/null
+++ b/.local/bin/development/pipsearch
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+{ sleep 1 && tmux send-keys /search\ results Enter; } &
+tmux new w3m "http://pypi.org/search?q=$*"
diff --git a/.local/bin/development/py b/.local/bin/development/py
new file mode 100755
index 0000000..af32c95
--- /dev/null
+++ b/.local/bin/development/py
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+"${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" "$@"
+
diff --git a/.local/bin/development/pyh b/.local/bin/development/pyh
new file mode 100755
index 0000000..fdd524a
--- /dev/null
+++ b/.local/bin/development/pyh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# python-help: get help for keywords in python
+
+[ -x "${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python" ] &&
+ alias python="${XDG_DATA_HOME:-$HOME/.local/share}/virtualenvs/main/bin/python"
+
+if [ "$#" -gt 0 ]; then
+ python -c "help('$*')"
+else
+ python -c "help()"
+fi
diff --git a/.local/bin/development/texclear b/.local/bin/development/texclear
new file mode 100755
index 0000000..6ad3c12
--- /dev/null
+++ b/.local/bin/development/texclear
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Clears the build files of a LaTeX/XeLaTeX build.
+# I have vim run this file whenever I exit a .tex file.
+
+[ "${1##*.}" = "tex" ] && {
+ find "$(dirname "${1}")" -regex '.*\(_minted.*\|.*\.\(4tc\|xref\|tmp\|pyc\|pyg\|pyo\|fls\|vrb\|fdb_latexmk\|bak\|swp\|aux\|log\|synctex\(busy\)\|lof\|lot\|maf\|idx\|mtc\|mtc0\|nav\|out\|snm\|toc\|bcf\|run\.xml\|synctex\.gz\|blg\|bbl\)\)' -delete
+} || printf "Provide a .tex file.\n"
+
diff --git a/.local/bin/fcode b/.local/bin/fcode
new file mode 100755
index 0000000..8da7a17
--- /dev/null
+++ b/.local/bin/fcode
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# fzf-unicode: get a list of emojis or unicode charecters using fzf
+# place your charecter files in plain text in ~/.local/share/chars/*
+
+FZF_HIST="$HOME/.local/share/fzf/unicode_history"
+mkdir -pv ~/.local/share/fzf
+
+if [ "$OPENFLAG" = 0 ]; then
+ notify-send fzf-unicode "$*"
+ chosen="$(printf '%s\n' "$@" | cut -d\ -f1 | tr -d '\n')"
+ echo "$chosen" | xclip -selection clipboard
+ notify-send "'$chosen' copied to clipboard."
+ exit
+fi
+
+cut -d ';' -f1 ~/.local/share/chars/* |
+ fzf -m --history="$FZF_HIST" \
+ --header="Copy Emojis to Clipboard" --header-first \
+ --preview 'printf "%s\n" {+} | cut -d\ -f1 | tr -d "\n"' \
+ --preview-window=nohidden,up,1 \
+ --bind 'ctrl-/:change-preview-window(down|up)' \
+ --bind 'enter:execute(echo {q} >> $FZF_HIST; OPENFLAG=0 fzf-unicode {+})'
diff --git a/.local/bin/fdict b/.local/bin/fdict
new file mode 100755
index 0000000..8a4ed61
--- /dev/null
+++ b/.local/bin/fdict
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# fzf-dict: get word definitions using sdcv
+
+mkdir -pv ~/.local/share/fzf
+export SDCV_PAGER="less -R"
+
+if [ "$OPENFLAG" = 0 ]; then
+ sdcv --color \
+ -u 'WordNet® 3.0 (En-En)' \
+ -u 'American Heritage Dictionary 4th Ed. (En-En)' \
+ -u 'Urban Dictionary P1 (En-En)' \
+ -u 'Urban Dictionary P2 (En-En)' \
+ "$@"
+ sdcv -u 'Wikipedia English - Free Encyclopedia' "$@" | w3m -T text/html
+ exit
+fi
+
+grep -v \' "${PREFIX:-/usr}/share/dict/words" | fzf \
+ --history "$HOME/.local/share/fzf/word_history" \
+ --header "Startdict Dictionary" --header-first \
+ --preview='OPENFLAG=0 fzf-words {} | fold -sw "$FZF_PREVIEW_COLUMNS"' \
+ --preview-window='nohidden,75%' --tiebreak=begin --print-query \
+ --bind 'alt-enter:execute(OPENFLAG=0 fzf-words {q})' \
+ --bind 'enter:execute(OPENFLAG=0 fzf-words {})'
diff --git a/.local/bin/fgrp b/.local/bin/fgrp
new file mode 100755
index 0000000..ddf3448
--- /dev/null
+++ b/.local/bin/fgrp
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# fzf-grep: browse through grepped lines using fzf
+
+if [ "$OPENFLAG" = 0 ]; then
+ location="$(echo "$*" | sed 's/^\(.*\):\([0-9]\+\):.*$/\1|\2/')"
+ file="${location%|*}"; line="${location##*|}"
+ case "${OPENWITH:=$EDITOR}" in
+ ''|vi|*vim*) $OPENWITH +"$line" "$file" ;;
+ *) $OPENWITH "$file" ;;
+ esac; exit
+fi
+
+mkdir -pv "${XDG_DATA_HOME:=$HOME/.local/share}/fzf"
+export FZF_HIST="$XDG_DATA_HOME/fzf/grep_history"
+grep -Rnsi --exclude-dir=.git --exclude-dir=node_modules --color=always "$@" |
+ fzf --ansi \
+ --history="$FZF_HIST" \
+ --prompt="grep > " \
+ --preview='preview "$(echo {1} | cut -d: -f1)"' \
+ --preview-window="hidden" \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview' \
+ --bind "ctrl-r:reload(grep -Rns --color=always $*)" \
+ --bind 'enter:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 fgrp {})' \
+ --bind 'alt-e:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${EDITOR:-vi} fgrp {})' \
+ --bind 'alt-o:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${OPENER:-xdg-open} fgrp {})' \
+ --bind 'alt-O:execute(echo {} >> "$FZF_HIST"; OPENFLAG=0 OPENWITH=${FILES:-lf} fgrp {})'
diff --git a/.local/bin/filter b/.local/bin/filter
new file mode 100755
index 0000000..9d3e5e3
--- /dev/null
+++ b/.local/bin/filter
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+help() { echo "filter - filter input based on given expression to evaluate
+
+USAGE:
+ filter [OPTION]... <FILTER_EXPRESSION> [FILES]...
+
+OPTIONS:
+ -i update files with filtered content
+ -h show this help message
+
+FILTER_EXPRESSION is a contains the command string that will be executed to test
+the input line. {} should be used as a placeholder that will be replaced to the
+double-quoted string of the input line. If the command evaluates to true, the
+line is printed to stdout.
+"; }
+
+err() { printf 'filter: %s\n' "$@" >&2; exit 1; }
+while getopts 'ih' o; do case "$o" in
+ i) iflag=1 ;;
+ h) help; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+filter="$1"; shift
+
+evaluate() {
+ while IFS= read -r line; do
+ escaped_line="$(printf "%s\n" "$line" | sed "s|\"|\\\\\\\\\"|")"
+ cmd="$(printf "%s\n" "$filter" | sed "s|{}|\"$escaped_line\"|")"
+ eval "$cmd" && printf "%s\n" "$line"
+ done
+}
+
+if [ "$iflag" = 1 ]; then
+ for file in "$@"; do
+ [ -z "$1" ] && err "option -i requires file argument and none were passed"
+ tmp="$(mktemp "/tmp/$file.tmp-filter.XXXXXX")"
+ evaluate < "$file" > "$tmp"
+ mv "$tmp" "$file"
+ done
+ exit
+fi
+
+if [ -n "$1" ]; then
+ evaluate < "$@"
+else
+ evaluate
+fi
+
diff --git a/.local/bin/fm b/.local/bin/fm
new file mode 100755
index 0000000..2f4fbb8
--- /dev/null
+++ b/.local/bin/fm
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# fzf-man: fuzzy search manual pages
+
+if [ "$OPENFLAG" = 0 ]; then
+ input="$*"; page="${input%%)*}";
+ name="${page%%[ (]*}"; section="${page#*(}"
+ if [ "$name" = "$section" ]; then
+ man "$name"
+ else
+ man "$section" "$name"
+ fi; exit
+fi
+
+mkdir -pv "${XDG_DATA_HOME:=$HOME/.local/share}/fzf"
+export FZF_HIST="${XDG_DATA_HOME:=$HOME/.local/share}/fzf/manual_history"
+
+apropos -l "${@:-.}" | fzf --history="$FZF_HIST" --prompt="man: " \
+ --preview='MANWIDTH=$FZF_PREVIEW_COLUMNS OPENFLAG=0 fm {}' \
+ --preview-window="hidden" --tiebreak="begin" \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview' \
+ --bind 'enter:execute(echo {1} >> "$FZF_HIST"; OPENFLAG=0 fm {})'
diff --git a/.local/bin/fmd b/.local/bin/fmd
new file mode 100755
index 0000000..0139d77
--- /dev/null
+++ b/.local/bin/fmd
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# fzf-media: fuzzy search media files
+# Useful when you want to look through a list of video without having to
+# bother with their individual supplementary files like subtitles.
+
+export PREVIEW="${PREVIEW:-"cat \"\$(dirname {})/.description/\${\$(basename {})%.*}.txt\" 2>/dev/null || preview {}"}"
+
+find "$@" -type f \
+ ! -path '*/.*' \
+ ! -name '*.srt' \
+ ! -name '*.vtt' \
+ ! -name '*.description' \
+ ! -wholename '.description/*' \
+ ! -name '*.info.json' \
+ ! -name '*.live_chat.json' \
+ ! -name '*.yt*' |
+ sort |
+ fzf --multi --reverse \
+ --history="${FZF_HIST:=$HOME/.local/share/fzf/media_history}" \
+ --header="${FZF_HEADER:-Browse Media Files}" --header-first \
+ --preview="$PREVIEW" --preview-window=hidden \
+ --bind 'alt-C:execute( ffbrowser "$(mediainfo --inform="General;%Comment%" {})" )' \
+ --bind 'ctrl-o:execute(append-to-history {q} "$FZF_HIST"; ${OPENER:-xdg-open} {})' \
+ --bind "alt-3:change-preview($PREVIEW)" \
+ --bind 'alt-#:execute($PREVIEW | less)'
diff --git a/.local/bin/fpm b/.local/bin/fpm
new file mode 100755
index 0000000..8da3d35
--- /dev/null
+++ b/.local/bin/fpm
@@ -0,0 +1,148 @@
+#!/bin/sh
+
+help() { echo "fzf-pm - fzf package manager
+
+USAGE:
+ fzf-pkgs [OPTION]... [QUERY]
+
+OPTIONS:
+ -g list global [all] packages
+ -l list local [instllaed] packages (default)
+ -i select and install packages (implies -g)
+ -u select and uninstall packages (implies -l)
+ -v show verbose output
+ -h show this help message
+
+ (for Arch linux only)
+ -a AUR_HELPER specify command for AUR helper
+
+ (special options)
+ -s PACKAGE print package info
+ -p print package manager
+
+ Note: passing global (-g) or local (-l) pkg list will cancel
+ any install (-i) or uninstall (-u) operations started previously.
+
+ENVIRONMENT VARIABLES:
+ AUR_HELPER set an AUR helper command for Arch linux
+
+Following package managers are supported:
+ apt, pkg, pacman and any pacman compatible AUR helper
+
+QUERY is mandatory when using an AUR Helper" ;}
+
+while getopts 's:gliuha:p' o; do case "$o" in
+ s) sflag=0; pkg="$OPTARG" ;;
+ g) operation=""; opmsg=""; list_all=0 ;;
+ l) operation=""; opmsg=""; list_all=1 ;;
+ i) operation="install_pkgs"; opmsg="to Install"; list_all=0 ;;
+ u) operation="uninstall_pkgs"; opmsg="to Uninstall"; list_all=1 ;;
+ h) help; exit ;;
+ a) export AUR_HELPER="$OPTARG" ;;
+ p) pflag=0 ;;
+ *) printf "fzf-pkgs: invalid option -- '%s'" "$OPTARG"; exit 1 ;;
+esac done
+shift $((OPTIND - 1))
+
+if command -v apt-get >> /dev/null; then
+ alias pkg_sort='sed -e "s/ - / => /"'
+
+ if [ "$list_all" = 0 ]; then
+ export pkg_info='apt-cache show'
+ alias list_pkgs='apt-cache search .'
+ alias search_pkg='apt-cache search'
+ else
+ export DPKG_COLOR='always'
+ export pkg_info='dpkg-query --status'
+ format='${Package} - ${Description}\n'
+ alias list_pkgs='dpkg-query --show --showformat "$format"'
+ alias search_pkg='dpkg-query --show --showformat "$format" | grep'
+ fi
+
+ if command -v pkg >> /dev/null; then
+ export PKGMAN="pkg"
+ alias install_pkgs='pkg install'
+ alias uninstall_pkgs='pkg uninstall'
+ else
+ export PKGMAN="apt"
+ alias install_pkgs='sudo apt-get install'
+ alias uninstall_pkgs='sudo apt-get remove'
+ fi
+
+elif command -v pacman >> /dev/null; then
+ alias pkg_sort='sed -e "N;s/\n\s*/ => /"'
+
+ if [ -n "$AUR_HELPER" ]; then
+ export PKGMAN="$AUR_HELPER"
+ if command -v "$PKGMAN" >/dev/null; then
+ alias install_pkgs='$PKGMAN -S'
+ alias uninstall_pkgs='$PKGMAN -Rns'
+ else
+ echo "fzf-pkgs: AUR Helper '$PKGMAN' command not found" >&2 &&
+ exit 1
+ fi
+ else
+ export PKGMAN='pacman'
+ alias install_pkgs='sudo $PKGMAN -S'
+ alias uninstall_pkgs='sudo $PKGMAN -Rns'
+ fi
+
+ if [ "$list_all" = 0 ]; then
+ export pkg_info="$PKGMAN --color=always -Si"
+ alias list_pkgs='$PKGMAN --color=always -Ss'
+ alias search_pkg='$PKGMAN --color=always -Ss'
+ else
+ export pkg_info="$PKGMAN --color=always -Qi"
+ alias list_pkgs='$PKGMAN --color=always -Qs'
+ alias search_pkg='$PKGMAN --color=always -Qs'
+ fi
+
+else
+ echo "fzf-pkgs: package manager not found" >&2
+ exit 1
+fi
+
+if [ "$pflag" = 0 ]; then
+ printf "%s\n" "$PKGMAN"
+ exit
+elif [ "$sflag" = 0 ]; then
+ printf "$ %s '%s'\n" "$pkg_info" "$pkg"
+ $pkg_info $pkg
+ exit
+fi
+
+query="$1"
+if [ -n "$AUR_HELPER" ] && [ -z "$query" ] && [ "$list_all" = 0 ]; then
+ echo "fzf-pkgs: providing QUERY is mandatory when using an AUR Helper"
+ exit 1
+ # printf "query: "; read -r query
+ # [ -z "$query" ] && exit 1
+fi
+
+if [ -n "$query" ]; then
+ prompt="searching '$query' "
+ get_pkgs() { search_pkg "$query"; }
+else
+ get_pkgs() { list_pkgs; }
+fi
+
+[ -z "$FZF_HIST_DIR" ] && export FZF_HIST_DIR="$HOME/.local/share/fzf"
+fzff() {
+ preview='
+ echo "selected packages:";
+ printf "\t%s\n" {+1} | tr " " "\n"
+ echo
+ eval "$pkg_info 2>/dev/null" {1}
+ '
+ fzf --ansi --multi \
+ --history="${FZF_HIST_DIR:-$HOME/.local/share}/package_history" \
+ --header="Select packages $opmsg" --header-first --prompt="$prompt> " \
+ --preview="$preview" --preview-window="hidden" --tiebreak='begin' \
+ --bind 'ctrl-v:toggle-preview,ctrl-space:toggle-preview'
+}
+
+pkgs="$(get_pkgs | pkg_sort | fzff | cut -d' ' -f1 | tr '\n' ' ')"
+[ -n "$pkgs" ] || exit 2
+echo "$pkgs"
+[ -n "$operation" ] && eval $operation $pkgs
+
diff --git a/.local/bin/fsend b/.local/bin/fsend
new file mode 100755
index 0000000..f75739d
--- /dev/null
+++ b/.local/bin/fsend
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+content="${1:-$(xprint | fzf -m --header "Select clipboard lines to send")}" || exit
+host="${2:-$(sed '/^Host \(.*\)/!d; s//\1/' ~/.ssh/config | fzf --header "Send to?")}" || exit
+sshadd "$(find ~/.ssh -name "${host}_id_*" | head -1)"
+[ -z "$NOTIFY" ] && command -V notify-send >/dev/null && NOTIFY=1
+
+notify() {
+ [ "$NOTIFY" = 1 ] && notify-send -r 8529 "$@"
+ printf "%s\n" "$@"
+}
+
+transferto() {
+ notify "Transfering files to $host:$1/" "$content"
+ rsync -PLru --progress "$content" "$host:$1/"
+}
+
+if [ -e "$content" ]; then
+ case "$content" in
+ *.txt|*.pdf) transferto "Documents" ;;
+ *)
+ case "$(file --brief --mime-type "$content")" in
+ text/*) transferto "Documents" ;;
+ image/*) transferto "Pictures" ;;
+ audio/*) transferto "Music" ;;
+ video/*) transferto "Videos" ;;
+ *) transferto "Downloads" ;;
+ esac
+ ;;
+ esac
+
+else
+ case "$content" in
+ http*) notify "Opening link in $host" "$content"
+ ssh "$host" "xdg-open \"$content\"" ;;
+ *) notify "Copying in $host's clipboard" "$content"
+ ssh "$host" "termux-clipboard-set \"$content\"" ;;
+ esac
+fi
+
+if [ $? = 0 ]; then
+ notify "  Done (fzf-send)"
+else
+ notify " ❌ Errors Occured (fzf-send)"
+ printf "\n%s" "Press Enter to continue..."
+ read -r
+fi
diff --git a/.local/bin/fw b/.local/bin/fw
new file mode 100755
index 0000000..ada20e8
--- /dev/null
+++ b/.local/bin/fw
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+export FZF_HIST="$HOME/.local/share/fzf/wiki_history"
+export FZF_HEADER="Search local wiki files"
+export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --delimiter='/' --with-nth=-1"
+fmd \
+ /mnt/storage/Media/Tech/ \
+ /mnt/storage/Library \
+ /usr/share/doc/arch-wiki/html/en \
+ "$@" ! -name '*.css'
diff --git a/.local/bin/help b/.local/bin/help
new file mode 100755
index 0000000..046b1cc
--- /dev/null
+++ b/.local/bin/help
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+help() { echo "help - get help for shell commands or programs
+
+USAGE:
+ help [OPTION...] <QUERY>
+
+OPTIONS:
+ -a show all available help
+ -h show this help message
+ "; }
+
+while getopts 'avh' o; do case "$o" in
+ a) aflag=0;;
+ h) help; exit ;;
+ *) printf "help: invalid option -- '%s'" "$OPTARG" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && help >&2 && exit 2
+
+
+##############################################################
+### H E L P F U N C T I O N S I N O R D E R ###
+##############################################################
+
+man_query() {
+ man -w "$query" >/dev/null 2>&1 || return 2
+ man -a "$query"
+}
+
+info_query() {
+ # if command -v info
+ [ -n "$(info --where "$query")" ] || return 2
+ info --vi-keys --all "$query"
+}
+
+show_script() {
+ file="$(which "$query" 2>/dev/null)" || return 2
+ "${PAGER:-less}" "$file"
+}
+
+cmd_help() {
+ if content="$($query -h 2>/dev/null)"; then
+ printf "$ %s -h" "$query"
+ elif content="$($query --help 2>/dev/null)"; then
+ printf "$ %s --help" "$query"
+ else
+ return 2
+ fi
+ printf '\n%s\n' "$content" | "${PAGER:-less}" -X
+ echo
+}
+
+tldr_query() {
+ content="$(tldr --color=always "$query" 2>/dev/null)" || return 2
+ printf "\n$ tldr '%s'\n%s\n\n" "$query" "$content" | "${PAGER:-less}" -X
+}
+
+pkg_info() {
+ if command -v pacman >/dev/null; then
+ cmd="$ pacman -Si $query"
+ info="$(pacman -Si "$query" 2>/dev/null)" || return 2
+ elif command -v apt >/dev/null; then
+ cmd="$ apt show $query"
+ info="$(apt show "$query" 2>/dev/null)" || return 2
+ elif command -v pkg >/dev/null; then
+ cmd="$ pkg info $query"
+ info="$(pkg info "$query" 2>/dev/null)" || return 2
+ else
+ return
+ fi
+ [ -z "$info" ] && return 2
+ printf "\n%s\n%s\n\n" "$cmd" "$info" | "${PAGER:-less}" -X
+}
+
+##########################################################
+### E N D O F H E L P F U N C T I O N S ###
+##########################################################
+
+
+help_funcs="$(sed -ne "/^### H E L P/,/^### E N D/ s/^\([a-zA-Z0-9_]\+\)\(\).*/\1/p" "$0")"
+main() {
+ if [ "$aflag" = 0 ]; then
+ eval "$help_funcs"
+ else
+ eval "$(echo "$help_funcs" | sed -z 's/\n/||/g' | sed 's/||$//')"
+ fi
+}
+
+query="$*"
+[ -f "$query" ] && { "${PAGER:-less}" "$query"; exit 0; }
+[ -d "$query" ] &&
+ { ls -AlFh --color --group-directories-first -- "$query"; exit 0; }
+
+command -V "$query" 2>/dev/null && { echo; export HELP_FOUND=1; }
+
+main || [ "$HELP_FOUND" = 1 ] ||
+ { echo "No help found for '$query'" >&2; exit 2; }
diff --git a/.local/bin/launch-gtypist b/.local/bin/launch-gtypist
new file mode 100755
index 0000000..c5f452f
--- /dev/null
+++ b/.local/bin/launch-gtypist
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+
+help() {
+ echo "launch-gtypist - launch gtypist in fullscreen
+
+USAGE:
+ launch-gtypist [OPTION]...
+
+OPTIONS:
+ -l LESSON start gtypist lesson
+ -f FILE load lesson from a file
+ -e % max error percentage
+ -v verbose output
+ -h show this help message
+
+LESSON can optionally be followed by the exercise number seprated by a colon.
+Example - Q2:3, which means 3rd execercise of lesson Q2.
+If LESSON is provided through the command line along with a file with -f
+option then the file will ignored"
+}
+
+
+while getopts 'l:f:e:vh' o; do case "$o" in
+ l) use_file=1; current="$OPTARG" ;;
+ f) use_file=0; file="$OPTARG" ;;
+ e) export GTYPIST_OPTS="$GTYPIST_OPTS --max-error=$OPTARG" ;;
+ v) vflag=0 ;;
+ h) help; exit ;;
+ *) echo "launch-gtypist: invalid option -- '${OPTARG}'"
+ echo 'Try `launch-gtypist -h` for more information.' >&2; exit 1 ;;
+esac done
+shift $((OPTIND - 1))
+
+msg() { [ "$vflag" = 0 ] && printf ':: %s\n' "$@" >&2; true; }
+notify() {
+ [ -n "$DISPLAY" ] && notify-send 'launch-gtypist' "$@"
+ printf '%s\n' "$@"
+}
+
+if [ "$use_file" = 0 ]; then
+ msg "Getting lesson from file: $file"
+ current="$(sed -En 's/^gtypist lesson\s*-\s*(.*)$/\1/p' "$file")" ||
+ exit 1
+ [ -z "$current" ] &&
+ printf 'launch-gtypist: current gtypist lesson not found in:\n\t%s\n' \
+ "$file" && exit 1
+fi
+
+[ -n "$1" ] && current="$1" && shift
+[ "${current#*:}" != "$current" ] && lesson="${current%:*}" &&
+ exercise="${current##*:}" || lesson="$current"
+[ -n "$lesson" ] && {
+ msg "Gtypist lesson name: $lesson"
+ export GTYPIST_OPTS="$GTYPIST_OPTS --start-label=$lesson"
+}
+
+tmuxx() { [ -z "$TMUX" ] && return 1; tmux "$@"; }
+
+
+shift_exercise() {
+ msg "Shifting to exercise $exercise"
+ sleep 1
+
+ keys() {
+ if [ -n "$TMUX" ]; then
+ for key in "$@"; do
+ tmux send-keys -t gtypist "$key";
+ done
+ else
+ xdotool key --clearmodifiers --delay 100 "$@"
+ fi
+ }
+
+ for i in $(seq "$((exercise-1))"); do
+ if [ "$i" -gt 1 ]; then
+ keys Escape n
+ else
+ keys space space space space space Escape Escape n
+ fi
+ done
+}
+
+
+msg "Switcing to default keymap"
+# kmonad-manage stop
+remap -x
+
+msg "Waiting for terminal columns to get more than 100..."
+while [ "$(tput cols)" -lt 100 ]; do sleep 0.5; done
+tmuxx rename-window gtypist
+[ -n "$exercise" ] && shift_exercise &
+msg " >>> Gtypist started."
+msg " gtypist $GTYPIST_OPTS $*"
+gtypist $GTYPIST_OPTS $@
+msg " <<< Gtypist exited."
+tmuxx set-window-option automatic-rename on
+
+msg "Switcing to user keymap"
+# kmonad-manage start
+remap
diff --git a/.local/bin/lessopen.sh b/.local/bin/lessopen.sh
new file mode 100755
index 0000000..df4a58e
--- /dev/null
+++ b/.local/bin/lessopen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+[ -d "$1" ] && { tree -CL 3 "$1"; exit; }
+
+if command -V highlight >/dev/null; then
+ highlight --force --out-format=ansi -- "$1"
+else
+ cat "$1"
+fi
diff --git a/.local/bin/loop b/.local/bin/loop
new file mode 100755
index 0000000..d3dccc7
--- /dev/null
+++ b/.local/bin/loop
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+help() {
+ echo "loop - execute command in loop
+
+USAGE:
+ loop [OPTION]... <COMMAND>
+
+OPTIONS:
+ -n INTERVAL sleep for given INTERVAL time between loops
+ all arguments of \`sleep\` command are valid
+ -c COUNT maximum count of loops (default: 1000)
+ -s clear screen for every execution
+ -q quiet, redirect output to /dev/null
+ -h show this help message
+
+ENVIRONMENT VARIABLES:
+ LOOP_INTERVAL set INTERVAL time
+ MAX_LOOP_COUNT set loop COUNT"
+}
+
+err() { printf 'loop: %s\n' "$@" >&2; exit 1; }
+
+while getopts 'sc:n:qh' o; do case "$o" in
+ s) cflag=1 ;;
+ n) export LOOP_INTERVAL="$OPTARG" ;;
+ c) export MAX_LOOP_COUNT="$OPTARG" ;;
+ q) qflag=1 ;;
+ h) help; exit ;;
+ *) err "invalid option -- $OPTARG" ;;
+esac done
+shift $((OPTIND - 1))
+
+[ "$#" -lt 1 ] && err "no COMMAND given"
+cmds="$*"
+max_count="${MAX_LOOP_COUNT:-1000}"
+[ -n "$LOOP_INTERVAL" ] && cmds="$cmds; sleep '$LOOP_INTERVAL'"
+[ "$cflag" = 1 ] && cmds="clear; $cmds"
+[ "$qflag" = 1 ] && cmds="$cmds >/dev/null"
+
+for count in $(seq "$max_count"); do
+ eval "$cmds" || break
+done
+
+[ "$count" -ge "$max_count" ] && err "reached max loop COUNT: $max_count"
diff --git a/.local/bin/lsinputs b/.local/bin/lsinputs
new file mode 100755
index 0000000..8bb091f
--- /dev/null
+++ b/.local/bin/lsinputs
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
+ (
+ syspath="${sysdevpath%/dev}"
+ devname="$(udevadm info -q name -p $syspath)"
+ [[ "$devname" == "bus/"* ]] && exit
+ eval "$(udevadm info -q property --export -p $syspath)"
+ [[ -z "$ID_SERIAL" ]] && exit
+ echo "/dev/$devname - $ID_SERIAL"
+ )
+done
diff --git a/.local/bin/mnt b/.local/bin/mnt
new file mode 100755
index 0000000..8470667
--- /dev/null
+++ b/.local/bin/mnt
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+sudo mkdir -p "${MOUNTPATH:=/run/media/$USER}"
+sudo chown "$USER:$USER" "$MOUNTPATH"
+
+makepath() {
+ [ -d "$path" ] && { rmdir "$path" || exit; }
+ mkdir -p "$path"
+}
+
+case "$1" in
+
+ mtp:*)
+ path="$MOUNTPATH/${1#mtp:}"
+ makepath
+ simple-mtpfs "$path"
+ ;;
+
+ *:|*:/*)
+ path="$MOUNTPATH/${1%%:*}"
+ makepath
+ if grep -q "^\[${1%:}\]$" "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/rclone.conf"; then
+ rclone mount --daemon "$1" "$path"
+ else
+ sshfs "$1" "$path"
+ fi
+ ;;
+
+ *)
+ if sudo cryptsetup isLuks "$1"; then
+ uuid=$(sudo cryptsetup luksUUID "$1" | tr -d -)
+ test -b /dev/disk/by-id/dm-uuid-*$uuid* && exit
+ sudo cryptsetup open "$1" "crypt-$uuid"
+ udisksctl mount -b "/dev/mapper/crypt-$uuid"
+ exit
+ fi
+ udisksctl mount -b "$1"
+ ;;
+esac
diff --git a/.local/bin/open b/.local/bin/open
new file mode 100755
index 0000000..a996105
--- /dev/null
+++ b/.local/bin/open
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+[ -z "$1" ] && echo "USAGE: open <FILE>" >&2 && exit 1
+
+for file in "$@"; do
+ case "$file" in
+
+ *.pdf|*.djvu|*.epub) setsid -f zathura "$file" ;;
+ *.png|*.jpg|*.jpeg|*.webp) setsid -f nsxiv "$file" ;;
+ *.gif|*.mkv|*.mp3|*.mp4|*.webm|*.ogg) ${PLAYER:-mpv --sub-auto=fuzzy} "$file" ;;
+ *.html) ${BROWSER:-w3m} "$file" ;;
+ *.pl.txt) fpl "$file" ;;
+ *.txt|*.description) ${PAGER:-less} "$file" ;;
+ *.md) glow --pager "$file" ;;
+ *.css|*.json|*.ipynb|*.vim|*.lua|*.iso|*.zip) LESSOPEN="|preview %s" less -r "$file" ;;
+ *.srt) fzf-subtitles -o "$file" ;;
+ *.dig) setsid -f digital "$file" ;;
+ *.doc|*.docx|*.ppt|*.pptx) setsid -f libreoffice "$file" ;;
+ *.sc|*.xls|*.xlsx) sc-im "$file" ;;
+ *.sim1) simulide "$file" ;;
+ *.xz) ${EDITOR:-nvim} "$file" ;;
+
+ *)
+ filetype="$(file --dereference --brief --mime-type "$file")"
+ case "$filetype" in
+ inode/directory) ${FILES:-lf} "$file" ; exit ;;
+ text/html*) ${BROWSER:-w3m} "$file" ;;
+ *pdf|*djvu|*epub+zip|*oxps|*fictionbook) setsid -f zathura "$file" ;;
+ text/*|*json|*zip|*zstd) "${EDITOR:-nvim}" "$file" ;;
+ application/vnd.openxmlformats-officedocument.*) setsid -f libreoffice "$file" ;;
+ application/sc) sc-im "$file" ;;
+ application/x-executable) "$file" ;;
+ image/*) setsid -f nsxiv "$file" ;;
+ video/*|audio/*) ${PLAYER:- mpv --sub-auto=fuzzy} "$file" ;;
+ *)
+ xdg-open "$file" || exit
+ [ -n "$DISPLAY" ] && notify-send "⚠️ open: unknown filetype" "$filetype"
+ echo "open: unknown filetype: $filetype" >&2
+ ;;
+ esac
+ ;;
+
+ esac
+
+ file="$(realpath "$file")"
+ sed -i "\|^$file$|d" "${XDG_DATA_HOME:-$HOME/.local/share}/openhist"
+ echo "$file" >> "${XDG_DATA_HOME:-$HOME/.local/share}/openhist"
+done
diff --git a/.local/bin/preview b/.local/bin/preview
new file mode 100755
index 0000000..f0cedb0
--- /dev/null
+++ b/.local/bin/preview
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+if [ -d "$1" ]; then
+ if [ -x /bin/eza ] || [ -x /usr/bin/eza ]; then
+ eza -alhF --group-directories-first --color=always --icons -- "$1"
+ else
+ ls -lhAF --group-directories-first --color -- "$1"
+ fi
+ readme="$(find "$1" -maxdepth 1 -name "README.*" | head -1)"
+ [ -n "$readme" ] && preview "$readme"
+ exit
+fi
+
+alias highlight='highlight --out-format=ansi'
+
+case "$1" in
+ '') echo "preview: file name required" >&2; exit 1 ;;
+ *.html) w3m -dump "$1" ;;
+ *.md) glow -s dark --width="${FZF_PREVIEW_COLUMNS:-"$(tput cols)"}" "$1" ;;
+ # *.vim) highlight --syntax=vim --replace-tabs=2 -- "$1" ;;
+ *.js|*.vim|*.lua) highlight -- "$1" ;;
+ *.txt|*.description|*.srt) cat -- "$1" ;;
+ *.png|*.jpg|*.jpeg|*.webp|*.mp3|*.ogg|*.mp4|*.mkv|*.webm) mediainfo -- "$1" ;;
+ *.info.json) jq -C . "$1" ;;
+ *.json|*.ipynb) highlight --syntax=json -- "$1" ;;
+ *.tgz|*.tar.gz) tar tzf "$1" ;;
+ *.tar.bz2|*.tbz2) tar tjf "$1" ;;
+ *.tar.txz|*.txz) xz --list "$1" ;;
+ *.tar) tar tf "$1" ;;
+ *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l "$1" ;;
+ *.rar) unrar l "$1" ;;
+ *.7z) 7z l "$1" ;;
+ *.zst) zstdcat "$1" ;;
+ *.[1-8]) man "$1" | col -b ;;
+ *.o) nm "$1" ;;
+ *.torrent) transmission-show "$1" ;;
+ *.iso) iso-info --no-header -l "$1" ;;
+ *odt|*.ods|*.odp|*.sxw) odt2txt "$1" ;;
+ *.doc) catdoc "$1" ;;
+ *.docx) docx2txt "$1" - ;;
+ # *.csv) sed s/,/\\n/g "$1" ;;
+
+ *)
+ filetype=$(file --dereference --brief --mime-type "$1")
+ case $filetype in
+ *html) w3m -dump "$1" ;;
+ text/markdown) glow -s dark -w "$(tput cols)" "$1" ;;
+ application/json) highlight --syntax=json --replace-tabs=2 -- "$1" ;;
+ text/*) highlight --force -- "$1" ;;
+ audio/*|video/*|image/*) mediainfo -- "$1" ;;
+ *xz) xz --list "$1" ;;
+ *zip|*tar*|*7z*|*bzip2) atool --list -- "$1" ;;
+ *opendocument*) odt2txt "$1" ;;
+ application/pgp-encrypted) gpg -d -- "$1" ;;
+ *) file -b "$1" ;;
+ esac
+ ;;
+
+esac
diff --git a/.local/bin/search b/.local/bin/search
new file mode 100755
index 0000000..d9c1a3d
--- /dev/null
+++ b/.local/bin/search
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+help() { echo "search - search tool for unix users
+
+USAGE:
+ search [OPTION]... <QUERY>
+
+OPTIONS:
+ -h show this help message"; }
+
+err() { printf 'search: %s\n' "$@" >&2; exit 1; }
+while getopts 'h' o; do case "$o" in
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+if [ "$PREVIEWFLAG" = 0 ]; then
+ [ -z "$INDEX" ] && export INDEX="$(echo "$*" | cut -d: -f1)"
+ [ -z "$LINE" ] && export LINE="$(echo "$*" | cut -d: -f2-)"
+
+ case "$INDEX" in
+ wiki) "${FILE_HANDLER:-preview}" "/usr/share/doc/$LINE" ;;
+ docs) "${FILE_HANDLER:-preview}" "$HOME/.local/share/Zeal/Zeal/docsets/$LINE" ;;
+ media) "${FILE_HANDLER:-preview}" "/run/media/$USER/Storage/Media/$LINE" ;;
+ library) "${FILE_HANDLER:-preview}" "/run/media/$USER/Storage/Library/$LINE" ;;
+ tldr) tldr --color=always "$LINE" ;;
+ word) sdcv-dict "$LINE" ;;
+ man)
+ page="${LINE%%)*}"; name="${page%%[ (]*}"; section="${page#*(}"
+ if [ "$name" != "$section" ]; then
+ man "$section" "$name"
+ else
+ man "$name"
+ fi
+ ;;
+ pacman) pacman --color=always -Si "${LINE%% *}" ;;
+ esac
+ exit
+fi
+
+if [ "$OPENFLAG" = 0 ]; then
+ export INDEX="$(echo "$*" | cut -d: -f1)"
+ export LINE="$(echo "$*" | cut -d: -f2-)"
+ export FILE_HANDLER="open"
+
+ case "$INDEX" in
+ wiki|docs|web-docs|media|library|man) PREVIEWFLAG=0 search ;;
+ *) PREVIEWFLAG=0 search | less -r ;;
+ esac
+ exit
+fi
+
+[ "$#" -lt 1 ] && help >&2 && exit 1
+FZF_HIST="$HOME/.local/share/fzf/search_history"
+
+cd "${SEARCHDB:-$HOME/.cache/search}" || exit
+mkdir -pv ~/.local/share/fzf
+grep -Rsi --color=always "$@" | fzf --ansi \
+ --history="$FZF_HIST" \
+ --preview="PREVIEWFLAG=0 search {}" \
+ --bind 'enter:execute(echo {} >> $FZF_HIST; OPENFLAG=0 search {})'
diff --git a/.local/bin/searchdb b/.local/bin/searchdb
new file mode 100755
index 0000000..57e3fa8
--- /dev/null
+++ b/.local/bin/searchdb
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+help() {
+ echo "searchdb - update local search database
+
+USAGE:
+ searchdb [OPTION]...
+
+OPTIONS:
+ -x clear all databases
+ -h show this help message"
+}
+
+err() { printf 'searchdb: %s\n' "$@" >&2; exit 1; }
+while getopts 'xh' o; do case "$o" in
+ x) rm -rf ~/.cache/search; exit ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+rm -rf ~/.cache/search
+export SEARCHDB="$HOME/.cache/search"
+mkdir -p "$SEARCHDB" || exit
+ln -sf /usr/share/dict/words "$SEARCHDB/word"
+
+tldr --list > "$SEARCHDB/tldr"
+apropos . > "$SEARCHDB/man"
+pacman -Ss | sed -e "N;s/\n\s*/ => /" > "$SEARCHDB/pacman"
+
+list() { find -L "$@" ! -wholename '*/.git*' -printf "%P\n"; }
+list /usr/share/doc > "$SEARCHDB/wiki"
+list ~/.local/share/Zeal/Zeal/docsets > "$SEARCHDB/docs"
+list -L "/run/media/$USER/Storage/Media" > "$SEARCHDB/media"
+list "/run/media/$USER/Storage/Library" > "$SEARCHDB/library"
diff --git a/.local/bin/setbg b/.local/bin/setbg
new file mode 100755
index 0000000..b636a37
--- /dev/null
+++ b/.local/bin/setbg
@@ -0,0 +1,18 @@
+--2024-10-23 16:26:25-- https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/setbg
+Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
+Resolving github.com (github.com)... 20.207.73.82
+Connecting to github.com (github.com)|20.207.73.82|:443... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: unspecified [text/html]
+Saving to: ‘setbg’
+
+ 0K .......... .......... .......... .......... .......... 3.47M
+ 50K .......... .......... .......... .......... .......... 9.00M
+ 100K .......... .......... .......... .......... .......... 10.7M
+ 150K .......... .......... .......... .......... .......... 10.7M
+ 200K .......... .......... .......... .......... .......... 10.9M
+ 250K .......... .......... .......... .......... .......... 11.2M
+ 300K .......... .......... .......... ....... 10.8M=0.04s
+
+2024-10-23 16:26:25 (8.07 MB/s) - ‘setbg’ saved [345695]
+
diff --git a/.local/bin/shortcuts b/.local/bin/shortcuts
new file mode 100755
index 0000000..545799f
--- /dev/null
+++ b/.local/bin/shortcuts
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+config="${XDG_CONFIG_HOME:-$HOME/.config}"
+bmdirs="$config/shell/bm-dirs"
+bmfiles="$config/shell/bm-files"
+
+shell_shortcuts="$config/shell/shortcutrc"
+zsh_named_dirs="$config/zsh/zshnameddirrc"
+lf_shortcuts="$config/lf/shortcutrc"
+vim_shortcuts="$config/nvim/shortcuts.vim"
+
+rm -f "$zsh_named_dirs" "$lf_shortcuts" "$vim_shortcuts"
+printf "# vim: filetype=sh\n" > "$shell_shortcuts"
+
+eval "echo \"$(cat "$bmdirs")\"" |
+awk -F'\t' "
+ !/^\s*#/ && !/^\s*$/ {
+ gsub(\"\\\s*#.*$\", \"\");
+ printf(\"alias %s='cd %s && ls -A'\n\", \$1, \$2) >> \"$shell_shortcuts\"
+ printf(\"hash -d %s=%s\n\", \$1, \$2) >> \"$zsh_named_dirs\"
+ printf(\"map c%s :cd %s\n\", \$1, \$2) >> \"$lf_shortcuts\"
+ printf(\"cmap ;%s %s\n\", \$1, \$2) >> \"$vim_shortcuts\"
+ }
+ "
+
+eval "echo \"$(cat "$bmfiles")\"" |
+awk -F'\t' "
+ !/^\s*#/ && !/^\s*$/ {
+ gsub(\"\\\s*#.*$\", \"\");
+ printf(\"alias %s='\$EDITOR %s'\n\", \$1, \$2) >> \"$shell_shortcuts\"
+ printf(\"hash -d %s=%s\n\", \$1, \$2) >> \"$zsh_named_dirs\"
+ printf(\"map E%s $\$EDITOR %s\n\", \$1, \$2) >> \"$lf_shortcuts\"
+ printf(\"cmap ;%s %s\n\", \$1, \$2) >> \"$vim_shortcuts\"
+ }
+ "
diff --git a/.local/bin/shorts/adbs b/.local/bin/shorts/adbs
new file mode 100755
index 0000000..bca7733
--- /dev/null
+++ b/.local/bin/shorts/adbs
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+adb -s "${ADB_DEVICE}" shell "$@"
diff --git a/.local/bin/shorts/append-to-history b/.local/bin/shorts/append-to-history
new file mode 100755
index 0000000..7d23dc8
--- /dev/null
+++ b/.local/bin/shorts/append-to-history
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+[ -n "$1" ] || exit
+sed -i "\|^${1}$|d" "${2}"
+echo "$1" >> "$2"
diff --git a/.local/bin/shorts/bs b/.local/bin/shorts/bs
new file mode 100755
index 0000000..7e7ec0a
--- /dev/null
+++ b/.local/bin/shorts/bs
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# build site
+
+cd "${SITE_BASE_DIR:-$HOME/Dev/sites/vikas.rocks}" || exit
+rm -rf public/*
+hugo
diff --git a/.local/bin/shorts/conv b/.local/bin/shorts/conv
new file mode 100755
index 0000000..92379e8
--- /dev/null
+++ b/.local/bin/shorts/conv
@@ -0,0 +1,10 @@
+#!/bin/sed -nf
+
+p
+s/\([0-9]\+\)[0-9]\{3\}\([^A-Za-z0-9]\|$\)/\1K\2/gp
+s/\([0-9]\+\)[0-9]\{3\}K\([^A-Za-z0-9]\|$\)/\1M\2/gp
+s/\([0-9]\+\)[0-9]\{3\}M\([^A-Za-z0-9]\|$\)/\1G\2/gp
+s/\([0-9]\+\)[0-9]\{3\}G\([^A-Za-z0-9]\|$\)/\1T\2/gp
+s/\([0-9]\+\)[0-9]\{3\}T\([^A-Za-z0-9]\|$\)/\1P\2/gp
+s/\([0-9]\+\)[0-9]\{3\}P\([^A-Za-z0-9]\|$\)/\1Z\2/gp
+s/\([0-9]\+\)[0-9]\{3\}Z\([^A-Za-z0-9]\|$\)/\1Y\2/gp
diff --git a/.local/bin/shorts/diffdirs b/.local/bin/shorts/diffdirs
new file mode 100755
index 0000000..9585f9f
--- /dev/null
+++ b/.local/bin/shorts/diffdirs
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+tree --dirsfirst -aL 3 "$1" > "$PREFIX/tmp/dir1.tree.txt"
+tree --dirsfirst -aL 3 "$2" > "$PREFIX/tmp/dir2.tree.txt"
+nvim -d "$PREFIX/tmp/dir1.tree.txt" "$PREFIX/tmp/dir2.tree.txt"
+
diff --git a/.local/bin/shorts/font2svg b/.local/bin/shorts/font2svg
new file mode 100755
index 0000000..539972d
--- /dev/null
+++ b/.local/bin/shorts/font2svg
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+fontforge -c "import fontforge; fontforge.open('$1').generate('${1%.*}.svg')"
diff --git a/.local/bin/shorts/preview-bat b/.local/bin/shorts/preview-bat
new file mode 100755
index 0000000..43d1532
--- /dev/null
+++ b/.local/bin/shorts/preview-bat
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+bat --tabs=2 --style=plain --color=always "$@"
diff --git a/.local/bin/shorts/preview-highlight b/.local/bin/shorts/preview-highlight
new file mode 100755
index 0000000..0972538
--- /dev/null
+++ b/.local/bin/shorts/preview-highlight
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+highlight --force --stdout --replace-tabs=2 --out-format=ansi "$@"
diff --git a/.local/bin/shorts/refcitx b/.local/bin/shorts/refcitx
new file mode 100755
index 0000000..e99fcd3
--- /dev/null
+++ b/.local/bin/shorts/refcitx
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+fcitx
+sleep 0.1
+remap
+
diff --git a/.local/bin/shorts/sc b/.local/bin/shorts/sc
new file mode 100755
index 0000000..8760379
--- /dev/null
+++ b/.local/bin/shorts/sc
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sc-im "$@"
diff --git a/.local/bin/shorts/scrcpy-k b/.local/bin/shorts/scrcpy-k
new file mode 100755
index 0000000..139732b
--- /dev/null
+++ b/.local/bin/shorts/scrcpy-k
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+remap -x
+adb connect blue:43896
+notify-send scrcpy-k "Starting scrcpy..."
+scrcpy -K --no-playback
+notify-send scrcpy-k "Connection closed..."
+remap
diff --git a/.local/bin/shorts/ssha b/.local/bin/shorts/ssha
new file mode 100755
index 0000000..3cbf87c
--- /dev/null
+++ b/.local/bin/shorts/ssha
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+[ "$TERM" != "${TERM#st-256color}" ] && export TERM=xterm-256color
+sshadd "$(find ~/.ssh -name "${1}_id_*" | head -1)"
+ssh "$@" -t "tmux attach -t $USER || tmux new -s $USER"
diff --git a/.local/bin/shorts/sync-server b/.local/bin/shorts/sync-server
new file mode 100755
index 0000000..641db9c
--- /dev/null
+++ b/.local/bin/shorts/sync-server
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+sshadd "$HOME/.ssh/${1}_id_ed25519"
+sync() { rsync -PRru --delete --exclude "*.git" "$@"; }
+
+sync \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./vim/vimrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./tmux/tmux.conf" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/aliasrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/inputrc" \
+ "${XDG_CONFIG_HOME:-$HOME/.config}/./shell/server.profile" \
+ "${1}:.config"
diff --git a/.local/bin/shorts/syncdrive b/.local/bin/shorts/syncdrive
new file mode 100755
index 0000000..3d010cc
--- /dev/null
+++ b/.local/bin/shorts/syncdrive
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+rclone -v sync --delete-excluded --exclude=".git/**" ~/GDrive gdrive:
diff --git a/.local/bin/shorts/synchs b/.local/bin/shorts/synchs
new file mode 100755
index 0000000..244dd48
--- /dev/null
+++ b/.local/bin/shorts/synchs
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+sync-server rpi
+
+# rsync -u ~/.config/lf/lfrc /tmp/lfrc
+# sed -i '/set icons/d' /tmp/lfrc
+# rsync -Pu /tmp/lfrc rpi:.config/lf/
diff --git a/.local/bin/shorts/synctab b/.local/bin/shorts/synctab
new file mode 100755
index 0000000..1e44419
--- /dev/null
+++ b/.local/bin/shorts/synctab
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+sshadd ~/.ssh/tab_id_ed25519
+sync() { rsync -Pru --delete --exclude "*.git" "$@"; }
+
+sync ~/GDrive/ tab:GDrive/
+sync "${XDG_VIDEOS_DIR:-$HOME/Videos}" tab:Videos/
+
+sync -R \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./allreader" \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./latex" \
+ "${XDG_DOCUMENTS_DIR:-$HOME/Documents}/./Notes/bookmarks.txt" \
+ tab:Documents/
+
+sync \
+ "${XDG_MUSIC_DIR:-$HOME/Music}/Piano" \
+ "${XDG_MUSIC_DIR:-$HOME/Music}/Devotional" \
+ tab:Music/
+
diff --git a/.local/bin/shorts/xdg-terminal-exec b/.local/bin/shorts/xdg-terminal-exec
new file mode 100755
index 0000000..43ed65d
--- /dev/null
+++ b/.local/bin/shorts/xdg-terminal-exec
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+st -e "$@"
diff --git a/.local/bin/shorts/xprint b/.local/bin/shorts/xprint
new file mode 100755
index 0000000..12156f2
--- /dev/null
+++ b/.local/bin/shorts/xprint
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+[ -n "$TERMUX_VERSION" ] && { termux-clipboard-get; exit; }
+
+xclip -out -selection clipboard 2>/dev/null ||
+xclip -out -selection secondry 2>/dev/null ||
+xclip -out -selection primary 2>/dev/null ||
+notify-send "Selection and clipboard is empty"
diff --git a/.local/bin/sshadd b/.local/bin/sshadd
new file mode 100755
index 0000000..6fb3b18
--- /dev/null
+++ b/.local/bin/sshadd
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+[ -z "$SSH_AUTH_SOCK" ] && export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
+msg=$(ssh-add -L 2>&1)
+if [ "$msg" = 'Could not open a connection to authentication agent.' ] ||
+ [ "$msg" = 'Error connecting to agent: No such file or directory' ] ||
+ [ "$msg" = 'Error connecting to agent: Connection refused' ]; then
+ rm -f "${SSH_AUTH_SOCK}"
+ ssh-agent -a "${SSH_AUTH_SOCK}" > /dev/null
+fi
+
+private_key="$1"
+content="$(cat "$1.pub")"
+if [ "$msg" = "The agent has no identities." ] ||
+ [ "${msg#*$content}" = "$msg" ]; then
+ ssh-add "$private_key"
+fi
diff --git a/.local/bin/statusbar/cpu_usage b/.local/bin/statusbar/cpu_usage
new file mode 100755
index 0000000..be729e2
--- /dev/null
+++ b/.local/bin/statusbar/cpu_usage
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+#
+# Copyright 2014 Pierre Mavro <deimos@deimos.fr>
+# Copyright 2014 Vivien Didelot <vivien@didelot.org>
+# Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>
+#
+# Licensed under the terms of the GNU GPL v3, or any later version.
+
+use strict;
+use warnings;
+use utf8;
+use Getopt::Long;
+
+# default values
+my $t_warn = 50;
+my $t_crit = 80;
+my $cpu_usage = -1;
+
+sub help {
+ print "Usage: cpu_usage [-w <warning>] [-c <critical>]\n";
+ print "-w <percent>: warning threshold to become yellow\n";
+ print "-c <percent>: critical threshold to become red\n";
+ exit 0;
+}
+
+GetOptions("help|h" => \&help,
+ "w=i" => \$t_warn,
+ "c=i" => \$t_crit);
+
+# Get CPU usage
+$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it is
+open (MPSTAT, 'mpstat 1 1 |') or die;
+while (<MPSTAT>) {
+ if (/^.*\s+(\d+\.\d+)\s+$/) {
+ $cpu_usage = 100 - $1; # 100% - %idle
+ last;
+ }
+}
+close(MPSTAT);
+
+$cpu_usage eq -1 and die 'Can\'t find CPU information';
+
+# Print short_text, full_text
+printf "%.1f%%\n", $cpu_usage;
+# printf "%.2f%%\n", $cpu_usage;
+
+# # Print color, if needed
+# if ($cpu_usage >= $t_crit) {
+# print "#FF0000\n";
+# exit 33;
+# } elsif ($cpu_usage >= $t_warn) {
+# print "#FFFC00\n";
+# }
+
+exit 0;
diff --git a/.local/bin/statusbar/i3bandwidth b/.local/bin/statusbar/i3bandwidth
new file mode 100755
index 0000000..8877d28
--- /dev/null
+++ b/.local/bin/statusbar/i3bandwidth
@@ -0,0 +1,105 @@
+#!/usr/bin/bash
+# Copyright (C) 2012 Stefan Breunig <stefan+measure-net-speed@mathphys.fsk.uni-heidelberg.de>
+# Copyright (C) 2014 kaueraal
+# Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+case "$BLOCK_BUTTON" in
+ 2) $TERMINAL -e nvim "$0" ;;
+esac
+
+# Use the provided interface, otherwise the device used for the default route.
+if [[ -n $BLOCK_INSTANCE ]]; then
+ INTERFACE=$BLOCK_INSTANCE
+else
+ INTERFACE=$(ip route | awk '/^default/ { print $5 ; exit }')
+fi
+
+[ -z "$INTERFACE" ] && echo && exit
+
+# Issue #36 compliant.
+if ! [ -e "/sys/class/net/${INTERFACE}/operstate" ] || ! [ "$(cat "/sys/class/net/${INTERFACE}/operstate")" = "up" ]
+then
+ # echo "$INTERFACE down"
+ # echo "$INTERFACE down"
+ # echo "#FF0000"
+ echo " "
+ exit 0
+fi
+
+# path to store the old results in
+path="/dev/shm/$(basename "$0")-${INTERFACE}"
+
+# grabbing data for each adapter.
+read -r rx < "/sys/class/net/${INTERFACE}/statistics/rx_bytes"
+read -r tx < "/sys/class/net/${INTERFACE}/statistics/tx_bytes"
+
+# get time
+time=$(date +%s)
+
+# write current data if file does not exist. Do not exit, this will cause
+# problems if this file is sourced instead of executed as another process.
+if ! [[ -f "${path}" ]]; then
+ echo "${time} ${rx} ${tx}" > "${path}"
+ chmod 0666 "${path}"
+fi
+
+# read previous state and update data storage
+read -r old < "${path}"
+echo "${time} ${rx} ${tx}" > "${path}"
+
+# parse old data and calc time passed
+old=(${old//;/ })
+time_diff=$(( time - old[0] ))
+
+# sanity check: has a positive amount of time passed
+[[ "${time_diff}" -gt 0 ]] || { echo " "; exit; }
+
+# calc bytes transferred, and their rate in byte/s
+rx_diff=$(( rx - old[1] ))
+tx_diff=$(( tx - old[2] ))
+rx_rate=$(( rx_diff / time_diff ))
+tx_rate=$(( tx_diff / time_diff ))
+
+# shift by 10 bytes to get KiB/s. If the value is larger than
+# 1024^2 = 1048576, then display MiB/s instead
+
+# incoming
+rx_kib=$(( rx_rate >> 10 ))
+if [ "$rx_kib" -gt 1 ]; then
+ # echo -n "📥 "
+ echo -n "↓ "
+ if [[ "$rx_rate" -gt 1048576 ]]; then
+ printf '%sM' "$(echo "scale=1; $rx_kib / 1024" | bc)"
+ else
+ echo -n "${rx_kib}K"
+ fi
+fi
+
+# outgoing
+tx_kib=$(( tx_rate >> 10 ))
+if [ "$tx_kib" -gt 1 ]; then
+ # echo -n "📤 "
+ echo -n " ↑ "
+ if [[ "$tx_rate" -gt 1048576 ]]; then
+ printf '%sM' "$(echo "scale=1; $tx_kib / 1024" | bc)"
+ else
+ echo -n "${tx_kib}K"
+ fi
+fi
+
+# echo
+# echo
+# echo "$BLOCK_COLOR_LEVEL1"
diff --git a/.local/bin/statusbar/i3battery b/.local/bin/statusbar/i3battery
new file mode 100755
index 0000000..5b2fb15
--- /dev/null
+++ b/.local/bin/statusbar/i3battery
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) notify-send Temprature "$(sensors --no-adapter coretemp-isa-0000 |
+ tail +2 | sed "s|(.*)||")" ;;
+ 2) $TERMINAL -e "$EDITOR" "$0" ;;
+ 3) $TERMINAL -e battop ;;
+ 4) brightness up ;;
+ 5) brightness down ;;
+esac;
+
+# Loop through all attached batteries and format the info
+for battery in /sys/class/power_supply/BAT?*; do
+ capacity="$(cat "$battery/capacity" 2>&1)"
+ # If non-first battery, print a space separator.
+ # [ -n "${capacity+x}" ] && printf " "
+ # Sets up the status and capacity
+ status="$(cat "$battery/status" 2>&1)"
+ case "$status" in
+ "Full") icon="󰂄" ;;
+ "Discharging") case "$capacity" in
+ 9[0-9]) icon="󰂂" ;;
+ 8[0-9]) icon="󰂁" ;;
+ 7[0-9]) icon="󰂀" ;;
+ 6[0-9]) icon="󰁿" ;;
+ 5[0-9]) icon="󰁾" ;;
+ 4[0-9]) icon="󰁽" ;;
+ 3[0-9]) icon="󰁼" ;;
+ 2[0-9]) icon="󰁻" ;;
+ 1[0-9]|[0-9]) icon="󰁺" ;;
+ 100) icon="󰁹" ;;
+ esac ;;
+ "Charging") case "$capacity" in
+ 9[0-9]) icon="󰂋" ;;
+ 8[0-9]) icon="󰢞" ;;
+ 7[0-9]) icon="󰢞" ;;
+ 6[0-9]) icon="󰂉" ;;
+ 5[0-9]) icon="󰢝" ;;
+ 4[0-9]) icon="󰂈" ;;
+ 3[0-9]) icon="󰂇" ;;
+ 2[0-9]) icon="󰂆" ;;
+ 1[0-9]|[0-9]) icon="󰢜" ;;
+ 100) icon="󰂅" ;;
+ esac ;;
+ "Not charging") icon="󱉝" ;;
+ "Unknown") icon="󰂑" ;;
+ *) exit 1 ;;
+ esac
+ # Will make a warn variable if discharging and low
+ [ "$status" = "Discharging" ] && [ "$capacity" -le 25 ] && warn="❗"
+ # Prints the info
+ printf "%s%s %d%%" "$warn" "$icon" "$capacity"; unset warn
+done && printf "\\n"
+
+echo
+if [ $capacity -ge 80 ]; then
+ echo "$BLOCK_COLOR_LEVEL1"
+elif [ $capacity -ge 40 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+elif [ $capacity -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ $capacity -ge 10 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+else
+ echo "$BLOCK_COLOR_LEVEL5"
+fi
diff --git a/.local/bin/statusbar/i3cpu b/.local/bin/statusbar/i3cpu
new file mode 100755
index 0000000..c5eeb68
--- /dev/null
+++ b/.local/bin/statusbar/i3cpu
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e gotop ;;
+ 2) $TERMINAL -e nvim "$(which i3cpu)" ;;
+ 3) echo "top,$TERMINAL -e top
+ htop,$TERMINAL -e htop
+ gotop,$TERMINAL -e gotop
+ nvtop,$TERMINAL -e nvtop" | jgmenu --vsimple --at-pointer ;;
+esac;
+
+cpu_usage="$(cpu_usage)"
+cpu="${cpu_usage%.*}"
+printf "%s" "$cpu_usage"
+# printf " "
+# sb-cpubars
+
+echo
+echo
+# Print color, if needed
+if [ "$cpu" -ge 90 ]; then
+ echo "$BLOCK_COLOR_LEVEL5";
+ exit 33;
+elif [ "$cpu" -ge 70 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+elif [ "$cpu" -ge 50 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ "$cpu" -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+else
+ echo "$BLOCK_COLOR_LEVEL1"
+fi
+
+
diff --git a/.local/bin/statusbar/i3cpubars b/.local/bin/statusbar/i3cpubars
new file mode 100755
index 0000000..c4c18af
--- /dev/null
+++ b/.local/bin/statusbar/i3cpubars
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Module showing CPU load as a changing bars.
+# Just like in polybar.
+# Each bar represents amount of load on one core since
+# last run.
+
+# Cache in tmpfs to improve speed and reduce SSD load
+cache=/tmp/cpubarscache
+
+case $BLOCK_BUTTON in
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🪨 CPU load module" "Each bar represents
+one CPU core";;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# id total idle
+stats=$(awk '/cpu[0-9]+/ {printf "%d %d %d\n", substr($1,4), ($2 + $3 + $4 + $5), $5 }' /proc/stat)
+[ ! -f $cache ] && echo "$stats" > "$cache"
+old=$(cat "$cache")
+# printf "🪨"
+echo "$stats" | while read -r row; do
+ id=${row%% *}
+ rest=${row#* }
+ total=${rest%% *}
+ idle=${rest##* }
+
+ case "$(echo "$old" | awk '{if ($1 == id)
+ printf "%d\n", (1 - (idle - $3) / (total - $2))*100 /12.5}' \
+ id="$id" total="$total" idle="$idle")" in
+
+ "0") printf "▁";;
+ "1") printf "▂";;
+ "2") printf "▃";;
+ "3") printf "▄";;
+ "4") printf "▅";;
+ "5") printf "▆";;
+ "6") printf "▇";;
+ "7") printf "█";;
+ "8") printf "█";;
+ esac
+done; # printf "\\n"
+echo "$stats" > "$cache"
diff --git a/.local/bin/statusbar/i3cpuload b/.local/bin/statusbar/i3cpuload
new file mode 100755
index 0000000..6c14ddd
--- /dev/null
+++ b/.local/bin/statusbar/i3cpuload
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#
+# Copyright 2014 Pierre Mavro <deimos@deimos.fr>
+# Copyright 2014 Vivien Didelot <vivien@didelot.org>
+# Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>
+#
+# Licensed under the terms of the GNU GPL v3, or any later version.
+
+use strict;
+use warnings;
+use utf8;
+use Getopt::Long;
+
+# default values
+my $t_warn = $ENV{T_WARN} // 70; # default 50
+my $t_crit = $ENV{T_CRIT} // 90; # default 80
+my $cpu_usage = -1;
+my $decimals = $ENV{DECIMALS} // 2;
+my $label = $ENV{LABEL} // "";
+
+sub help {
+ print "Usage: cpu_usage [-w <warning>] [-c <critical>] [-d <decimals>]\n";
+ print "-w <percent>: warning threshold to become yellow\n";
+ print "-c <percent>: critical threshold to become red\n";
+ print "-d <decimals>: Use <decimals> decimals for percentage (default is $decimals) \n";
+ exit 0;
+}
+
+GetOptions("help|h" => \&help,
+ "w=i" => \$t_warn,
+ "c=i" => \$t_crit,
+ "d=i" => \$decimals,
+);
+
+# Get CPU usage
+$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it is
+open (MPSTAT, 'mpstat |') or die;
+while (<MPSTAT>) {
+ if (/^.*\s+(\d+\.\d+)[\s\x00]?$/) {
+ $cpu_usage = 100 - $1; # 100% - %idle
+ last;
+ }
+}
+close(MPSTAT);
+
+$cpu_usage eq -1 and die 'Can\'t find CPU information';
+
+# Print short_text, full_text
+print "${label}";
+printf "%.${decimals}f%%\n", $cpu_usage;
+
+
+# print "\n";
+# # Print color, if needed
+# if ($cpu_usage >= $t_crit) {
+# print "$ENV{BLOCK_COLOR_LEVEL5}\n";
+# exit 33;
+# } elsif ($cpu_usage >= $t_warn) {
+# print "$ENV{BLOCK_COLOR_LEVEL4}\n";
+# } elsif ($cpu_usage >= 50) {
+# print "$ENV{BLOCK_COLOR_LEVEL3}\n";
+# } elsif ($cpu_usage >= 20) {
+# print "$ENV{BLOCK_COLOR_LEVEL2}\n";
+# } else {
+# print "$ENV{BLOCK_COLOR_LEVEL1}\n";
+# }
+
+exit 0;
diff --git a/.local/bin/statusbar/i3memory b/.local/bin/statusbar/i3memory
new file mode 100755
index 0000000..edf9a73
--- /dev/null
+++ b/.local/bin/statusbar/i3memory
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e gotop ;;
+ 2) $TERMINAL -e nvim "$(which i3cpu)" ;;
+ 3) echo "top,$TERMINAL -e top
+ htop,$TERMINAL -e htop
+ gotop,$TERMINAL -e gotop
+ nvtop,$TERMINAL -e nvtop" | jgmenu --vsimple --at-pointer ;;
+esac;
+
+memory="$(memory_percent)"
+printf "%s" "$(memory_usage)"
+# printf " "
+# sb-cpubars
+
+echo
+echo
+# Print color, if needed
+if [ "$memory" -ge 90 ]; then
+ echo "$BLOCK_COLOR_LEVEL5";
+ exit 33;
+elif [ "$memory" -ge 70 ]; then
+ echo "$BLOCK_COLOR_LEVEL4"
+elif [ "$memory" -ge 50 ]; then
+ echo "$BLOCK_COLOR_LEVEL3"
+elif [ "$memory" -ge 20 ]; then
+ echo "$BLOCK_COLOR_LEVEL2"
+else
+ echo "$BLOCK_COLOR_LEVEL1"
+fi
+
+
diff --git a/.local/bin/statusbar/i3weather b/.local/bin/statusbar/i3weather
new file mode 100755
index 0000000..2d34149
--- /dev/null
+++ b/.local/bin/statusbar/i3weather
@@ -0,0 +1,26 @@
+#!/bin/sh
+# i3block for displaying the current temperature, humidity and precipitation, if wttr.in i unavailable then WEATHER UNAVAILABLE will be displayed
+
+case "$BLOCK_BUTTON" in
+ '') ;;
+ 1)
+ $TERMINAL -e less -r ~/.cache/weather.txt & sleep 0.3
+ i3-msg 'move to workspace "12: Weather"; workspace "12: Weather"' >/dev/null 2>&1
+ ;;
+ 2) $TERMINAL -e nvim "$0" ;;
+ *) notify-send "⛅ Refreshing weather info..." ;;
+esac
+
+HTTP_WEATHER="https://wttr.in/Vasai"
+# weather="$(curl -s "$HTTP_WEATHER?format=%c%C++❄️+%t++☀️+%f++🌬️+%w")"
+weather="$(curl -Ss "$HTTP_WEATHER?0&T&Q" | cut -c 16- | head -2 |
+ xargs echo "$(curl -s "$HTTP_WEATHER?format=%c")")"
+
+if [ "$(echo "$weather" | grep -Ec "(Unknown|curl|HTML)")" -gt 0 ]; then
+ echo "WEATHER UNAVAILABLE"
+else
+ echo "${weather:-⛅ -- }"
+fi
+
+curl -s "$HTTP_WEATHER" > ~/.cache/weather.txt
+
diff --git a/.local/bin/statusbar/i3wifi b/.local/bin/statusbar/i3wifi
new file mode 100755
index 0000000..689e3a2
--- /dev/null
+++ b/.local/bin/statusbar/i3wifi
@@ -0,0 +1,37 @@
+#!/bin/sh
+# i3block for the displaying the wifi connectivity level
+# If the wifi interface exists but no connection is active, "down" shall be displayed.
+
+case "$BLOCK_BUTTON" in
+ 1) $TERMINAL -e nmtui ;;
+ 2) $TERMINAL -e nvim "$0" ;;
+ 3) $TERMINAL -e nethogs ;;
+ # 3) echo "nethogs,$TERMINAL -e nethogs
+ # bmon,$TERMINAL -e bmon
+ # nmtui, $TERMINAL -e nmtui" | jgmenu --vsimple --at-pointer ;;
+esac
+
+iface="$(find /sys/class/net/ -maxdepth 1 -name "w*" -printf "%f\n")"
+if [ "$(cat "/sys/class/net/$iface/operstate")" = 'down' ]; then
+ icon="󰤭"; quality="down"; color="$BLOCK_COLOR_LEVEL5"
+else
+ quality=$(grep "$iface" /proc/net/wireless | awk '{ print int($3 * 100 / 70) }')
+ if [ "$quality" = 100 ]; then
+ icon="󰤨"; color="$BLOCK_COLOR_LEVEL1"
+ elif [ "$quality" -ge 80 ]; then
+ icon="󰤥"; color="$BLOCK_COLOR_LEVEL1"
+ elif [ "$quality" -ge 60 ]; then
+ icon="󰤢"; color="$BLOCK_COLOR_LEVEL2"
+ elif [ "$quality" -ge 40 ]; then
+ icon="󰤟"; color="$BLOCK_COLOR_LEVEL3"
+ elif [ "$quality" -ge 20 ]; then
+ icon="󰤟"; color="$BLOCK_COLOR_LEVEL4"
+ else
+ icon="󰤯"; color="$BLOCK_COLOR_LEVEL5"
+ fi
+ [ -n "$quality" ] && quality="$quality%"
+fi
+
+echo "$icon $quality"
+echo
+echo "$color"
diff --git a/.local/bin/statusbar/memory_percent b/.local/bin/statusbar/memory_percent
new file mode 100755
index 0000000..2b8da66
--- /dev/null
+++ b/.local/bin/statusbar/memory_percent
@@ -0,0 +1,57 @@
+#!/bin/sh
+# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+TYPE="${BLOCK_INSTANCE:-mem}"
+
+awk -v type=$TYPE '
+/^MemTotal:/ {
+ mem_total=$2
+}
+/^MemFree:/ {
+ mem_free=$2
+}
+/^Buffers:/ {
+ mem_free+=$2
+}
+/^Cached:/ {
+ mem_free+=$2
+}
+/^SwapTotal:/ {
+ swap_total=$2
+}
+/^SwapFree:/ {
+ swap_free=$2
+}
+END {
+ if (type == "swap") {
+ free=swap_free/1024/1024
+ used=(swap_total-swap_free)/1024/1024
+ total=swap_total/1024/1024
+ } else {
+ free=mem_free/1024/1024
+ used=(mem_total-mem_free)/1024/1024
+ total=mem_total/1024/1024
+ }
+ pct=0
+ if (total > 0) {
+ pct=used/total*100
+ }
+ # full text
+ # printf("%.1fG/%.1fG", used, total)
+ # printf("%.1fG", used)
+ printf("%d", pct)
+}
+' /proc/meminfo
diff --git a/.local/bin/statusbar/memory_usage b/.local/bin/statusbar/memory_usage
new file mode 100755
index 0000000..8f0fee4
--- /dev/null
+++ b/.local/bin/statusbar/memory_usage
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+TYPE="${BLOCK_INSTANCE:-mem}"
+
+awk -v type=$TYPE '
+/^MemTotal:/ {
+ mem_total=$2
+}
+/^MemFree:/ {
+ mem_free=$2
+}
+/^Buffers:/ {
+ mem_free+=$2
+}
+/^Cached:/ {
+ mem_free+=$2
+}
+/^SwapTotal:/ {
+ swap_total=$2
+}
+/^SwapFree:/ {
+ swap_free=$2
+}
+END {
+ if (type == "swap") {
+ free=swap_free/1024/1024
+ used=(swap_total-swap_free)/1024/1024
+ total=swap_total/1024/1024
+ } else {
+ free=mem_free/1024/1024
+ used=(mem_total-mem_free)/1024/1024
+ total=mem_total/1024/1024
+ }
+ pct=0
+ if (total > 0) {
+ pct=used/total*100
+ }
+ # full text
+ # printf("%.1fG/%.1fG", used, total)
+ printf("%.1fG", used)
+}
+' /proc/meminfo
diff --git a/.local/bin/ttyl b/.local/bin/ttyl
new file mode 100755
index 0000000..fd71280
--- /dev/null
+++ b/.local/bin/ttyl
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+help() {
+ echo "ttyl - tty lock
+
+USAGE:
+ ttyl [OPTION]... [COMMAND]
+
+OPTIONS:
+ -a lock all TTYs
+ (default when no command is passed and terminal is a tty)
+ -c lock current TTY
+ -h show this help message"
+}
+
+err() { printf 'ttyl: %s\n' "$@" >&2; exit 1; }
+
+while getopts 'ach' o; do case "$o" in
+ a) lockall=0 ;;
+ c) lockall=1 ;;
+ h) help >&2; exit ;;
+ *) err "invalid option -- '$OPTARG'" ;;
+esac done
+shift $((OPTIND - 1))
+
+case "$lockall" in
+ 1) lock="vlock" ;;
+ 0) lock="vlock -a" ;;
+ *)
+ case "$(tty)" in
+ /dev/tty[1-7]) lock="vlock -a" ;;
+ *) lock="vlock" ;;
+ esac
+ ;;
+esac
+
+sleep 1 && $@ & $lock
diff --git a/.local/bin/unix b/.local/bin/unix
new file mode 100755
index 0000000..a9fb96e
--- /dev/null
+++ b/.local/bin/unix
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#original artwork by http://www.sanderfocus.nl/#/portfolio/tech-heroes
+#converted to shell by #nixers @ irc.unix.chat
+
+cat << 'eof'
+ ,_ ,_==▄▂
+ , ▂▃▄▄▅▅▅▂▅¾. / /
+ ▄▆<´ "»▓▓▓%\ / / / /
+ ,▅7" ´>▓▓▓% / / > / >/%
+ ▐¶▓ ,»▓▓¾´ /> %/%// / /
+ ▓▃▅▅▅▃,,▄▅▅▅Æ\// ///>// />/ /
+ V║«¼.;→ ║<«.,`=// />//%/% / /
+ //╠<´ -²,)(▓~"-╝/¾/ %/>/ />
+ / / / ▐% -./▄▃▄▅▐, /7//;//% / /
+ / ////`▌▐ %zWv xX▓▇▌//&;% / /
+ / / / %//%/¾½´▌▃▄▄▄▄▃▃▐¶\/& /
+ </ /</%//`▓!%▓%╣[38;5;255;╣WY<Y)y&/`\
+ / / %/%//</%//\i7; ╠N>)VY>7; \_ UNIX IS VERY SIMPLE IT JUST NEEDS A
+ / /</ //<///<_/%\▓ V%W%£)XY _/%‾\_, GENIUS TO UNDERSTAND ITS SIMPLICITY
+ / / //%/_,=--^/%/%%\¾%¶%%} /%%%%%%;\,
+ %/< /_/ %%%%%;X%%\%%;, _/%%%;, \
+ / / %%%%%%;, \%%l%%;// _/%;, dmr
+ / %%%;, <;\-=-/ /
+ ;, l
+eof
diff --git a/.local/bin/web/fpl b/.local/bin/web/fpl
new file mode 100755
index 0000000..0398770
--- /dev/null
+++ b/.local/bin/web/fpl
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# You can pass any text file containing a list of video titles.
+# An fzf prompt will shown to select a video title.
+# The script will then try to find a video file whose name fuzzy matches the
+# selected title.
+
+[ -z "$1" ] && { echo "fzf-playlist: browse a list of video titles
+USAGE: fpl <PLAYLIST_FILE>" >&2; exit 1; }
+
+if [ "$OPENFLAG" = 1 ]; then
+
+ if [ -z "$OPENWITH" ]; then
+ files="$(find "${PWD%/*}")"
+ else
+ files="$(find "${PWD%/*}" -name '*.webm' -or -name '*.mkv' -or -name '*.mp4' -or \
+ -name '*.mp3' -or -name '*.ogg')"
+ fi
+
+ if [ -z "$OPENWITH" ]; then
+ for title in "$@"; do echo "$files" |
+ fzf --filter "$(printf '%s\n' "$title" | sed 's/[^A-Za-z0-9]*//g')"
+ echo; done
+ else
+ for title in "$@"; do $OPENWITH "$(echo "$files" |
+ fzf --filter "$(printf '%s\n' "$title" | sed 's/[^A-Za-z0-9]*//g')" |
+ head -1)"; echo; done
+ fi
+
+ exit
+fi
+
+file="$(readlink -f "$1")"
+cd "${file%/*}" || exit
+fzf --multi --reverse \
+ --header="Playlist: ${file##*/}" --header-first \
+ --bind 'enter:become(OPENFLAG=1 fpl {+})' \
+ --bind 'ctrl-o:execute(OPENFLAG=1 OPENWITH=mpv fpl {})' < "$file"
+
diff --git a/.local/bin/web/savesite b/.local/bin/web/savesite
new file mode 100755
index 0000000..206a633
--- /dev/null
+++ b/.local/bin/web/savesite
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+[ "$#" -lt 1 ] && { echo "savesite - save local copy of a website
+USAGE: savesite <URL> [DEST_DIR]"; exit 1; }
+
+url="$1"
+site="${2:-"$(echo "$url" | sed 's|\(https\?://\)\?\([A-Za-z0-9.-]*\)/.*|\2|')"}"
+WGETLOGS="${3:-.logs/$site.log}"
+started="$(date)"
+
+touch "$WGETLOGS" || exit
+printf ":: Downloading site: %s\n" "$site"
+printf ":: Logging to: %s\n" "$WGETLOGS"
+
+{
+ setsid wget \
+ --continue \
+ --recursive \
+ --no-clobber \
+ --page-requisites \
+ --html-extension \
+ --convert-links \
+ --restrict-file-names=windows \
+ --domains "$site" \
+ --no-parent \
+ --output-file "$WGETLOGS" \
+ "$url"
+
+ [ -n "$DISPLAY" ] && notify-send "savesite: finished downloading" "$site"
+ printf "%s\n" ":: Finished downloading site: $site" \
+ ":: Started at: $started" \
+ ":: Finished at: $(date)" >> "$WGETLOGS"
+} &
+
+tail -f "$WGETLOGS"
diff --git a/.local/bin/web/w3mman b/.local/bin/web/w3mman
new file mode 100755
index 0000000..5013fbd
--- /dev/null
+++ b/.local/bin/web/w3mman
@@ -0,0 +1,335 @@
+#!/bin/bash
+
+# w3m-man
+#
+# Use wget, w3m and less to download and view man pages.
+#
+# Homepage: https://github.com/sc0ttj/w3m-man
+#
+# Supports using $MANPAGER, $HTMLPAGER, $TERM_BROWSER, and
+# falls back to w3m and less if these are not set.
+#
+# How it works:
+#
+# - saves manpage from online sources to $HOME/.w3m-manpages/
+# - not proper man pages, just plain text output of websites
+# - prettifies them a bit (removes junk headers, links, messages)
+#
+# Usage:
+#
+# man <command> # view man page in plain text in $PAGER
+# man -H <command> # view man page as HTML in $BROWSER
+# man <command> --url # print the URL of the man page to STDOUT
+
+# TODO:
+#
+# - Display the path searched for manpages:
+#
+# man --path
+#
+# - Display the location of a manpage rather than the manpage itself:
+#
+# man -w command
+#
+# - Search for manpages containing a search string:
+#
+# man -k "search_string"
+#
+
+if [ "$1" = "--help" ];then
+
+ echo "# man (w3m-man)
+# Use wget, w3m and less to download and view man pages
+# See https://github.com/sc0ttj/w3m-man
+
+Usage:
+
+ man <command> # (download and) print the man page
+
+ man <command> --url # print the URL from which the man
+ # page was/would be downloaded
+
+ man --help # print this help info
+
+Where <command> is the command name you want to read about.
+
+Examples:
+
+ man diff # view 'diff' command (section 1)
+
+ man mount.8 # view 'mount' in section 8 (config stuff)
+
+ man 8 mount # same as above, but doesn't work with -H
+
+ man -H mount # view 'mount' man page as HTML using $BROWSER
+
+ man <command> --url # only print the URL from which the man page
+ # was/would be downloaded
+
+Man pages are divided into sections, as follows:
+
+ 1. User: most user commands and programs.
+
+ 2. System: calls by the Linux kernel.
+
+ 3. Library: documents provided by the standard C library.
+
+ 4. Devices: documents various devices, most of which reside in /dev.
+
+ 5. Files: describes various file formats and filesystems and proc(5).
+
+ 7. Overviews, conventions, and miscellaneous.
+
+ 8. Superuser and system administration commands.
+
+Checks the following URLs:
+
+the Ubuntu or Debian man pages, also:
+
+http://man.he.net/?topic=\${command}&section=\${section}
+http://manpages.org/\${command}/\${section}
+https://linux.die.net/man/\${section}/\${command}
+https://www.mankier.com/\${section}/\${command}
+https://man7.org/linux/man-pages/man\${section}/\${command}.\${section}.html
+http://manpages.org/\${command}
+http://man.he.net/?topic=\${command}&section=all
+https://ss64.com/bash/\${command}.html
+"
+ exit 0
+fi
+
+old_man="$(command -v man)"
+unset man
+
+command="$1"
+section="1"
+
+DISTRO_COMPAT_VERSION="latest"
+if [ -f /etc/DISTRO_SPECS ];then
+ source /etc/DISTRO_SPECS
+fi
+
+
+# support GNU man -H option (to view as HTML)
+if [ "$1" = "-H" ];then
+ command="$2"
+fi
+
+# support GNU man syntax `man 1 mount`
+re='^[1-8]+$'
+if [[ $1 =~ $re ]] ; then
+ command="${2}.$1"
+ section="$1"
+fi
+
+# support GNU man syntax `man mount.1`, `man mount.2`, etc
+section="${command//*\./}"
+command="${command//\.*/}"
+if [ "$command" = "$section" ];then
+ section=1
+fi
+
+manpage_file="$HOME/.w3m-manpages/$command.$section"
+
+# support env var $MANPAGER
+pager=${MANPAGER:-$PAGER}
+pager=${pager:-less -XR}
+w3m='w3m -o auto_image=false -o display_image=false'
+browser=${TERM_BROWSER:-$TERMBROWSER}
+browser=${browser:-$w3m}
+htmlpager=${HTMLPAGER:-w3m -dump}
+
+# Remove some junk from the plain text files generated by w3m,
+# such as headers, links to adverts, etc
+function prettifier {
+ url="$1"
+ case "$url" in
+
+ *'ubuntu.com'*|*'debian.org'*)
+ sed \
+ -e '1,5d' \
+ -e 's/ bug$//' \
+ -e 's/ / /g'
+ ;;
+
+ *'linux.die.net'*)
+ sed -e '1d' -e 's/\[INS::INS\]//g' -e 's/ \[ \]//g' \
+ -e 's/Site Search//g' 2>/dev/null | head -n -12
+ ;;
+
+ *mankier*)
+ grep -vEi ' • [A-Z]| □ [A-Z]' | sed -e '1,7d' -e 's/tldr.sh//g' \
+ -e "s/$command /$command($section) /g"
+ ;;
+
+ *ss64*com*)
+ sed '1,5d' 2>/dev/null
+ ;;
+
+ *'man7.org'*)
+ sed -e '1,4d' -e '8,13d' -e 's/ top/ /g' \
+ | grep -vE 'StatCounter' | head -n -15
+ ;;
+
+ *manpages*org*)
+ sed -e '1,3d' \
+ | head -n -14
+ ;;
+
+ *man*he*net*) cat - ;;
+
+ *) cat - ;;
+ esac
+}
+
+# create the config dir, if needed
+[ ! -d $HOME/.w3m-manpages ] && mkdir -p $HOME/.w3m-manpages
+
+# if we already have a proper man page, just print it and exit
+if [ ! -z "$MANPATH" ] && [ "$(which groff)" != "" ] && [ "$1" != "-H" ] && [ "$2" != "--url" ];then
+ usegroff=false
+ groff_file=''
+ zipped=false
+ paths=$(echo "${MANPATH}" | tr ':' '\n')
+ # for each path
+ for dir in ./ $paths
+ do
+ zipped=false
+ # let's find the man page file
+ groff_file=$dir/man${section}/${command}.${section}
+ # it might be gzipped
+ [ ! -f $groff_file ] && groff_file=$dir/man${section}/${command}.${section}.gz && zipped=true
+ # it might be in the current directory
+ [ -f ./${command}.${section} ] && groff_file="./${command}.${section}"
+ [ -f ./${command}.${section}.gz ] && groff_file="./${command}.${section}.gz" && zipped=true
+ # if we found the file
+ if [ -f $groff_file ];then
+ # unpack it, if needed
+ [ $zipped = true ] && zcat $groff_file > /tmp/unzipped && groff_file=/tmp/unzipped
+ # now lets read the man page and exit
+ groff -T utf8 -man $groff_file | $pager && exit 0
+ fi
+ done
+fi
+
+# if we already have the man page as plain text, just print it and exit
+[ "$1" != "-H" ] && [ "$2" != "--url" ] && [ -f "$manpage_file" ] && cat "$manpage_file" | $pager && exit 0
+
+# set a list of urls to check:
+
+# these man pages cover the correct versions of the program you have installed,
+# for the OS you're actually using (if using an Ubuntu or Debian based pup)
+if [ "$DISTRO_BINARY_COMPAT" = "ubuntu" ];then
+ URLS="https://manpages.ubuntu.com/manpages/${DISTRO_COMPAT_VERSION}/man${section}/${command}.${section}.html"
+elif [ "$DISTRO_BINARY_COMPAT" = "debian" ];then
+ URLS="https://manpages.debian.org/${DISTRO_COMPAT_VERSION}/${command}/${command}.${section}.en.html"
+fi
+
+# add the rest
+URLS="$URLS
+http://man.he.net/?topic=${command}&section=${section}
+http://manpages.org/${command}/${section}
+https://linux.die.net/man/${section}/${command}
+https://www.mankier.com/${section}/${command}
+https://man7.org/linux/man-pages/man${section}/${command}.${section}.html
+http://manpages.org/${command}
+http://man.he.net/?topic=${command}&section=all
+https://ss64.com/bash/${command}.html
+"
+# for each url in the list
+for url in ${URLS}
+do
+ # skip any empty urls
+ [ "$url" != "" ] || continue
+ [ "$url" != " " ] || continue
+
+ # crawl the url
+ wget --timeout=2 --spider -S -o /tmp/"$command".html "$url"
+
+ # get the status code
+ grep -m1 'HTTP/[1-3].[0-9] [0-9][0-9][0-9]' /tmp/"$command".html | grep -E '200 OK' > /tmp/response
+
+ # if HTTP status not 200, skip this url
+ grep -q -m1 "200" /tmp/response || continue
+
+ # print the URL if --url given
+ [ "$2" = "--url" ] && echo "$url" && exit 0
+
+ # grab the URL contents as plain text, put it into a file
+ timeout 2 $htmlpager "$url" | prettifier "$url" > "$manpage_file"
+
+ # if file is empty, remove it, skip this url
+ [ ! -s "$manpage_file" ] && rm "$manpage_file" && continue
+
+ # check if we if we got a "not found" page
+ notfound=false
+ grep -qiE "^Couldn|Hmmm|Invalid characters|No matches for \"|t found manual page under category" "$manpage_file" && notfound=true
+
+ # if we DID get a "not found" page, delete the man page, skip this url
+ [ "$notfound" = true ] && rm "$manpage_file" && continue
+
+ # if man page not a file, skip this url
+ [ ! -f "$manpage_file" ] && continue
+
+ # if -H was given, print it out as HTML (like GNU man)
+ if [ "$1" = "-H" ] ;then
+ $browser "$url"
+ fi
+
+ #
+ # add a footer to the man page
+ #
+ echo >> "$manpage_file"
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >> "$manpage_file"
+ echo >> "$manpage_file"
+ echo "Generated by https://github.com/sc0ttj/w3m-manpage" >> "$manpage_file"
+ echo >> "$manpage_file"
+ echo "Source URL $url" >> "$manpage_file"
+ echo >> "$manpage_file"
+
+ # man page created, dont need to do another url
+ break
+done
+
+# if we still did not _create_ a file, see if we have local
+# matching ones, in a different section
+if [ ! -f "$manpage_file" ];then
+ local_pages=$(ls $HOME/.w3m-manpages | grep "${command}.")
+ if [ "$local_pages" != "" ];then
+ if [ $(echo "$local_pages" | wc -l) = 1 ];then
+ echo
+ echo "Loading $local_pages" | tr -d '\n'
+ echo
+ sleep 2
+ manpage_file="$HOME/.w3m-manpages/$local_pages"
+ elif [ $(echo "$local_pages" | wc -l) -ge 2 ];then
+ echo
+ echo "Did you mean any of these?"
+ echo
+ echo "$local_pages"
+ exit 1
+ fi
+ fi
+fi
+
+# if we have a man page, and didnt already print the html, print it here
+[ "$1" != "-H" ] && [ -f "$manpage_file" ] \
+ && cat "$manpage_file" | $pager && exit 0
+
+# if _still_ nothing, try download it online from the next section
+if [ ! -f "$manpage_file" ];then
+ if [ -f /tmp/man_loopcount ] && [ $(wc -l /tmp/man_loopcount | cut -f1 -d' ') -ge 8 ];then
+ rm /tmp/man_loopcount
+ exit 1
+ fi
+ next_section=$(($section + 1))
+ [ $next_section -eq 9 ] && next_section=1
+ echo -n "."
+ echo "." >> /tmp/man_loopcount
+ exec $0 $next_section $command
+ retval=$?
+ [ $retval -eq 0 ] && rm /tmp/manprogress
+ echo
+fi
+
+man="$old_man"
diff --git a/.local/bin/web/ytf b/.local/bin/web/ytf
new file mode 100755
index 0000000..57b4af2
--- /dev/null
+++ b/.local/bin/web/ytf
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$1" in
+ '') echo "ytf - download media using youtube config file\nUSAGE: ytf <FILE> [OPTION]..." >&2; exit 1 ;;
+ *.ytd) yt-dlp --config "$@" --config ~/.config/yt-dlp/videos.conf ;;
+ *.ytp) yt-dlp --config "$@" --config ~/.config/yt-dlp/playlist.conf ;;
+ *.ytps) yt-dlp --config "$@" --config ~/.config/yt-dlp/sequenced-playlist.conf ;;
+ *.ytc) yt-dlp --config "$@" --config ~/.config/yt-dlp/channel.conf ;;
+ *) echo "ytf: $1: config file not understood"; exit 1 ;;
+esac
diff --git a/.local/bin/web/ytplaylist b/.local/bin/web/ytplaylist
new file mode 100755
index 0000000..7bc9026
--- /dev/null
+++ b/.local/bin/web/ytplaylist
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Useful when creating a directory of videos sequenced as per a youtube
+# playlist.
+# Run this script from from the root of a directory that contains all the media
+# and metadata files.
+# The playlist file is expected to be in 'playlist' directory within the root
+# with .pl.txt extension. (playlist/PLAYLIST_NAME.pl.txt)
+# The new playlist directory will be created in the current directory i.e. the
+# root if no other destination is passed as the second argument.
+
+case "$1" in
+ '') echo "ytplaylist - build a directory of sequenced videos using a playlist file\n
+USAGE:\n\tytplaylist <PLAYLIST_FILE> [DESTINATION_DIR] " >&2; exit ;;
+ playlist/*.pl.txt) ;;
+ *)
+ printf "%s" "Unconventional file path, contniue? [y/N] "
+ read -r ans
+ case "$ans" in y) ;; *) exit 1 ;; esac
+ ;;
+esac
+
+playlist="$(readlink -f $1)"
+i=1
+fpl "$playlist" | while read -r file; do
+ if [ -z "$file" ]; then
+ i=$(( $i + 1 ))
+ continue
+ fi
+ dir="$(dirname "$file")"
+ base="$(basename "$file")"
+ rsync -Pru --mkpath "$file" \
+ "${2:-$(basename "${playlist%.pl.txt}")}/${dir#$(readlink -f "$PWD")}/$(printf "%02d" "$i") $base"
+done
diff --git a/.local/bin/web/ytv b/.local/bin/web/ytv
new file mode 100755
index 0000000..c6e9eec
--- /dev/null
+++ b/.local/bin/web/ytv
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+yt-dlp "$@" --config ~/.config/yt-dlp/videos.conf