summaryrefslogtreecommitdiffstats
path: root/public/.local
diff options
context:
space:
mode:
authorMitsuo Tokumori <[email protected]>2024-09-11 04:25:38 +0900
committerMitsuo Tokumori <[email protected]>2024-09-11 04:25:38 +0900
commit37ff7062874b72bafa99afe661f42653565ed511 (patch)
tree60372bf7fdb94c9034c7d1cc5a17cd7df526c4fc /public/.local
parentdca319b8d9d221f1aaf3a00ee457d202096c66ac (diff)
downloaddotfiles-37ff7062874b72bafa99afe661f42653565ed511.tar.gz
dotfiles-37ff7062874b72bafa99afe661f42653565ed511.tar.bz2
dotfiles-37ff7062874b72bafa99afe661f42653565ed511.zip
RESTRUCTURE. Replicate relative paths in public/
Diffstat (limited to 'public/.local')
-rw-r--r--public/.local/bin/README.txt17
-rwxr-xr-xpublic/.local/bin/audio_control.sh37
-rwxr-xr-xpublic/.local/bin/brightness_control.sh17
-rwxr-xr-xpublic/.local/bin/build-latex.sh21
-rwxr-xr-xpublic/.local/bin/dmenu-webshortcuts.sh93
-rwxr-xr-xpublic/.local/bin/input_control.sh62
-rwxr-xr-xpublic/.local/bin/laptop-backup.sh38
-rwxr-xr-xpublic/.local/bin/laptop-xinput_setup.sh13
-rwxr-xr-xpublic/.local/bin/laptop-xrandr.sh23
-rwxr-xr-xpublic/.local/bin/lp1-unzip_deletebinaries_zip.sh20
-rwxr-xr-xpublic/.local/bin/myfile-handler.sh7
-rwxr-xr-xpublic/.local/bin/network_control.sh53
-rwxr-xr-xpublic/.local/bin/ocrthis.sh20
-rwxr-xr-xpublic/.local/bin/rename_pictures.sh16
-rwxr-xr-xpublic/.local/bin/sb-audio35
-rwxr-xr-xpublic/.local/bin/sb-battery37
-rwxr-xr-xpublic/.local/bin/sb-input9
-rwxr-xr-xpublic/.local/bin/sb-network52
-rwxr-xr-xpublic/.local/bin/scan_loop.sh33
-rwxr-xr-xpublic/.local/bin/screenshot.sh21
-rwxr-xr-xpublic/.local/bin/screenshot_ocr.sh29
-rwxr-xr-xpublic/.local/bin/setbg.sh9
-rwxr-xr-xpublic/.local/bin/setup_default_apps.sh31
-rwxr-xr-xpublic/.local/bin/updatewebsite.sh9
24 files changed, 702 insertions, 0 deletions
diff --git a/public/.local/bin/README.txt b/public/.local/bin/README.txt
new file mode 100644
index 0000000..280b362
--- /dev/null
+++ b/public/.local/bin/README.txt
@@ -0,0 +1,17 @@
+My Linux executable scripts.
+
+NOTES
+* Beware of not leaking personal information
+
+I also use other people's awesome scrips. I store them in `~/code` and then
+slink the ones I use in `~/.local/bin`.
+
+NOTATION
+(notation is messed up, I'd be better if only used dashed prefixes)
+* All scripts here should end in ".sh"
+* `laptop-*` scripts might only work on my current machine
+* `sb-*` scripts are meant to be called by dwmblocks
+* `*_control` scripts are used in conjunction with xbindkeys(1) and `sb-*`
+ See also:
+ https://github.com/LukeSmithxyz/voidrice/tree/master/.local/bin/statusbar
+ https://github.com/LukeSmithxyz/dwmblocks/blob/master/config.h
diff --git a/public/.local/bin/audio_control.sh b/public/.local/bin/audio_control.sh
new file mode 100755
index 0000000..a257120
--- /dev/null
+++ b/public/.local/bin/audio_control.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+delta=${2:-10}
+signal=10
+
+# signal dwmblocks to update volume block
+send_signal() {
+ pkill -RTMIN+$signal dwmblocks
+}
+
+# WIP: change default sink (speaker). E.g., when connecting HDMI.
+change_sink() {
+ pactl list sinks | grep "Name:"
+ # Use tab completion if set up interactively
+ pactl "set-default-sink alsa_output.pci-0000_05_00.6.analog-stereo"
+}
+
+case $1 in
+ inc) pactl set-sink-volume @DEFAULT_SINK@ +$delta% ;;
+ dec) pactl set-sink-volume @DEFAULT_SINK@ -$delta% ;;
+ micinc) pactl set-source-volume @DEFAULT_SOURCE@ +$delta% ;;
+ micdec) pactl set-source-volume @DEFAULT_SOURCE@ -$delta% ;;
+ mutetoggle) pactl set-sink-mute @DEFAULT_SINK@ toggle ;;
+ deafentoggle) pactl set-source-mute @DEFAULT_SOURCE@ toggle ;;
+ *)
+ echo Speaker:
+ pactl get-sink-volume @DEFAULT_SINK@
+ pactl get-sink-mute @DEFAULT_SINK@
+ echo -e "\nMic:"
+ pactl get-source-volume @DEFAULT_SOURCE@
+ pactl get-source-mute @DEFAULT_SOURCE@
+ echo -e "\nApplications:"
+ pactl list sink-inputs | grep -e 'Sink Input' -e 'application.name' -e 'Volume:'
+ ;;
+esac
+
+send_signal
diff --git a/public/.local/bin/brightness_control.sh b/public/.local/bin/brightness_control.sh
new file mode 100755
index 0000000..13345d7
--- /dev/null
+++ b/public/.local/bin/brightness_control.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+delta=${2:-10}
+signal=11
+
+# signal dwmblocks to update block
+send_signal() {
+ pkill -RTMIN+$signal dwmblocks
+}
+
+case $1 in
+ inc) xbacklight -inc $delta ;;
+ dec) xbacklight -dec $delta ;;
+ *) xbacklight -get ;;
+esac
+
+send_signal
diff --git a/public/.local/bin/build-latex.sh b/public/.local/bin/build-latex.sh
new file mode 100755
index 0000000..7048246
--- /dev/null
+++ b/public/.local/bin/build-latex.sh
@@ -0,0 +1,21 @@
+# Build single latex file using xelatex
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $(basename "$0") FILE"
+ exit 1
+fi
+
+cleanup() {
+ # cleanup of auxiliary files
+ rm -f *.aux *.fls *.fdb_latexmk
+ # rm *.log
+}
+
+xelatex $1 || exit # Initial compilation
+#bibtex # Bibliography tool
+#xelatex $1 || exit # Incorporate bibliography changes
+xelatex $1 || exit # Fix cross-references
+#xelatex $1 || exit # 4th run just to be safe
+cleanup
+echo "## Mispelled words:"
+pdftotext "${1%.tex}.pdf" - | hunspell -d en_US -i utf-8 -a | sort | uniq
diff --git a/public/.local/bin/dmenu-webshortcuts.sh b/public/.local/bin/dmenu-webshortcuts.sh
new file mode 100755
index 0000000..e1d233c
--- /dev/null
+++ b/public/.local/bin/dmenu-webshortcuts.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+# Use dmenu and user-defined web shorcuts to query websites faster.
+#
+# This script tries to mimic Krunner Web Search Keywords functionality.
+# See: https://userbase.kde.org/Plasma/Krunner#Browse_websites
+#
+# TODO: Integrate it to dmenu_run (so that this script doens't require a
+# dedicated keybinding)
+#
+# Mitsuo
+# 2023-11-23
+
+input=$(echo "" | dmenu -p 'wp:Hello World')
+## Set Internal Field Separator, save separated fields as an array in $CMD (-a),
+## don't allow backslashes to escape any characters (-r). Feed $input as stdin.
+#IFS=':' read -ra CMD <<< "$input"
+#keyword=${CMD[0]}
+#search_term=${CMD[1]}
+keyword="${input%%:*}"
+search_term="${input#*:}"
+
+# Define web shortcuts here
+case "$keyword" in
+ # Search
+ "dd") xdg-open "https://duckduckgo.com/?t=h_&q=${search_term// /+}" ;;
+ "gg") xdg-open "https://www.google.com/search?q=$search_term" ;;
+ "bing") xdg-open "https://www.bing.com/search?q=${search_term// /+}" ;;
+ "metac") xdg-open "https://www.metacrawler.com/serp?q=${search_term// /+}" ;;
+
+ # Finance
+ "ggf") xdg-open "https://www.google.com/finance/quote/$search_term?window=1Y" ;;
+ "yf") xdg-open "https://finance.yahoo.com/quote/$search_term" ;;
+ "bb") xdg-open "https://www.bloomberg.com/quote/$search_term" ;;
+
+ # Maps
+ "ggm") xdg-open "https://www.google.com/maps/search/${search_term// /+}" ;;
+ "osm") xdg-open "https://www.openstreetmap.org/search?query=$search_term" ;;
+
+ # Reference
+ "wp") xdg-open "https://en.wikipedia.org/wiki/${search_term// /_}" ;;
+ "wt") xdg-open "https://en.wiktionary.org/wiki/${search_term// /_}" ;;
+ "wv") xdg-open "https://en.wikivoyage.org/wiki/${search_term// /_}" ;;
+ "scholar") xdg-open "https://scholar.google.com/scholar?hl=en&q=${search_query// /+}" ;;
+ "arxiv") xdg-open "https://arxiv.org/search/?query=${search_query// /+}" ;;
+
+ # Computer
+ "arch") xdg-open "https://wiki.archlinux.org/index.php?search=${search_term// /+}" ;;
+ "aur") xdg-open "https://aur.archlinux.org/packages?O=0&K=${search_term// /+}" ;;
+ "so") xdg-open "https://stackoverflow.com/search?q=${search_term// /+}" ;;
+ "gh") xdg-open "https://github.com/search?q=${search_term// /+}&type=repositories" ;;
+ "gl") xdg-open "https://about.gitlab.com/search?searchText=$search_term" ;;
+ "pypi") xdg-open "https://pypi.org/search/?q=${search_term// /+}&o=" ;;
+ "npm") xdg-open "https://www.npmjs.com/search?q=${search_term// /+}" ;;
+
+ # Media
+ "yt") xdg-open "https://www.youtube.com/results?search_query=$search_term" ;;
+ "vm") xdg-open "https://vimeo.com/search?q=$search_term" ;;
+ "sp") xdg-open "https://open.spotify.com/search/$search_term" ;;
+ "sc") xdg-open "https://soundcloud.com/search?q=$search_term" ;;
+ "dz") xdg-open "https://www.deezer.com/search/$search_term" ;;
+ "imdb") xdg-open "https://www.imdb.com/find/?q=$search_term" ;;
+
+ # Social Media
+ "x") xdg-open "https://x.com/search?q=$search_term&src=typed_query" ;;
+ "rd") xdg-open "https://duckduckgo.com/?t=h_&q=site%3Areddit.com+${search_term// /+}&ia=web" ;;
+ "ig") xdg-open "https://duckduckgo.com/?q=site%3Ainstagram.com+${search_term// /+}&ia=web" ;;
+ "fb") xdg-open "https://duckduckgo.com/?q=site%3Afacebook.com+${search_term// /+}&ia=web" ;;
+
+ # Shopping
+ "amzn") xdg-open "https://www.amazon.com/s?k=${search_term// /+}" ;;
+ "amznjp") xdg-open "https://www.amazon.co.jp/s?k=${search_term// /+}" ;;
+ "ebay") xdg-open "https://www.ebay.com/sch/i.html?_nkw=${search_term// /+}" ;;
+
+ # Utilities
+ "ggt") xdg-open "https://translate.google.com/?sl=auto&tl=en&text=$search_term&op=translate" ;;
+ "en2es") xdg-open "https://www.wordreference.com/es/translation.asp?tranword=$search_term" ;;
+ "es2en") xdg-open "https://www.wordreference.com/es/en/translation.asp?spen=$search_term" ;;
+ "en2de") xdg-open "https://www.wordreference.com/es/en/translation.asp?spen=$search_term" ;;
+ "de2en") xdg-open "https://www.wordreference.com/deen/$search_term" ;;
+ "jisho") xdg-open "https://jisho.org/search/$search_term" ;;
+ "rae") xdg-open "https://dle.rae.es/?w=$search_term" ;;
+
+ # Mitsuo
+ "pw") xdg-open "http://wiki.pulse15/index.php?search=${search_term// /+}" ;;
+ "factorio") xdg-open "https://wiki.factorio.com/${search_term// /_}" ;;
+ "dst") xdg-open "https://dontstarve.wiki.gg/wiki/${search_term// /_}" ;;
+ "mc") xdg-open "https://minecraft.wiki/w/${search_term// /_}" ;;
+ "terraria") xdg-open "https://terraria.wiki.gg/wiki/${search_term// /_}" ;;
+
+ *) exit 1 ;;
+esac
+
diff --git a/public/.local/bin/input_control.sh b/public/.local/bin/input_control.sh
new file mode 100755
index 0000000..f63de3b
--- /dev/null
+++ b/public/.local/bin/input_control.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# Use either X keyboard extension layouts (setxkbmap), or fcitx (or both).
+#
+# At first I configured this to use setxkbmap, it works fine.
+#
+# fcitx already provides keybindings, but I wanted to display
+# the current input method in dwmblocks immediatly. So I'm
+# adding such support through fcitx5-remote.
+
+signal=20
+
+# signal dwmblocks to update block
+send_signal() {
+ pkill -RTMIN+$signal dwmblocks
+}
+
+# Cycle X keyboard extension layouts
+cycle_layouts() {
+ layouts=(us latam) # X keyboard extension
+ STATE_FILE="$XDG_STATE_HOME/keyboard_layout_state"
+
+ if [ -f "$STATE_FILE" ]; then
+ index=$(cat "$STATE_FILE")
+ else
+ index=0
+ fi
+ next_index=$(( (index + 1) % ${#layouts[@]} ))
+ echo $next_index > "$STATE_FILE"
+
+ setxkbmap ${layouts[$index]}
+}
+
+fcitx_control() {
+ # For this to correctly reflect the state of the system "Share Input State"
+ # should be set to "All" in fcitx5-configtool.
+
+ case $1 in
+ en)
+ fcitx5-remote -c # Closed
+ fcitx5-remote -g Default
+ ;;
+ es)
+ fcitx5-remote -c # Closed
+ fcitx5-remote -g Spanish
+ ;;
+ ja)
+ fcitx5-remote -g Default
+ fcitx5-remote -o # Open
+ ;;
+ *)
+ fcitx5-remote -q #
+ fcitx5-remote -n
+ fcitx5-remote
+ ;;
+ esac
+}
+
+#cycle_layouts
+fcitx_control $1
+
+send_signal
diff --git a/public/.local/bin/laptop-backup.sh b/public/.local/bin/laptop-backup.sh
new file mode 100755
index 0000000..a22c179
--- /dev/null
+++ b/public/.local/bin/laptop-backup.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Fast backup using rsync
+
+if [ $# -ne 2 ]; then
+ echo "Usage: $(basename "$0") /dev/sdX backup"
+ exit 1
+fi
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "This script must be run as root."
+ exit 1
+fi
+
+rsync_options="-auvP --delete"
+device=$1
+name=$2
+
+# Note: `name` (nor `device`) should not contain spaces
+
+cryptsetup open --type luks $device $name
+if [ $? -ne 0 ]; then
+ # bad device
+ exit 1
+fi
+mount /dev/mapper/$name /mnt/$name
+# TODO: stop backing up /var. Backup is just for Postgres and Mediawiki.
+# `/var` is used by too many applications. Specialy pacman that clutters it
+# with cached binaries.
+rsync $rsync_options /var /mnt/$name # <10G
+rsync $rsync_options /home /mnt/$name # <900G
+rsync $rsync_options /etc /mnt/$name # <20M
+echo "Backup complete."
+df -h #| grep -E "${name}|var|home|etc"
+umount /mnt/$name
+cryptsetup close $name
+
+echo "All done. Check \`$ lsblk\` before unplugging the storage device."
diff --git a/public/.local/bin/laptop-xinput_setup.sh b/public/.local/bin/laptop-xinput_setup.sh
new file mode 100755
index 0000000..e471869
--- /dev/null
+++ b/public/.local/bin/laptop-xinput_setup.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# See https://wiki.archlinux.org/title/Libinput
+
+#xinput list
+#xinput list-props
+
+pulse15() {
+ xinput set-prop "UNIW0001:00 093A:0255 Touchpad" "libinput Tapping Enabled" 1
+ #xinput set-prop "UNIW0001:00 093A:0255 Touchpad" "libinput Tapping Enabled Default" 1
+}
+
+pulse15
diff --git a/public/.local/bin/laptop-xrandr.sh b/public/.local/bin/laptop-xrandr.sh
new file mode 100755
index 0000000..cbe9479
--- /dev/null
+++ b/public/.local/bin/laptop-xrandr.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# See https://wiki.archlinux.org/title/Multihead
+
+# Didn't know how to get the screen name, this works for now
+#screen=$(xrandr | grep "primary" | awk '{ print $1 }')
+# But now how do I get the rest? And the correct order? Maybe it's better just
+# to define "hardcoded" functions and just call them.
+
+simple_2_monitor() {
+ # enable
+ xrandr --output eDP --auto \
+ --output HDMI-A-0 --auto --left-of eDP
+ # disable
+ xrandr --output eDP --auto \
+ --output HDMI-A-0 --off
+}
+
+# Thank you: https://www.maketecheasier.com/how-to-setup-dual-monitors-with-xrandr/
+# xrandr --auto --output HDMI-A-0 --mode 1920x1080 --right-of eDP
+
+#simple_2_monitor
+xrandr --auto --output HDMI-A-0 --mode 1920x1080 --right-of eDP
diff --git a/public/.local/bin/lp1-unzip_deletebinaries_zip.sh b/public/.local/bin/lp1-unzip_deletebinaries_zip.sh
new file mode 100755
index 0000000..3fa4afb
--- /dev/null
+++ b/public/.local/bin/lp1-unzip_deletebinaries_zip.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Script for LP1 labs that are uploaded to Google Drive with binaries and
+# that causes problems with Google Drive's automatic virus scan.
+
+# unzip
+for f in *.zip; do unzip -q "$f"; done
+
+# delete build/ and dist/ directories (virus detection in Google Drive)
+find . -type d -regex '^.*/\(dist\|build\)$' -print0 | xargs -0 rm -r
+
+# zip
+rm *.zip # remove old zip files
+for d in */; do
+ dirname="${d%/}"
+ zip -qr "$dirname.zip" "$d"
+done
+
+# dos2unix (for me)
+find . -type f -iregex ".*\.\(csv\|cpp\|h\|hpp\)" -print0 | xargs -0 dos2unix
diff --git a/public/.local/bin/myfile-handler.sh b/public/.local/bin/myfile-handler.sh
new file mode 100755
index 0000000..40360b8
--- /dev/null
+++ b/public/.local/bin/myfile-handler.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# A script to handle custom protocol
+url="$1"
+
+file_path="${url#myfile://}"
+file_path="${file_path/\~/$HOME}"
+xdg-open "$file_path"
diff --git a/public/.local/bin/network_control.sh b/public/.local/bin/network_control.sh
new file mode 100755
index 0000000..4dc4b38
--- /dev/null
+++ b/public/.local/bin/network_control.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+signal=30
+
+# signal dwmblocks to update network block
+send_signal() {
+ pkill -RTMIN+$signal dwmblocks
+}
+
+toggle_wifi() {
+ status=$(nmcli radio wifi)
+
+ if [ "$status" = "enabled" ]; then
+ nmcli radio wifi off
+ else
+ nmcli radio wifi on
+ fi
+}
+
+# This one is hard because it requires root, and the VPN interface name
+# 2 ways to toggle, using systemctl, or wg-quick(1)
+# This one might be better controled through a `dmenu` script.
+toggle_vpn() {
+ :
+}
+
+toggle_network_quarantine() {
+ # Check the status of all wireless devices
+ if rfkill list | grep -q "Soft blocked: no"; then
+ # not all blocked
+ rfkill block all
+ else
+ # all blocked
+ rfkill unblock all
+ fi
+}
+
+# WIP
+toggle_bluetooth() {
+ :
+}
+
+case $1 in
+ wifitoggle) toggle_wifi ;;
+ vpntoggle) toggle_vpn ;;
+ bluetoothtoggle) toggle_bluetooth ;;
+ isolatetoggle) toggle_network_quarantine ;;
+ *)
+ echo "invalid option :)"
+ ;;
+esac
+
+send_signal
diff --git a/public/.local/bin/ocrthis.sh b/public/.local/bin/ocrthis.sh
new file mode 100755
index 0000000..3010a6a
--- /dev/null
+++ b/public/.local/bin/ocrthis.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Creates and OCR PDF out of an image
+# (OCR limited to printed characters (handwriting or photograph OCR is bad, if
+# any)
+#
+# Alternatively use `tesseract FILE text`
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $(basename "$0") input_file"
+ # (there is `basename` and `dirname`)
+ exit 1
+fi
+
+b="$(basename "$1")"
+convert "$1" "${b}.pdf"
+# TODO: some contrast enhancement step would help. If text has low contrast
+# with background (e.g., blue on black, green on black), then OCR fails.
+ocrmypdf "${b}.pdf" "${b}.ocr.pdf"
+mv -f "${b}.ocr.pdf" "${b}.pdf"
diff --git a/public/.local/bin/rename_pictures.sh b/public/.local/bin/rename_pictures.sh
new file mode 100755
index 0000000..a3f2463
--- /dev/null
+++ b/public/.local/bin/rename_pictures.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Very specific script to bulk rename pictures with some format
+# (complex script for a simple task)
+
+exit # just in case
+
+shopt -s nullglob
+for file in ss_*.png; do
+ date_part="${file:3:8}"
+ time_part="${file:12:6}"
+ new_name="ss-${date_part}T${time_part}0500.png"
+
+ mv "$file" "$new_name"
+done
+shopt -u nullglob
diff --git a/public/.local/bin/sb-audio b/public/.local/bin/sb-audio
new file mode 100755
index 0000000..87ce7d7
--- /dev/null
+++ b/public/.local/bin/sb-audio
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Prints the current volume and 🔇 if muted.
+
+case $BLOCK_BUTTON in
+ 1) setsid -w -f "$TERMINAL" -e pulsemixer; pkill -RTMIN+10 "${STATUSBAR:-dwmblocks}" ;;
+ 2) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle ;;
+ 4) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+ ;;
+ 5) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%- ;;
+ 3) notify-send "📢 Volume module" "\- Shows volume 🔊, 🔇 if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+#vol="$(wpctl get-volume @DEFAULT_AUDIO_SINK@)"
+
+vol="$(pactl get-sink-volume @DEFAULT_SINK@ | awk '/Volume/ { gsub(/%/,"",$5); print $5 }')"
+micvol="$(pactl get-source-volume @DEFAULT_SOURCE@ | awk '/Volume/ { gsub(/%/,"",$5); print $5 }')"
+
+case 1 in
+ $((vol >= 70)) ) icon="🔊" ;;
+ $((vol >= 30)) ) icon="🔉" ;;
+ * ) icon="🔈" ;;
+esac
+
+if pactl get-sink-mute @DEFAULT_SINK@ | grep -q yes; then
+ icon="🔇"
+fi
+
+if pactl get-source-mute @DEFAULT_SOURCE@ | grep -q no; then
+ icon="🎤$micvol%"$icon
+fi
+
+echo "$icon$vol%"
diff --git a/public/.local/bin/sb-battery b/public/.local/bin/sb-battery
new file mode 100755
index 0000000..93cbe08
--- /dev/null
+++ b/public/.local/bin/sb-battery
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Prints all batteries, their percentage remaining and an emoji corresponding
+# to charge status (🔌 for plugged up, 🔋 for discharging on battery, etc.).
+
+case $BLOCK_BUTTON in
+ 3) notify-send "🔋 Battery module" "🔋: discharging
+🛑: not charging
+♻: stagnant charge
+🔌: charging
+⚡: charged
+❗: battery very low!
+- Scroll to change adjust xbacklight." ;;
+ 4) xbacklight -inc 10 ;;
+ 5) xbacklight -dec 10 ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# Loop through all attached batteries and format the info
+for battery in /sys/class/power_supply/BAT?*; do
+ # If non-first battery, print a space separator.
+ [ -n "${capacity+x}" ] && printf " "
+ # Sets up the status and capacity
+ case "$(cat "$battery/status" 2>&1)" in
+ "Full") status="⚡" ;;
+ "Discharging") status="🔋" ;;
+ "Charging") status="🔌" ;;
+ "Not charging") status="🛑" ;;
+ "Unknown") status="♻️" ;;
+ *) exit 1 ;;
+ esac
+ capacity="$(cat "$battery/capacity" 2>&1)"
+ # Will make a warn variable if discharging and low
+ [ "$status" = "🔋" ] && [ "$capacity" -le 25 ] && warn="❗"
+ # Prints the info
+ printf "%s%s%d%%" "$status" "$warn" "$capacity"; unset warn
+done && printf "\\n"
diff --git a/public/.local/bin/sb-input b/public/.local/bin/sb-input
new file mode 100755
index 0000000..4fb1575
--- /dev/null
+++ b/public/.local/bin/sb-input
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+icon="🌐"
+layout="$(setxkbmap -query | grep layout | awk '{print $2}')"
+
+# fcitx state, 0 for close, 1 for inactive, 2 for active
+test $(fcitx5-remote) = 2 && layout="日本語"
+
+echo $icon$layout
diff --git a/public/.local/bin/sb-network b/public/.local/bin/sb-network
new file mode 100755
index 0000000..0bdbe82
--- /dev/null
+++ b/public/.local/bin/sb-network
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+# Prints some network connectivity status in emoji
+
+case $BLOCK_BUTTON in
+ 1) setsid -w -f "$TERMINAL" -e pulsemixer; pkill -RTMIN+10 "${STATUSBAR:-dwmblocks}" ;;
+ 2) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle ;;
+ 4) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+ ;;
+ 5) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%- ;;
+ 3) notify-send "📢 Volume module" "\- Shows volume 🔊, 🔇 if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+
+set_wlan() {
+ nmcli_status=$(nmcli -t -f TYPE,STATE connection show --active)
+ wifi=$(echo $nmcli_status | grep -q "802-11-wireless:activated" && echo "📶")
+ vpn=$(echo $nmcli_status | grep -q "wireguard:activated" && echo "🔒")
+ wlan="$wifi$vpn"
+}
+
+
+set_bt() {
+ # If bluetooth is on, show number of connected devices and their initials
+ if ! bluetoothctl show | grep -q "Powered: yes"; then return; fi
+ ds=$(bluetoothctl devices Connected | cut -d ' ' -f 3-)
+ if [ -z "$ds" ]; then
+ bt=$(echo "🦷")
+ return
+ fi
+ N=$(echo "$ds" | wc -l)
+ ds=$(echo "$ds" | cut -c 1-3 | paste -sd ",")
+ bt=$(echo "🦷$N:$ds")
+}
+
+
+check_network_quarantine() {
+ # If all wireless devices are (software) blocked,
+ # change status bar icon and exit
+ if ! rfkill list | grep -q "Soft blocked: no"; then
+ echo "🗿"
+ exit
+ fi
+}
+
+
+check_network_quarantine
+set_wlan
+set_bt
+echo "$wlan$bt"
diff --git a/public/.local/bin/scan_loop.sh b/public/.local/bin/scan_loop.sh
new file mode 100755
index 0000000..722e63d
--- /dev/null
+++ b/public/.local/bin/scan_loop.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# The scan loop is useful when Automatic Document Feeder (ADF) can't be used
+
+scan_device_uri="hpaio:/net/OfficeJet_Pro_6970?ip=192.168.18.21"
+# ^This HP printer is remarkable. It's been working fine since 2017. I refill
+# the cardridge with UV ink very easily (I've never purchased ink cardridges
+# other than the ones that came with the printer). As of 2023, only the Cyan
+# and Black cardridges/inkjets work but Black&White print is all I need.
+# And the Linux support and CLI interface is amazing.
+
+
+# Automatic Document Feeder
+adf() {
+ hp-scan --mode=color --resolution=300 --size=a4 --adf #--duplex
+}
+
+
+# Scans until terminated with ^C. Saves .png files on CWD.
+flatbed_loop() {
+ echo "Warning: scan loop will run until terminated with Ctrl-C"
+ i=0
+ while true; do
+ # device show with $ hp-info
+ hp-scan --mode=color --size=a4 --device=$scan_device_uri
+ echo "page " $((i + 1)) " done, you have 4 seconds to load next page"
+ sleep 4
+ i=$((expr $i + 1))
+ done
+ # convert *.png output.pdf
+}
+
+flatbed_loop
diff --git a/public/.local/bin/screenshot.sh b/public/.local/bin/screenshot.sh
new file mode 100755
index 0000000..be4a8f9
--- /dev/null
+++ b/public/.local/bin/screenshot.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Takes a screenshot and saves it
+
+# Inspired by Denshi's screenshot script (https://git.denshi.org/Scripts/tree/screenshot).
+# See also https://www.youtube.com/watch?v=uYNTFg3_QaY&t=243s
+
+savepath="$HOME/media/Pictures/Screenshots"
+filename="$HOSTNAME-$(date -Iseconds | tr -d ':-').png"
+
+if [ "$1" == "screen" ]; then
+ # capture the screen determined by the cursor location
+ shotgun -s "$savepath/$filename"
+elif [ "$1" == "screens" ]; then
+ # TODO: This is not currently possible with shotgun 2.5.1
+ :
+else
+ # capture a region of the screen
+ shotgun -g $(hacksaw) "$savepath/$filename"
+fi
+
diff --git a/public/.local/bin/screenshot_ocr.sh b/public/.local/bin/screenshot_ocr.sh
new file mode 100755
index 0000000..d88accf
--- /dev/null
+++ b/public/.local/bin/screenshot_ocr.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Select a region of the screen and perform OCR to it. Save text in clipboard.
+
+savepath="/tmp/screenshot_ocr.sh.d"
+filename="$HOSTNAME-$(date -Iseconds | tr -d ':-').png"
+# German: deu, Spanish: spa, Japanese vertical: jpn_vert
+tesseract_options="-l eng+jpn"
+
+_init() {
+ if [ ! -d "$savepath" ]; then
+ mkdir -p "$savepath"
+ fi
+ cd "$savepath"
+}
+
+_init
+# Screenshot region of screen
+shotgun -g $(hacksaw) "$filename"
+# Exit if previous command was unsuccessful
+test $? -ne 0 && exit
+# Try to scan codes from the image
+zbarimg $filename | xclip -selection "clipboard"
+# Perform OCR and save to clipboard
+tesseract $tesseract_options $filename - | xclip -selection "clipboard"
+rm $filename
+
+# TODO: clean japanese output. If text is 80% japanese characters, then it
+# should not contain spaces around the characters.
diff --git a/public/.local/bin/setbg.sh b/public/.local/bin/setbg.sh
new file mode 100755
index 0000000..78cdb2d
--- /dev/null
+++ b/public/.local/bin/setbg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Sets the background (Suckless setup)
+
+bgfile="$HOME/media/Pictures/Wallpapers/landscapes/japan/Lake_Kawaguchiko_Sakura_Mount_Fuji_3.jpg"
+bgfile2="$HOME/media/Pictures/Wallpapers/mine/IMG_20200706_190712.jpg"
+
+xwallpaper --output eDP --zoom "$bgfile"
+xwallpaper --output HDMI-A-0 --zoom "$bgfile2"
diff --git a/public/.local/bin/setup_default_apps.sh b/public/.local/bin/setup_default_apps.sh
new file mode 100755
index 0000000..9c58b95
--- /dev/null
+++ b/public/.local/bin/setup_default_apps.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# Set defaults for xdg-open
+#
+# For a list of MIME types see https://www.iana.org/assignments/media-types/media-types.xhtml
+
+# Useful commands:
+# xdg-mime query filetype FILE
+# xdg-mime query default MIMETYPE
+
+# File
+#pcmanfm
+
+# Image
+xdg-mime default nsxiv.desktop image/bmp image/gif image/jpeg image/jpg image/png image/tiff image/x-bmp image/x-portable-anymap image/x-portable-bitmap image/x-portable-graymap image/x-tga image/x-xpixmap image/webp image/heic image/svg+xml application/postscript image/jp2 image/jxl image/avif image/heif
+
+# Video
+#xdg-mime default mpv.desktop A_LOT_OF_MIME_TYPES
+
+# Mail
+#thunderbird
+
+# Office
+xdg-mime default org.pwmt.zathura.desktop application/pdf application/postscript image/vnd.djvu application/epub+zip
+#libreoffice
+
+# Text
+xdg-mime default nvim.desktop text/plain
+
+# Net
+xdg-mime default org.qbittorrent.qBittorrent.desktop application/x-bittorrent x-scheme-handler/magnet
diff --git a/public/.local/bin/updatewebsite.sh b/public/.local/bin/updatewebsite.sh
new file mode 100755
index 0000000..71c99b2
--- /dev/null
+++ b/public/.local/bin/updatewebsite.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# This script syncs local files to my VPS
+
+# Thank you: https://unix.stackexchange.com/a/2503/347754
+options="-uvrPs --delete-after --copy-links"
+targetdir="tokumori.xyz:/var/www"
+
+rsync $options /home/mitsuo/mahcode/www/tokumori.xyz $targetdir