summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLibravatar Biswakalyan Bhuyan <biswa@surgot.in> 2022-09-24 12:21:56 +0530
committerLibravatarLibravatar Biswakalyan Bhuyan <biswa@surgot.in> 2022-09-24 12:21:56 +0530
commit86f99da8d08e1f2e290d8ebfd5adb016faff7bac (patch)
tree8f121a2aaa187d8266e20df23ad36262ab051866
downloadbin-86f99da8d08e1f2e290d8ebfd5adb016faff7bac.tar.gz
bin-86f99da8d08e1f2e290d8ebfd5adb016faff7bac.tar.bz2
bin-86f99da8d08e1f2e290d8ebfd5adb016faff7bac.zip
script's
-rw-r--r--__pycache__/clear_comtypes_cache.cpython-310.pycbin0 -> 1303 bytes
-rwxr-xr-xbase588
-rwxr-xr-xbooksplit43
-rwxr-xr-xchardetect8
-rw-r--r--clear_comtypes_cache.py57
-rw-r--r--client_secrets.json1
-rwxr-xr-xcompiler57
-rw-r--r--cron/README.md11
-rwxr-xr-xcron/checkup17
-rwxr-xr-xcron/crontog6
-rwxr-xr-xcron/newsup15
-rwxr-xr-xdisplayselect83
-rwxr-xr-xdmenuhandler21
-rwxr-xr-xdmenumount67
-rwxr-xr-xdmenumountcifs19
-rwxr-xr-xdmenupass6
-rwxr-xr-xdmenurecord123
-rwxr-xr-xdmenuumount44
-rwxr-xr-xdmenuunicode18
-rwxr-xr-xdwm_bar66
-rwxr-xr-xemoji3
-rwxr-xr-xepylint8
-rwxr-xr-xestimator_ckpt_converter8
-rwxr-xr-xext45
-rwxr-xr-xf2py8
-rwxr-xr-xf2py38
-rwxr-xr-xf2py3.108
-rwxr-xr-xflake88
-rwxr-xr-xfonttools8
-rwxr-xr-xget_objgraph54
-rwxr-xr-xgetbib14
-rwxr-xr-xgetkeys5
-rwxr-xr-xgoogle-oauthlib-tool8
-rwxr-xr-xholehe8
-rwxr-xr-xhttpx8
-rwxr-xr-xifinstalled12
-rwxr-xr-ximport_pb_to_tensorboard8
-rwxr-xr-xisort8
-rwxr-xr-xisort-identify-imports8
-rwxr-xr-xlayoutmenu7
-rwxr-xr-xlfub24
-rwxr-xr-xlinkhandler23
-rwxr-xr-xmaimpick14
-rwxr-xr-xmarkdown_py8
-rwxr-xr-xnasad8
-rwxr-xr-xnewword6
-rwxr-xr-xnoisereduce81
-rwxr-xr-xnormalizer8
-rwxr-xr-xnotflix53
-rwxr-xr-xopout13
-rwxr-xr-xotp53
-rwxr-xr-xpauseallmpv10
-rwxr-xr-xpeertubetorrent9
-rwxr-xr-xpodentr7
-rwxr-xr-xprompt8
-rwxr-xr-xpy.test8
-rwxr-xr-xpycodestyle8
-rwxr-xr-xpyflakes8
-rwxr-xr-xpyftmerge8
-rwxr-xr-xpyftsubset8
-rwxr-xr-xpylint8
-rwxr-xr-xpyreverse8
-rwxr-xr-xpyrsa-decrypt8
-rwxr-xr-xpyrsa-encrypt8
-rwxr-xr-xpyrsa-keygen8
-rwxr-xr-xpyrsa-priv2pub8
-rwxr-xr-xpyrsa-sign8
-rwxr-xr-xpyrsa-verify8
-rwxr-xr-xpytest8
-rwxr-xr-xqndl12
-rwxr-xr-xqueueandnotify14
-rwxr-xr-xrandompass31
-rwxr-xr-xremaps11
-rwxr-xr-xrotdir12
-rwxr-xr-xrssadd18
-rwxr-xr-xsamedir10
-rwxr-xr-xsaved_model_cli8
-rwxr-xr-xset_wallpaper18
-rwxr-xr-xsetbg33
-rwxr-xr-xshortcuts43
-rwxr-xr-xslider126
-rwxr-xr-xsocialscan8
-rwxr-xr-xstatusbar/sb-battery37
-rwxr-xr-xstatusbar/sb-clock29
-rwxr-xr-xstatusbar/sb-cpu12
-rwxr-xr-xstatusbar/sb-cpubars44
-rwxr-xr-xstatusbar/sb-disk23
-rwxr-xr-xstatusbar/sb-doppler260
-rwxr-xr-xstatusbar/sb-forecast35
-rwxr-xr-xstatusbar/sb-help-icon17
-rwxr-xr-xstatusbar/sb-internet26
-rwxr-xr-xstatusbar/sb-iplocate10
-rwxr-xr-xstatusbar/sb-kbselect16
-rwxr-xr-xstatusbar/sb-mailbox20
-rwxr-xr-xstatusbar/sb-memory12
-rwxr-xr-xstatusbar/sb-moonphase37
-rwxr-xr-xstatusbar/sb-mpdup8
-rwxr-xr-xstatusbar/sb-music19
-rwxr-xr-xstatusbar/sb-nettraf29
-rwxr-xr-xstatusbar/sb-news17
-rwxr-xr-xstatusbar/sb-pacpackages29
-rwxr-xr-xstatusbar/sb-popupgrade9
-rwxr-xr-xstatusbar/sb-price50
-rwxr-xr-xstatusbar/sb-tasks20
-rwxr-xr-xstatusbar/sb-torrent27
-rwxr-xr-xstatusbar/sb-volume30
-rwxr-xr-xswitch_audio14
-rwxr-xr-xsymilar8
-rwxr-xr-xsysact26
-rwxr-xr-xsystem_action16
-rwxr-xr-xtag67
-rwxr-xr-xtd-toggle12
-rwxr-xr-xtensorboard8
-rwxr-xr-xtexclear16
-rwxr-xr-xtf_upgrade_v28
-rwxr-xr-xtflite_convert8
-rwxr-xr-xtoco8
-rwxr-xr-xtoco_from_protos8
-rwxr-xr-xtorwrap7
-rwxr-xr-xtqdm8
-rwxr-xr-xtransadd9
-rwxr-xr-xttx8
-rwxr-xr-xtutorialvids26
-rwxr-xr-xundill22
-rwxr-xr-xunix26
-rw-r--r--upload.py181
-rwxr-xr-xwheel8
-rwxr-xr-xytplay4
128 files changed, 3009 insertions, 0 deletions
diff --git a/__pycache__/clear_comtypes_cache.cpython-310.pyc b/__pycache__/clear_comtypes_cache.cpython-310.pyc
new file mode 100644
index 0000000..6eb21b9
--- /dev/null
+++ b/__pycache__/clear_comtypes_cache.cpython-310.pyc
Binary files differ
diff --git a/base58 b/base58
new file mode 100755
index 0000000..1e291f0
--- /dev/null
+++ b/base58
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from base58.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/booksplit b/booksplit
new file mode 100755
index 0000000..69e4f36
--- /dev/null
+++ b/booksplit
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# Requires ffmpeg
+
+[ ! -f "$2" ] && printf "The first file should be the audio, the second should be the timecodes.\\n" && exit
+
+echo "Enter the album/book title:"; read -r booktitle
+echo "Enter the artist/author:"; read -r author
+echo "Enter the publication year:"; read -r year
+
+inputaudio="$1"
+ext="${1#*.}"
+
+# Get a safe file name from the book.
+escbook="$(echo "$booktitle" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")"
+
+! mkdir -p "$escbook" &&
+ echo "Do you have write access in this directory?" &&
+ exit 1
+
+# Get the total number of tracks from the number of lines.
+total="$(wc -l < "$2")"
+
+cmd="ffmpeg -i \"$inputaudio\" -nostdin -y"
+
+while read -r x;
+do
+ end="$(echo "$x" | cut -d' ' -f1)"
+ file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext"
+ if [ -n "$start" ]; then
+ cmd="$cmd -metadata artist=\"$author\" -metadata title=\"$title\" -metadata album=\"$booktitle\" -metadata year=\"$year\" -metadata track=\"$track\" -metadata total=\"$total\" -ss \"$start\" -to \"$end\" -vn -c:a copy \"$file\" "
+ fi
+ title="$(echo "$x" | cut -d' ' -f2-)"
+ esctitle="$(echo "$title" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")"
+ track="$((track+1))"
+ start="$end"
+done < "$2"
+
+# Last track must be added out of the loop.
+file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext"
+cmd="$cmd -metadata artist=\"$author\" -metadata title=\"$title\" -metadata album=\"$booktitle\" -metadata year=\"$year\" -metadata track=\"$track\" -ss \"$start\" -vn -c copy \"$file\""
+
+eval "$cmd"
diff --git a/chardetect b/chardetect
new file mode 100755
index 0000000..09f9ed1
--- /dev/null
+++ b/chardetect
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from chardet.cli.chardetect import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/clear_comtypes_cache.py b/clear_comtypes_cache.py
new file mode 100644
index 0000000..bd743cd
--- /dev/null
+++ b/clear_comtypes_cache.py
@@ -0,0 +1,57 @@
+import os
+import sys
+import shutil
+
+def get_next_cache_dir():
+ work_dir = os.getcwd()
+ try:
+ # change working directory to avoid import from local folder
+ # during installation process
+ os.chdir(os.path.dirname(sys.executable))
+ import comtypes.client
+ return comtypes.client._code_cache._find_gen_dir()
+ except ImportError:
+ return None
+ finally:
+ os.chdir(work_dir)
+
+
+def _remove(directory):
+ shutil.rmtree(directory)
+ print('Removed directory "%s"' % directory)
+
+
+def remove_directory(directory, silent):
+ if directory:
+ if silent:
+ _remove(directory)
+ else:
+ try:
+ confirm = raw_input('Remove comtypes cache directories? (y/n): ')
+ except NameError:
+ confirm = input('Remove comtypes cache directories? (y/n): ')
+ if confirm.lower() == 'y':
+ _remove(directory)
+ else:
+ print('Directory "%s" NOT removed' % directory)
+ return False
+ return True
+
+
+if len(sys.argv) > 1 and "-y" in sys.argv[1:]:
+ silent = True
+else:
+ silent = False
+
+
+# First iteration may get folder with restricted rights.
+# Second iteration always gets temp cache folder (writable for all).
+directory = get_next_cache_dir()
+removed = remove_directory(directory, silent)
+
+if removed:
+ directory = get_next_cache_dir()
+
+ # do not request the second confirmation
+ # if the first folder was already removed
+ remove_directory(directory, silent=removed)
diff --git a/client_secrets.json b/client_secrets.json
new file mode 100644
index 0000000..7a935fc
--- /dev/null
+++ b/client_secrets.json
@@ -0,0 +1 @@
+{"installed":{"client_id":"475299845441-6vo5r5d5fo4se00aanoc9b3oi0416ljc.apps.googleusercontent.com","project_id":"my-youtube-api-355917","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}} \ No newline at end of file
diff --git a/compiler b/compiler
new file mode 100755
index 0000000..67992be
--- /dev/null
+++ b/compiler
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# This script will compile or run another finishing operation on a document. I
+# have this script run via vim.
+#
+# Compiles .tex. groff (.mom, .ms), .rmd, .md, .org. Opens .sent files as sent
+# presentations. Runs scripts based on extension or shebang.
+#
+# Note that .tex files which you wish to compile with XeLaTeX should have the
+# string "xelatex" somewhere in a comment/command in the first 5 lines.
+
+file=$(readlink -f "$1")
+dir=${file%/*}
+base="${file%.*}"
+ext="${file##*.}"
+
+cd "$dir" || exit 1
+
+textype() { \
+ command="pdflatex"
+ ( head -n5 "$file" | grep -qi 'xelatex' ) && command="xelatex"
+ $command --output-directory="$dir" "$base" &&
+ grep -qi addbibresource "$file" &&
+ biber --input-directory "$dir" "$base" &&
+ $command --output-directory="$dir" "$base" &&
+ $command --output-directory="$dir" "$base"
+}
+
+case "$ext" in
+ # Try to keep these cases in alphabetical order.
+ [0-9]) preconv "$file" | refer -PS -e | groff -mandoc -T pdf > "$base".pdf ;;
+ c) cc "$file" -o "$base" && "$base" ;;
+ cpp) g++ "$file" -o "$base" && "$base" ;;
+ cs) mcs "$file" && mono "$base".exe ;;
+ go) go run "$file" ;;
+ h) sudo make install ;;
+ java) javac -d classes "$file" && java -cp classes "${1%.*}" ;;
+ m) octave "$file" ;;
+ md) if [ -x "$(command -v lowdown)" ]; then
+ lowdown --parse-no-intraemph "$file" -Tms | groff -mpdfmark -ms -kept > "$base".pdf
+ elif [ -x "$(command -v groffdown)" ]; then
+ groffdown -i "$file" | groff > "$base.pdf"
+ else
+ pandoc -t ms --highlight-style=kate -s -o "$base".pdf "$file"
+ fi ; ;;
+ mom) preconv "$file" | refer -PS -e | groff -mom -kept -T pdf > "$base".pdf ;;
+ ms) preconv "$file" | refer -PS -e | groff -me -ms -kept -T pdf > "$base".pdf ;;
+ org) emacs "$file" --batch -u "$USER" -f org-latex-export-to-pdf ;;
+ py) python "$file" ;;
+ [rR]md) Rscript -e "rmarkdown::render('$file', quiet=TRUE)" ;;
+ rs) cargo build ;;
+ sass) sassc -a "$file" "$base.css" ;;
+ scad) openscad -o "$base".stl "$file" ;;
+ sent) setsid -f sent "$file" 2>/dev/null ;;
+ tex) textype "$file" ;;
+ *) sed -n '/^#!/s/^#!//p; q' "$file" | xargs -r -I % "$file" ;;
+esac
diff --git a/cron/README.md b/cron/README.md
new file mode 100644
index 0000000..fa0c354
--- /dev/null
+++ b/cron/README.md
@@ -0,0 +1,11 @@
+# Important Note
+
+These cronjobs have components that require information about your current display to display notifications correctly.
+
+When you add them as cronjobs, I recommend you precede the command with commands as those below:
+
+```
+export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u $USER)/bus; export DISPLAY=:0; . $HOME/.zprofile; then_command_goes_here
+```
+
+This ensures that notifications will display, xdotool commands will function and environmental variables will work as well.
diff --git a/cron/checkup b/cron/checkup
new file mode 100755
index 0000000..bd3c634
--- /dev/null
+++ b/cron/checkup
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Syncs repositories and downloads updates, meant to be run as a cronjob.
+
+notify-send "πŸ“¦ Repository Sync" "Checking for package updates..."
+
+sudo pacman -Syyuw --noconfirm || notify-send "Error downloading updates.
+
+Check your internet connection, if pacman is already running, or run update manually to see errors."
+pkill -RTMIN+8 "${STATUSBAR:-dwmblocks}"
+
+if pacman -Qu | grep -v "\[ignored\]"
+then
+ notify-send "🎁 Repository Sync" "Updates available. Click statusbar icon (πŸ“¦) for update."
+else
+ notify-send "πŸ“¦ Repository Sync" "Sync complete. No new packages for update."
+fi
diff --git a/cron/crontog b/cron/crontog
new file mode 100755
index 0000000..5aba5e6
--- /dev/null
+++ b/cron/crontog
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Toggles all cronjobs off/on.
+# Stores disabled crontabs in ~/.consaved until restored.
+
+([ -f "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved ] && crontab - < "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && rm "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && notify-send "πŸ•“ Cronjobs re-enabled.") || ( crontab -l > "${XDG_CONFIG_HOME:-$HOME/.config}"/cronsaved && crontab -r && notify-send "πŸ•“ Cronjobs saved and disabled.")
diff --git a/cron/newsup b/cron/newsup
new file mode 100755
index 0000000..ed266d7
--- /dev/null
+++ b/cron/newsup
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Set as a cron job to check for new RSS entries for newsboat.
+# If newsboat is open, sends it an "R" key to refresh.
+
+/usr/bin/notify-send "πŸ“° Updating RSS feeds..."
+
+pgrep -f newsboat$ && /usr/bin/xdotool key --window "$(/usr/bin/xdotool search --name "^newsboat$")" R && exit
+
+echo πŸ”ƒ > /tmp/newsupdate
+pkill -RTMIN+6 "${STATUSBAR:-dwmblocks}"
+/usr/bin/newsboat -x reload
+rm -f /tmp/newsupdate
+pkill -RTMIN+6 "${STATUSBAR:-dwmblocks}"
+/usr/bin/notify-send "πŸ“° RSS feed update complete."
diff --git a/displayselect b/displayselect
new file mode 100755
index 0000000..f9e8062
--- /dev/null
+++ b/displayselect
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+# A UI for detecting and selecting all displays. Probes xrandr for connected
+# displays and lets user select one to use. User may also select "manual
+# selection" which opens arandr.
+
+twoscreen() { # If multi-monitor is selected and there are two screens.
+
+ mirror=$(printf "no\\nyes" | dmenu -i -p "Mirror displays?")
+ # Mirror displays using native resolution of external display and a scaled
+ # version for the internal display
+ if [ "$mirror" = "yes" ]; then
+ external=$(echo "$screens" | dmenu -i -p "Optimize resolution for:")
+ internal=$(echo "$screens" | grep -v "$external")
+
+ res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | \
+ tail -n 1 | awk '{print $1}')
+ res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | \
+ tail -n 1 | awk '{print $1}')
+
+ res_ext_x=$(echo "$res_external" | sed 's/x.*//')
+ res_ext_y=$(echo "$res_external" | sed 's/.*x//')
+ res_int_x=$(echo "$res_internal" | sed 's/x.*//')
+ res_int_y=$(echo "$res_internal" | sed 's/.*x//')
+
+ scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l)
+ scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l)
+
+ xrandr --output "$external" --auto --scale 1.0x1.0 \
+ --output "$internal" --auto --same-as "$external" \
+ --scale "$scale_x"x"$scale_y"
+ else
+
+ primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary")
+ direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
+ xrandr --output "$primary" --auto --scale 1.0x1.0 --output "$secondary" --"$direction"-of "$primary" --auto --scale 1.0x1.0
+ fi
+ }
+
+morescreen() { # If multi-monitor is selected and there are more than two screens.
+ primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary" | dmenu -i -p "Select secondary display:")
+ direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
+ tertiary=$(echo "$screens" | grep -v "$primary" | grep -v "$secondary" | dmenu -i -p "Select third display:")
+ xrandr --output "$primary" --auto --output "$secondary" --"$direction"-of "$primary" --auto --output "$tertiary" --"$(printf "left\\nright" | grep -v "$direction")"-of "$primary" --auto
+ }
+
+multimon() { # Multi-monitor handler.
+ case "$(echo "$screens" | wc -l)" in
+ 2) twoscreen ;;
+ *) morescreen ;;
+ esac ;}
+
+onescreen() { # If only one output available or chosen.
+ xrandr --output "$1" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "\b$1" | awk '{print "--output", $1, "--off"}' | paste -sd ' ' -)
+ }
+
+postrun() { # Stuff to run to clean up.
+ setbg # Fix background if screen size/arangement has changed.
+ remaps # Re-remap keys if keyboard added (for laptop bases)
+ { killall dunst ; setsid -f dunst ;} >/dev/null 2>&1 # Restart dunst to ensure proper location on screen
+ }
+
+# Get all possible displays
+allposs=$(xrandr -q | grep "connected")
+
+# Get all connected screens.
+screens=$(echo "$allposs" | awk '/ connected/ {print $1}')
+
+# If there's only one screen
+[ "$(echo "$screens" | wc -l)" -lt 2 ] &&
+ { onescreen "$screens"; postrun; notify-send "πŸ’» Only one screen detected." "Using it in its optimal settings..."; exit ;}
+
+# Get user choice including multi-monitor and manual selection:
+chosen=$(printf "%s\\nmulti-monitor\\nmanual selection" "$screens" | dmenu -i -p "Select display arangement:") &&
+case "$chosen" in
+ "manual selection") arandr ; exit ;;
+ "multi-monitor") multimon ;;
+ *) onescreen "$chosen" ;;
+esac
+
+postrun
diff --git a/dmenuhandler b/dmenuhandler
new file mode 100755
index 0000000..3e5055f
--- /dev/null
+++ b/dmenuhandler
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Feed this script a link and it will give dmenu
+# some choice programs to use to open it.
+feed="${1:-$(printf "%s" | dmenu -p 'Paste URL or file path')}"
+
+case "$(printf "Copy URL\\nsxiv\\nsetbg\\nPDF\\nbrowser\\nlynx\\nvim\\nmpv\\nmpv loop\\nmpv float\\nqueue download\\nqueue yt-dlp\\nqueue yt-dlp audio" | dmenu -i -p "Open it with?")" in
+ "Copy URL") echo "$feed" | xclip -selection clipboard ;;
+ mpv) setsid -f mpv -quiet "$feed" >/dev/null 2>&1 ;;
+ "mpv loop") setsid -f mpv -quiet --loop "$feed" >/dev/null 2>&1 ;;
+ "mpv float") setsid -f "$TERMINAL" -e mpv --geometry=+0-0 --autofit=30% --title="mpvfloat" "$feed" >/dev/null 2>&1 ;;
+ "queue yt-dlp") qndl "$feed" >/dev/null 2>&1 ;;
+ "queue yt-dlp audio") qndl "$feed" 'yt-dlp --embed-metadata -icx -f bestaudio/best' >/dev/null 2>&1 ;;
+ "queue download") qndl "$feed" 'curl -LO' >/dev/null 2>&1 ;;
+ PDF) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 ;;
+ sxiv) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 ;;
+ vim) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" && setsid -f "$TERMINAL" -e "$EDITOR" "/tmp/$(echo "$feed" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 ;;
+ setbg) curl -L "$feed" > $XDG_CACHE_HOME/pic ; xwallpaper --zoom $XDG_CACHE_HOME/pic >/dev/null 2>&1 ;;
+ browser) setsid -f "$BROWSER" "$feed" >/dev/null 2>&1 ;;
+ lynx) lynx "$feed" >/dev/null 2>&1 ;;
+esac
diff --git a/dmenumount b/dmenumount
new file mode 100755
index 0000000..3cb1f81
--- /dev/null
+++ b/dmenumount
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# Gives a dmenu prompt to mount unmounted drives and Android phones. If
+# they're in /etc/fstab, they'll be mounted automatically. Otherwise, you'll
+# be prompted to give a mountpoint from already existsing directories. If you
+# input a novel directory, it will prompt you to create that directory.
+
+getmount() { \
+ [ -z "$chosen" ] && exit 1
+ # shellcheck disable=SC2086
+ mp="$(find $1 2>/dev/null | dmenu -i -p "Type in mount point.")" || exit 1
+ test -z "$mp" && exit 1
+ if [ ! -d "$mp" ]; then
+ mkdiryn=$(printf "No\\nYes" | dmenu -i -p "$mp does not exist. Create it?") || exit 1
+ [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp")
+ fi
+ }
+
+mountusb() { \
+ chosen="$(echo "$usbdrives" | dmenu -i -p "Mount which drive?")" || exit 1
+ chosen="$(echo "$chosen" | awk '{print $1}')"
+ sudo -A mount "$chosen" 2>/dev/null && notify-send "πŸ’» USB mounting" "$chosen mounted." && exit 0
+ alreadymounted=$(lsblk -nrpo "name,type,mountpoint" | awk '$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not ( -path *%s -prune ) ",$3}')
+ getmount "/mnt /media /mount /home -maxdepth 5 -type d $alreadymounted"
+ partitiontype="$(lsblk -no "fstype" "$chosen")"
+ case "$partitiontype" in
+ "vfat") sudo -A mount -t vfat "$chosen" "$mp" -o rw,umask=0000;;
+ "exfat") sudo -A mount "$chosen" "$mp" -o uid="$(id -u)",gid="$(id -g)";;
+ *) sudo -A mount "$chosen" "$mp"; user="$(whoami)"; ug="$(groups | awk '{print $1}')"; sudo -A chown "$user":"$ug" "$mp";;
+ esac
+ notify-send "πŸ’» USB mounting" "$chosen mounted to $mp."
+ }
+
+mountandroid() { \
+ chosen="$(echo "$anddrives" | dmenu -i -p "Which Android device?")" || exit 1
+ chosen="$(echo "$chosen" | cut -d : -f 1)"
+ getmount "$HOME -maxdepth 3 -type d"
+ simple-mtpfs --device "$chosen" "$mp"
+ echo "OK" | dmenu -i -p "Tap Allow on your phone if it asks for permission and then press enter" || exit 1
+ simple-mtpfs --device "$chosen" "$mp"
+ notify-send "πŸ€– Android Mounting" "Android device mounted to $mp."
+ }
+
+asktype() { \
+ choice="$(printf "USB\\nAndroid" | dmenu -i -p "Mount a USB drive or Android device?")" || exit 1
+ case $choice in
+ USB) mountusb ;;
+ Android) mountandroid ;;
+ esac
+ }
+
+anddrives=$(simple-mtpfs -l 2>/dev/null)
+usbdrives="$(lsblk -rpo "name,type,size,mountpoint" | grep 'part\|rom' | awk '$4==""{printf "%s (%s)\n",$1,$3}')"
+
+if [ -z "$usbdrives" ]; then
+ [ -z "$anddrives" ] && echo "No USB drive or Android device detected" && exit
+ echo "Android device(s) detected."
+ mountandroid
+else
+ if [ -z "$anddrives" ]; then
+ echo "USB drive(s) detected."
+ mountusb
+ else
+ echo "Mountable USB drive(s) and Android device(s) detected."
+ asktype
+ fi
+fi
diff --git a/dmenumountcifs b/dmenumountcifs
new file mode 100755
index 0000000..46c2b57
--- /dev/null
+++ b/dmenumountcifs
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Gives a dmenu prompt to mount unmounted local NAS shares for read/write.
+# Requirements - "%wheel ALL=(ALL) NOPASSWD: ALL"
+#
+# Browse for mDNS/DNS-SD services using the Avahi daemon...
+srvname=$(avahi-browse _smb._tcp -t | awk '{print $4}' | dmenu -i -p "Which NAS?") || exit 1
+notify-send "Searching for network shares..." "Please wait..."
+# Choose share disk...
+share=$(smbclient -L "$srvname" -N | grep Disk | awk '{print $1}' | dmenu -i -p "Mount which share?") || exit 1
+# Format URL...
+share2mnt=//"$srvname".local/"$share"
+
+sharemount() {
+ mounted=$(mount -v | grep "$share2mnt") || ([ ! -d /mnt/"$share" ] && sudo mkdir /mnt/"$share")
+ [ -z "$mounted" ] && sudo mount -t cifs "$share2mnt" -o user=nobody,password="",noperm /mnt/"$share" && notify-send "Netshare $share mounted" && exit 0
+ notify-send "Netshare $share already mounted"; exit 1
+}
+
+sharemount
diff --git a/dmenupass b/dmenupass
new file mode 100755
index 0000000..2c14e6f
--- /dev/null
+++ b/dmenupass
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# This script is the SUDO_ASKPASS variable, meaning that it will be used as a
+# password prompt if needed.
+
+dmenu -fn Monospace-18 -P -p "$1" <&- && echo
diff --git a/dmenurecord b/dmenurecord
new file mode 100755
index 0000000..b83a7c5
--- /dev/null
+++ b/dmenurecord
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+# Usage:
+# `$0`: Ask for recording type via dmenu
+# `$0 screencast`: Record both audio and screen
+# `$0 video`: Record only screen
+# `$0 audio`: Record only audio
+# `$0 kill`: Kill existing recording
+#
+# If there is already a running instance, user will be prompted to end it.
+
+updateicon() { \
+ echo "$1" > /tmp/recordingicon
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ }
+
+killrecording() {
+ recpid="$(cat /tmp/recordingpid)"
+ # kill with SIGTERM, allowing finishing touches.
+ kill -15 "$recpid"
+ rm -f /tmp/recordingpid
+ updateicon ""
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ # even after SIGTERM, ffmpeg may still run, so SIGKILL it.
+ sleep 3
+ kill -9 "$recpid"
+ exit
+ }
+
+screencast() { \
+ ffmpeg -y \
+ -f x11grab \
+ -framerate 60 \
+ -s "$(xdpyinfo | awk '/dimensions/ {print $2;}')" \
+ -i "$DISPLAY" \
+ -f alsa -i default \
+ -r 30 \
+ -c:v h264 -crf 0 -preset ultrafast -c:a aac \
+ "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" &
+ echo $! > /tmp/recordingpid
+ updateicon "βΊοΈπŸŽ™οΈ"
+ }
+
+video() { ffmpeg \
+ -f x11grab \
+ -s "$(xdpyinfo | awk '/dimensions/ {print $2;}')" \
+ -i "$DISPLAY" \
+ -c:v libx264 -qp 0 -r 30 \
+ "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "⏺️"
+ }
+
+webcamhidef() { ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 1920x1080 \
+ "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "πŸŽ₯"
+ }
+
+webcam() { ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 640x480 \
+ "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "πŸŽ₯"
+ }
+
+
+audio() { \
+ ffmpeg \
+ -f alsa -i default \
+ -c:a flac \
+ "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" &
+ echo $! > /tmp/recordingpid
+ updateicon "πŸŽ™οΈ"
+ }
+
+askrecording() { \
+ choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio\\nwebcam\\nwebcam (hi-def)" | dmenu -i -p "Select recording style:")
+ case "$choice" in
+ screencast) screencast;;
+ audio) audio;;
+ video) video;;
+ *selected) videoselected;;
+ webcam) webcam;;
+ "webcam (hi-def)") webcamhidef;;
+ esac
+ }
+
+asktoend() { \
+ response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") &&
+ [ "$response" = "Yes" ] && killrecording
+ }
+
+videoselected()
+{
+ slop -f "%x %y %w %h" > /tmp/slop
+ read -r X Y W H < /tmp/slop
+ rm /tmp/slop
+
+ ffmpeg \
+ -f x11grab \
+ -framerate 60 \
+ -video_size "$W"x"$H" \
+ -i :0.0+"$X,$Y" \
+ -c:v libx264 -qp 0 -r 30 \
+ "$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" &
+ echo $! > /tmp/recordingpid
+ updateicon "⏺️"
+}
+
+case "$1" in
+ screencast) screencast;;
+ audio) audio;;
+ video) video;;
+ *selected) videoselected;;
+ kill) killrecording;;
+ *) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording;;
+esac
diff --git a/dmenuumount b/dmenuumount
new file mode 100755
index 0000000..946d12c
--- /dev/null
+++ b/dmenuumount
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# A dmenu prompt to unmount drives.
+# Provides you with mounted partitions, select one to unmount.
+# Drives mounted at /, /boot and /home will not be options to unmount.
+
+unmountusb() {
+ [ -z "$drives" ] && exit
+ chosen="$(echo "$drives" | dmenu -i -p "Unmount which drive?")" || exit 1
+ chosen="$(echo "$chosen" | awk '{print $1}')"
+ [ -z "$chosen" ] && exit
+ sudo -A umount "$chosen" && notify-send "πŸ’» USB unmounting" "$chosen unmounted."
+ }
+
+unmountandroid() { \
+ chosen="$(awk '/simple-mtpfs/ {print $2}' /etc/mtab | dmenu -i -p "Unmount which device?")" || exit 1
+ [ -z "$chosen" ] && exit
+ sudo -A umount -l "$chosen" && notify-send "πŸ€– Android unmounting" "$chosen unmounted."
+ }
+
+asktype() { \
+ choice="$(printf "USB\\nAndroid" | dmenu -i -p "Unmount a USB drive or Android device?")" || exit 1
+ case "$choice" in
+ USB) unmountusb ;;
+ Android) unmountandroid ;;
+ esac
+ }
+
+drives=$(lsblk -nrpo "name,type,size,mountpoint,label" | awk -F':' '{gsub(/ /,":")}$4!~/\/boot|\/efi|\/home$|SWAP/&&length($4)>1{printf "%s (%s) %s\n",$4,$3,$5}')
+
+if ! grep simple-mtpfs /etc/mtab; then
+ [ -z "$drives" ] && echo "No drives to unmount." && exit
+ echo "Unmountable USB drive detected."
+ unmountusb
+else
+ if [ -z "$drives" ]
+ then
+ echo "Unmountable Android device detected."
+ unmountandroid
+ else
+ echo "Unmountable USB drive(s) and Android device(s) detected."
+ asktype
+ fi
+fi
diff --git a/dmenuunicode b/dmenuunicode
new file mode 100755
index 0000000..7d9a4ea
--- /dev/null
+++ b/dmenuunicode
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# The famous "get a menu of emojis to copy" script.
+
+# Get user selection via dmenu from emoji file.
+chosen=$(cut -d ';' -f1 ~/.local/share/larbs/emoji | dmenu -i -l 30 | sed "s/ .*//")
+
+# Exit if none chosen.
+[ -z "$chosen" ] && exit
+
+# If you run this command with an argument, it will automatically insert the
+# character. Otherwise, show a message that the emoji has been copied.
+if [ -n "$1" ]; then
+ xdotool type "$chosen"
+else
+ printf "$chosen" | xclip -selection clipboard
+ notify-send "'$chosen' copied to clipboard." &
+fi
diff --git a/dwm_bar b/dwm_bar
new file mode 100755
index 0000000..487c9a3
--- /dev/null
+++ b/dwm_bar
@@ -0,0 +1,66 @@
+#!/bin/env sh
+
+# INIT
+printf "$$" > ~/.cache/pidofbar
+sec=0
+
+update_memory () {
+ memory="$(free -h | sed -n "2s/\([^ ]* *\)\{2\}\([^ ]*\).*/\2/p")"
+}
+
+update_time () {
+ time="$(date "+[  %a %d %b ] [ ο€— %I:%M %P ]")"
+}
+
+update_bat () {
+ # you might need to change the path depending on your device
+ read -r bat_status </sys/class/power_supply/BAT0/status
+ read -r bat_capacity </sys/class/power_supply/BAT0/capacity
+ if [ "$bat_status" = "Charging" ]; then
+ bat_status="ο—§"
+ elif [ "$bat_capacity" -gt 80 ]; then
+ bat_status=""
+ elif [ "$bat_capacity" -gt 60 ]; then
+ bat_status=""
+ elif [ "$bat_capacity" -gt 40 ]; then
+ bat_status=""
+ elif [ "$bat_capacity" -gt 20 ]; then
+ bat_status=""
+ else
+ bat_status=""
+ fi
+ bat="$bat_status $bat_capacity%"
+}
+
+update_vol () {
+ vol="$([ "$(pamixer --get-mute)" = "false" ] && printf ' ' || printf ' ')$(pamixer --get-volume)%"
+}
+
+# We have to run this only once.
+update_vol
+
+display () {
+ xsetroot -name "[ ο‹› $memory ] [ $vol ] $time"
+}
+
+# Handling receiving signal
+# RTMIN = 34 (always)
+trap "update_vol;display" "RTMIN"
+
+## kill -m "$(cat ~/.cache/pidofbar)"
+# where m = 34 + n
+
+while true
+do
+ sleep 1 &
+ wait && {
+ # to update item ever n seconds with a offset of m
+ ## [ $((sec % n)) -eq m ] && udpate_item
+ [ $((sec % 5 )) -eq 0 ] && update_time
+ [ $((sec % 15)) -eq 0 ] && update_memory
+
+ # how often the display updates ( 5 seconds )
+ [ $((sec % 5 )) -eq 0 ] && display
+ sec=$((sec + 1))
+ }
+done
diff --git a/emoji b/emoji
new file mode 100755
index 0000000..8bfdf32
--- /dev/null
+++ b/emoji
@@ -0,0 +1,3 @@
+#!/bin/sh
+emoji="$(cat $HOME/.local/share/emoji | dmenu -p "Select Emoji: " -l 15 | cut -d' ' -f1)"
+echo "$emoji" | tr "\n" " " | xclip -sel c
diff --git a/epylint b/epylint
new file mode 100755
index 0000000..2e104d9
--- /dev/null
+++ b/epylint
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pylint import run_epylint
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run_epylint())
diff --git a/estimator_ckpt_converter b/estimator_ckpt_converter
new file mode 100755
index 0000000..6d357cb
--- /dev/null
+++ b/estimator_ckpt_converter
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow_estimator.python.estimator.tools.checkpoint_converter import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/ext b/ext
new file mode 100755
index 0000000..6950ff6
--- /dev/null
+++ b/ext
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# A general, all-purpose extraction script. Not all extraction programs here
+# are installed by LARBS automatically.
+#
+# Default behavior: Extract archive into new directory
+# Behavior with `-c` option: Extract contents into current directory
+
+while getopts "hc" o; do case "${o}" in
+ c) extracthere="True" ;;
+ *) printf "Options:\\n -c: Extract archive into current directory rather than a new one.\\n" && exit 1 ;;
+esac done
+
+if [ -z "$extracthere" ]; then
+ archive="$(readlink -f "$*")" &&
+ directory="$(echo "$archive" | sed 's/\.[^\/.]*$//')" &&
+ mkdir -p "$directory" &&
+ cd "$directory" || exit 1
+else
+ archive="$(readlink -f "$(echo "$*" | cut -d' ' -f2)" 2>/dev/null)"
+fi
+
+[ -z "$archive" ] && printf "Give archive to extract as argument.\\n" && exit 1
+
+if [ -f "$archive" ] ; then
+ case "$archive" in
+ *.tar.bz2|*.tbz2) bsdtar -xf "$archive" ;;
+ *.tar.xz) bsdtar -xf "$archive" ;;
+ *.tar.gz|*.tgz) bsdtar -xf "$archive" ;;
+ *.tar.zst) bsdtar -xf "$archive" ;;
+ *.tar) bsdtar -xf "$archive" ;;
+ *.lzma) unlzma "$archive" ;;
+ *.bz2) bunzip2 "$archive" ;;
+ *.rar) unrar x -ad "$archive" ;;
+ *.gz) gunzip "$archive" ;;
+ *.zip) unzip "$archive" ;;
+ *.Z) uncompress "$archive" ;;
+ *.7z) 7z x "$archive" ;;
+ *.xz) unxz "$archive" ;;
+ *.exe) cabextract "$archive" ;;
+ *) printf "extract: '%s' - unknown archive method\\n" "$archive" ;;
+ esac
+else
+ printf "File \"%s\" not found.\\n" "$archive"
+fi
diff --git a/f2py b/f2py
new file mode 100755
index 0000000..40ce6f8
--- /dev/null
+++ b/f2py
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from numpy.f2py.f2py2e import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/f2py3 b/f2py3
new file mode 100755
index 0000000..40ce6f8
--- /dev/null
+++ b/f2py3
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from numpy.f2py.f2py2e import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/f2py3.10 b/f2py3.10
new file mode 100755
index 0000000..40ce6f8
--- /dev/null
+++ b/f2py3.10
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from numpy.f2py.f2py2e import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/flake8 b/flake8
new file mode 100755
index 0000000..170c767
--- /dev/null
+++ b/flake8
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from flake8.main.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/fonttools b/fonttools
new file mode 100755
index 0000000..49c4cd1
--- /dev/null
+++ b/fonttools
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from fontTools.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/get_objgraph b/get_objgraph
new file mode 100755
index 0000000..be3da53
--- /dev/null
+++ b/get_objgraph
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+#
+# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
+# Copyright (c) 2008-2016 California Institute of Technology.
+# Copyright (c) 2016-2022 The Uncertainty Quantification Foundation.
+# License: 3-clause BSD. The full license text is available at:
+# - https://github.com/uqfoundation/dill/blob/master/LICENSE
+"""
+display the reference paths for objects in ``dill.types`` or a .pkl file
+
+Notes:
+ the generated image is useful in showing the pointer references in
+ objects that are or can be pickled. Any object in ``dill.objects``
+ listed in ``dill.load_types(picklable=True, unpicklable=True)`` works.
+
+Examples::
+
+ $ get_objgraph FrameType
+ Image generated as FrameType.png
+"""
+
+import dill as pickle
+#pickle.debug.trace(True)
+#import pickle
+
+# get all objects for testing
+from dill import load_types
+load_types(pickleable=True,unpickleable=True)
+from dill import objects
+
+if __name__ == "__main__":
+ import sys
+ if len(sys.argv) != 2:
+ print ("Please provide exactly one file or type name (e.g. 'IntType')")
+ msg = "\n"
+ for objtype in list(objects.keys())[:40]:
+ msg += objtype + ', '
+ print (msg + "...")
+ else:
+ objtype = str(sys.argv[-1])
+ try:
+ obj = objects[objtype]
+ except KeyError:
+ obj = pickle.load(open(objtype,'rb'))
+ import os
+ objtype = os.path.splitext(objtype)[0]
+ try:
+ import objgraph
+ objgraph.show_refs(obj, filename=objtype+'.png')
+ except ImportError:
+ print ("Please install 'objgraph' to view object graphs")
+
+
+# EOF
diff --git a/getbib b/getbib
new file mode 100755
index 0000000..8675aae
--- /dev/null
+++ b/getbib
@@ -0,0 +1,14 @@
+#!/bin/sh
+[ -z "$1" ] && echo "Give either a pdf file or a DOI as an argument." && exit
+
+if [ -f "$1" ]; then
+ # Try to get DOI from pdfinfo or pdftotext output.
+ doi=$(pdfinfo "$1" | grep -io "doi:.*") ||
+ doi=$(pdftotext "$1" 2>/dev/null - | grep -io "doi:.*" -m 1) ||
+ exit 1
+else
+ doi="$1"
+fi
+
+# Check crossref.org for the bib citation.
+curl -s "https://api.crossref.org/works/$doi/transform/application/x-bibtex" -w "\\n"
diff --git a/getkeys b/getkeys
new file mode 100755
index 0000000..266f29a
--- /dev/null
+++ b/getkeys
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+cat "${XDG_DATA_HOME:-$HOME/.local/share}"/larbs/getkeys/"$1" 2>/dev/null && exit
+echo "Run command with one of the following arguments for info about that program:"
+ls "${XDG_DATA_HOME:-$HOME/.local/share}"/larbs/getkeys
diff --git a/google-oauthlib-tool b/google-oauthlib-tool
new file mode 100755
index 0000000..d84b136
--- /dev/null
+++ b/google-oauthlib-tool
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from google_auth_oauthlib.tool.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/holehe b/holehe
new file mode 100755
index 0000000..786cf49
--- /dev/null
+++ b/holehe
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from holehe.core import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/httpx b/httpx
new file mode 100755
index 0000000..3d3d397
--- /dev/null
+++ b/httpx
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from httpx import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/ifinstalled b/ifinstalled
new file mode 100755
index 0000000..c192eba
--- /dev/null
+++ b/ifinstalled
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Some optional functions in LARBS require programs not installed by default. I
+# use this little script to check to see if a command exists and if it doesn't
+# it informs the user that they need that command to continue. This is used in
+# various other scripts for clarity's sake.
+
+for x in "$@"; do
+ if ! which "$x" >/dev/null 2>&1 && ! pacman -Qq "$x" >/dev/null 2>&1; then
+ notify-send "πŸ“¦ $x" "must be installed for this function." && exit 1 ;
+ fi
+done
diff --git a/import_pb_to_tensorboard b/import_pb_to_tensorboard
new file mode 100755
index 0000000..2b77b14
--- /dev/null
+++ b/import_pb_to_tensorboard
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.python.tools.import_pb_to_tensorboard import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/isort b/isort
new file mode 100755
index 0000000..daca689
--- /dev/null
+++ b/isort
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from isort.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/isort-identify-imports b/isort-identify-imports
new file mode 100755
index 0000000..a772abd
--- /dev/null
+++ b/isort-identify-imports
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from isort.main import identify_imports_main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(identify_imports_main())
diff --git a/layoutmenu b/layoutmenu
new file mode 100755
index 0000000..1bf95f2
--- /dev/null
+++ b/layoutmenu
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+cat <<EOF | xmenu
+[]= Tiled Layout 0
+><> Floating Layout 1
+[M] Monocle Layout 2
+EOF
diff --git a/lfub b/lfub
new file mode 100755
index 0000000..9012f50
--- /dev/null
+++ b/lfub
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# This is a wrapper script for lb that allows it to create image previews with
+# ueberzug. This works in concert with the lf configuration file and the
+# lf-cleaner script.
+
+set -e
+
+cleanup() {
+ exec 3>&-
+ rm "$FIFO_UEBERZUG"
+}
+
+if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
+ lf "$@"
+else
+ [ ! -d "$HOME/.cache/lf" ] && mkdir -p "$HOME/.cache/lf"
+ export FIFO_UEBERZUG="$HOME/.cache/lf/ueberzug-$$"
+ mkfifo "$FIFO_UEBERZUG"
+ ueberzug layer -s <"$FIFO_UEBERZUG" -p json &
+ exec 3>"$FIFO_UEBERZUG"
+ trap cleanup HUP INT QUIT TERM PWR EXIT
+ lf "$@" 3>&-
+fi
diff --git a/linkhandler b/linkhandler
new file mode 100755
index 0000000..fa74caf
--- /dev/null
+++ b/linkhandler
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Feed script a url or file location.
+# If an image, it will view in sxiv,
+# if a video or gif, it will view in mpv
+# if a music file or pdf, it will download,
+# otherwise it opens link in browser.
+
+# If no url given. Opens browser. For using script as $BROWSER.
+[ -z "$1" ] && { "$BROWSER"; exit; }
+
+case "$1" in
+ *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtu.be*|*hooktube.com*|*bitchute.com*|*videos.lukesmith.xyz*|*odysee.com*)
+ setsid -f mpv -quiet "$1" >/dev/null 2>&1 ;;
+ *png|*jpg|*jpe|*jpeg|*gif)
+ curl -sL "$1" > "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *pdf|*cbz|*cbr)
+ curl -sL "$1" > "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *mp3|*flac|*opus|*mp3?source*)
+ qndl "$1" 'curl -LO' >/dev/null 2>&1 ;;
+ *)
+ [ -f "$1" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$1" >/dev/null 2>&1 || setsid -f "$BROWSER" "$1" >/dev/null 2>&1
+esac
diff --git a/maimpick b/maimpick
new file mode 100755
index 0000000..7125e61
--- /dev/null
+++ b/maimpick
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# This is bound to Shift+PrintScreen by default, requires maim. It lets you
+# choose the kind of screenshot to take, including copying the image or even
+# highlighting an area to copy. scrotcucks on suicidewatch right now.
+
+case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -l 6 -i -p "Screenshot which area?")" in
+ "a selected area") maim -s pic-selected-"$(date '+%y%m%d-%H%M-%S').png" ;;
+ "current window") maim -i "$(xdotool getactivewindow)" pic-window-"$(date '+%y%m%d-%H%M-%S').png" ;;
+ "full screen") maim pic-full-"$(date '+%y%m%d-%H%M-%S').png" ;;
+ "a selected area (copy)") maim -s | xclip -selection clipboard -t image/png ;;
+ "current window (copy)") maim -i "$(xdotool getactivewindow)" | xclip -selection clipboard -t image/png ;;
+ "full screen (copy)") maim | xclip -selection clipboard -t image/png ;;
+esac
diff --git a/markdown_py b/markdown_py
new file mode 100755
index 0000000..ca0b785
--- /dev/null
+++ b/markdown_py
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from markdown.__main__ import run
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run())
diff --git a/nasad b/nasad
new file mode 100755
index 0000000..af148de
--- /dev/null
+++ b/nasad
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from nasa.daemon import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/newword b/newword
new file mode 100755
index 0000000..778605e
--- /dev/null
+++ b/newword
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+word=$(dmenu -p "Enter Word: " <&-)
+mean=$(dmenu -p "Enter Meaning: " <&-)
+
+echo "$word -> $mean" >> ~/.local/share/vocab/words.txt
diff --git a/noisereduce b/noisereduce
new file mode 100755
index 0000000..c344760
--- /dev/null
+++ b/noisereduce
@@ -0,0 +1,81 @@
+#!/usr/bin/sh
+
+usage ()
+{
+ printf "Usage : noisereduce <input video file> <output video file>\n"
+ exit
+}
+
+# Tests for requirements
+ifinstalled ffmpeg || { echo >&2 "We require 'ffmpeg' but it's not installed."; exit 1; }
+ifinstalled sox || { echo >&2 "We require 'ffmpeg' but it's not installed."; exit 1; }
+
+if [ "$#" -ne 2 ]
+then
+ usage
+fi
+
+if [ ! -e "$1" ]
+then
+ printf "File not found: %s\n" "$1"
+ exit
+fi
+
+if [ -e "$2" ]
+then
+ printf "File %s already exists, overwrite? [y/N]\n: " "$2"
+ read -r yn
+ case $yn in
+ [Yy]* ) ;;
+ * ) exit;;
+ esac
+fi
+
+inBasename=$(basename "$1")
+inExt="${inBasename##*.}"
+
+isVideoStr=$(ffprobe -v warning -show_streams "$1" | grep codec_type=video)
+if [ -n "$isVideoStr" ]
+then
+ isVideo=1
+ printf "Detected %s as a video file\n" "$inBasename"
+else
+ isVideo=0
+ printf "Detected %s as an audio file\n" "$inBasename"
+fi
+
+printf "Sample noise start time [00:00:00]: "
+read -r sampleStart
+if [ -z "$sampleStart" ] ; then sampleStart="00:00:00"; fi
+printf "Sample noise end time [00:00:00.900]: "
+read -r sampleEnd
+if [ -z "$sampleEnd" ] ; then sampleEnd="00:00:00.900"; fi
+printf "Noise reduction amount [0.21]: "
+read -r sensitivity
+if [ -z "$sensitivity" ] ; then sensitivity="0.21"; fi
+
+
+tmpVidFile="/tmp/noiseclean_tmpvid.$inExt"
+tmpAudFile="/tmp/noiseclean_tmpaud.wav"
+noiseAudFile="/tmp/noiseclean_noiseaud.wav"
+noiseProfFile="/tmp/noiseclean_noise.prof"
+tmpAudCleanFile="/tmp/noiseclean_tmpaud-clean.wav"
+
+printf "Cleaning noise on %s...\n" "$1"
+
+if [ $isVideo -eq "1" ]; then
+ ffmpeg -v warning -y -i "$1" -qscale:v 0 -vcodec copy -an "$tmpVidFile"
+ ffmpeg -v warning -y -i "$1" -qscale:a 0 "$tmpAudFile"
+else
+ cp "$1" "$tmpAudFile"
+fi
+ffmpeg -v warning -y -i "$1" -vn -ss "$sampleStart" -t "$sampleEnd" "$noiseAudFile"
+sox "$noiseAudFile" -n noiseprof "$noiseProfFile"
+sox "$tmpAudFile" "$tmpAudCleanFile" noisered "$noiseProfFile" "$sensitivity"
+if [ $isVideo -eq "1" ]; then
+ ffmpeg -v warning -y -i "$tmpAudCleanFile" -i "$tmpVidFile" -vcodec copy -qscale:v 0 -qscale:a 0 "$2"
+else
+ cp "$tmpAudCleanFile" "$2"
+fi
+
+printf "Done"
diff --git a/normalizer b/normalizer
new file mode 100755
index 0000000..2479e13
--- /dev/null
+++ b/normalizer
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from charset_normalizer.cli.normalizer import cli_detect
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(cli_detect())
diff --git a/notflix b/notflix
new file mode 100755
index 0000000..8899473
--- /dev/null
+++ b/notflix
@@ -0,0 +1,53 @@
+#!/usr/bin/env sh
+
+#########
+# Input #
+#########
+
+input() {
+ printf "Search Torrent: " && read -r name || name="$1"
+ get_url
+}
+
+##################
+# URL Processing #
+##################
+
+get_url() {
+ search=$(echo "${name}" | sed 's/ /\%20/g')
+ magnet=$(curl -s "$baseurl/search/${search}/1/99/200" | grep -Eo "magnet:\?xt=urn:btih:[a-zA-Z0-9]*" | head -n 1)
+ choose
+}
+
+
+##########
+# choice #
+##########
+
+stream() {
+ peerflix -k "${magnet}"
+}
+
+download() {
+ peerflix "${magnet}"
+}
+
+choose() {
+ choice="$( printf "stream\ndownload" | fzf)"
+ [ "$choice" = "stream" ] && stream
+ [ "$choice" = "download" ] && download
+}
+
+###########
+# Startup #
+###########
+
+# defaults
+
+baseurl=$(curl -s -L -o /dev/null -w "%{url_effective}\n" https://thepiratebay.party)
+name=$(printf "$*")
+
+# checks if name variable is empty or not
+[ -n "$name" ] && get_url
+[ ! -n "$name" ] && input
+
diff --git a/opout b/opout
new file mode 100755
index 0000000..faf6575
--- /dev/null
+++ b/opout
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# opout: "open output": A general handler for opening a file's intended output,
+# usually the pdf of a compiled document. I find this useful especially
+# running from vim.
+
+basename="${1%.*}"
+
+case "${*}" in
+ *.tex|*.m[dse]|*.[rR]md|*.mom|*.[0-9]) setsid -f xdg-open "$basename".pdf >/dev/null 2>&1 ;;
+ *.html) setsid -f "$BROWSER" "$basename".html >/dev/null 2>&1 ;;
+ *.sent) setsid -f sent "$1" >/dev/null 2>&1 ;;
+esac
diff --git a/otp b/otp
new file mode 100755
index 0000000..1726b1a
--- /dev/null
+++ b/otp
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Get a one-time password, or add a OTP secret to your pass-otp store.
+
+# The assumption of this script is that all otp passwords are stored with the
+# suffix `-otp`. This script automatically appends newly added otps as such.
+
+# For OTP passwords to be generated properly, it is important for the local
+# computer to have its time properly synced. This can be done with the command
+# below which requires the package `ntp`.
+
+ifinstalled pass pass-otp
+
+dir="${PASSWORD_STORE_DIR}"
+
+choice="$({ echo "πŸ†•add" ; echo "πŸ•™sync-time" ; ls ${dir}/*-otp.gpg ;} | sed "s/.*\///;s/-otp.gpg//" | dmenu -p "Pick a 2FA:")"
+
+case $choice in
+ πŸ†•add )
+ ifinstalled maim zbar xclip || exit 1
+
+ temp="$dir/temp.png"
+ otp="otp-test-script"
+ trap 'shred -fu $temp; pass rm $otp' HUP INT QUIT TERM PWR EXIT
+
+ notify-send "Scan the image." "Scan the OTP QR code."
+
+ maim -s "$temp" || exit 1
+ info="$(zbarimg -q "$temp")"
+ info="${info#QR-Code:}"
+ issuer="$(echo "$info" | grep -o "issuer=[A-z0-9]\+")"
+ name="${issuer#issuer=}"
+
+ if echo "$info" | pass otp insert "$otp"; then
+ while true ; do
+ export name="$(dmenu -p "Give this One Time Password a one-word name:")"
+ echo "$name" | grep -q -- "^[A-z0-9-]\+$" && break
+ done
+ pass mv "$otp" "$name-otp"
+ notify-send "Successfully added." "$name-otp has been created."
+ else
+ notify-send "No OTP data found." "Try to scan the image again more precisely."
+ fi
+
+ ;;
+ πŸ•™sync-time )
+ ifinstalled ntp || exit 1
+ notify-send -u low "πŸ•™ Synchronizing Time..." "Synching time with remote NTP servers..."
+ updatedata="$(sudo ntpdate pool.ntp.org)" &&
+ notify-send -u low "πŸ•™ Synchronizing Time..." "Done. Time changed by ${updatedata#*offset }"
+ ;;
+ *) pass otp -c ${choice}-otp ;;
+esac
diff --git a/pauseallmpv b/pauseallmpv
new file mode 100755
index 0000000..d69a414
--- /dev/null
+++ b/pauseallmpv
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# You might notice all mpv commands are aliased to have this input-ipc-server
+# thing. That's just for this particular command, which allows us to pause
+# every single one of them with one command! This is bound to super + shift + p
+# (with other things) by default and is used in some other places.
+
+for i in $(ls /tmp/mpvSockets/*); do
+ echo '{ "command": ["set_property", "pause", true] }' | socat - "$i";
+done
diff --git a/peertubetorrent b/peertubetorrent
new file mode 100755
index 0000000..e89b1c0
--- /dev/null
+++ b/peertubetorrent
@@ -0,0 +1,9 @@
+#!/bin/sh
+# torrent peertube videos, requires the transadd script
+# first argument is the video link, second is the quality (360, 480 or 1080)
+# 13/07/20 - Arthur Bais
+
+instance=$(echo "$1" | sed "s/\/w.\+//")
+vidid=$(echo "$1" | sed "s/.\+\///")
+link=$(curl -s "$instance/api/v1/videos/$vidid" | grep -o "$instance/download/torrents/.\{37\}$2.torrent")
+transadd "$link"
diff --git a/podentr b/podentr
new file mode 100755
index 0000000..9454b07
--- /dev/null
+++ b/podentr
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# entr command to run `queueandnotify` when newsboat queue is changed
+
+[ "$(pgrep -x "$(basename "$0")" | wc -l)" -gt 2 ] && exit
+
+echo "${XDG_DATA_HOME:-$HOME/.local/share}"/newsboat/queue | entr -p queueandnotify 2>/dev/null
diff --git a/prompt b/prompt
new file mode 100755
index 0000000..666434f
--- /dev/null
+++ b/prompt
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# A dmenu binary prompt script.
+# Gives a dmenu prompt labeled with $1 to perform command $2.
+# For example:
+# `./prompt "Do you want to shutdown?" "shutdown -h now"`
+
+[ "$(printf "No\\nYes" | dmenu -i -p "$1" -nb darkred -sb red -sf white -nf gray )" = "Yes" ] && $2
diff --git a/py.test b/py.test
new file mode 100755
index 0000000..3dbd45f
--- /dev/null
+++ b/py.test
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pytest import console_main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(console_main())
diff --git a/pycodestyle b/pycodestyle
new file mode 100755
index 0000000..8732f23
--- /dev/null
+++ b/pycodestyle
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pycodestyle import _main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(_main())
diff --git a/pyflakes b/pyflakes
new file mode 100755
index 0000000..4809d6f
--- /dev/null
+++ b/pyflakes
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pyflakes.api import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/pyftmerge b/pyftmerge
new file mode 100755
index 0000000..1e4c3a8
--- /dev/null
+++ b/pyftmerge
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from fontTools.merge import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/pyftsubset b/pyftsubset
new file mode 100755
index 0000000..6f56bcb
--- /dev/null
+++ b/pyftsubset
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from fontTools.subset import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/pylint b/pylint
new file mode 100755
index 0000000..d21a75d
--- /dev/null
+++ b/pylint
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pylint import run_pylint
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run_pylint())
diff --git a/pyreverse b/pyreverse
new file mode 100755
index 0000000..433cf32
--- /dev/null
+++ b/pyreverse
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pylint import run_pyreverse
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run_pyreverse())
diff --git a/pyrsa-decrypt b/pyrsa-decrypt
new file mode 100755
index 0000000..13fe183
--- /dev/null
+++ b/pyrsa-decrypt
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.cli import decrypt
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(decrypt())
diff --git a/pyrsa-encrypt b/pyrsa-encrypt
new file mode 100755
index 0000000..2fd0772
--- /dev/null
+++ b/pyrsa-encrypt
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.cli import encrypt
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(encrypt())
diff --git a/pyrsa-keygen b/pyrsa-keygen
new file mode 100755
index 0000000..0fcfad8
--- /dev/null
+++ b/pyrsa-keygen
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.cli import keygen
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(keygen())
diff --git a/pyrsa-priv2pub b/pyrsa-priv2pub
new file mode 100755
index 0000000..f497202
--- /dev/null
+++ b/pyrsa-priv2pub
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.util import private_to_public
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(private_to_public())
diff --git a/pyrsa-sign b/pyrsa-sign
new file mode 100755
index 0000000..5a45815
--- /dev/null
+++ b/pyrsa-sign
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.cli import sign
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(sign())
diff --git a/pyrsa-verify b/pyrsa-verify
new file mode 100755
index 0000000..ff68ce9
--- /dev/null
+++ b/pyrsa-verify
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from rsa.cli import verify
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(verify())
diff --git a/pytest b/pytest
new file mode 100755
index 0000000..3dbd45f
--- /dev/null
+++ b/pytest
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pytest import console_main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(console_main())
diff --git a/qndl b/qndl
new file mode 100755
index 0000000..48bc61e
--- /dev/null
+++ b/qndl
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# $1 is a url; $2 is a command
+[ -z "$1" ] && exit
+base="$(basename "$1")"
+notify-send "⏳ Queuing $base..."
+cmd="$2"
+[ -z "$cmd" ] && cmd="yt-dlp --embed-metadata -ic"
+idnum="$(tsp $cmd "$1")"
+realname="$(echo "$base" | sed "s/?\(source\|dest\).*//;s/%20/ /g")"
+tsp -D "$idnum" mv "$base" "$realname"
+tsp -D "$idnum" notify-send "πŸ‘ $realname done."
diff --git a/queueandnotify b/queueandnotify
new file mode 100755
index 0000000..1c3025c
--- /dev/null
+++ b/queueandnotify
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Podboat sucks. This script replaces it.
+# It reads the newsboat queue, queuing downloads with taskspooler.
+# It also removes the junk from extensions.
+queuefile="${XDG_DATA_HOME:-$HOME/.local/share}/newsboat/queue"
+
+while read -r line; do
+ [ -z "$line" ] && continue
+ url="${line%%[ ]*}"
+ qndl "$url" "curl -LO"
+done < "$queuefile"
+
+echo > "$queuefile"
diff --git a/randompass b/randompass
new file mode 100755
index 0000000..fca095d
--- /dev/null
+++ b/randompass
@@ -0,0 +1,31 @@
+#! /usr/bin/python
+import string
+import random
+
+
+## characters to generate password from
+characters = list(string.ascii_letters + string.digits + "!@#$%^&*()")
+
+def generate_random_password():
+ ## length of password from the user
+ length = int(input("Enter password length: "))
+
+ ## shuffling the characters
+ random.shuffle(characters)
+
+ ## picking random characters from the list
+ password = []
+ for i in range(length):
+ password.append(random.choice(characters))
+
+ ## shuffling the resultant password
+ random.shuffle(password)
+
+ ## converting the list to string
+ ## printing the list
+ print("".join(password))
+
+
+
+## invoking the function
+generate_random_password()
diff --git a/remaps b/remaps
new file mode 100755
index 0000000..c95ac84
--- /dev/null
+++ b/remaps
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# This script is called on startup to remap keys.
+# Decrease key repeat delay to 300ms and increase key repeat rate to 50 per second.
+xset r rate 300 50
+# Map the caps lock key to super, and map the menu key to right super.
+setxkbmap -option caps:super,altwin:menu_win
+# When caps lock is pressed only once, treat it as escape.
+killall xcape 2>/dev/null ; xcape -e 'Super_L=Escape'
+# Turn off caps lock if on since there is no longer a key for it.
+xset -q | grep "Caps Lock:\s*on" && xdotool key Caps_Lock
diff --git a/rotdir b/rotdir
new file mode 100755
index 0000000..86da6db
--- /dev/null
+++ b/rotdir
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# When I open an image from the file manager in sxiv (the image viewer), I want
+# to be able to press the next/previous keys to key through the rest of the
+# images in the same directory. This script "rotates" the content of a
+# directory based on the first chosen file, so that if I open the 15th image,
+# if I press next, it will go to the 16th etc. Autistic, I know, but this is
+# one of the reasons that sxiv is great for being able to read standard input.
+
+[ -z "$1" ] && echo "usage: rotdir regex 2>&1" && exit 1
+base="$(basename "$1")"
+ls "$PWD" | awk -v BASE="$base" 'BEGIN { lines = ""; m = 0; } { if ($0 == BASE) { m = 1; } } { if (!m) { if (lines) { lines = lines"\n"; } lines = lines""$0; } else { print $0; } } END { print lines; }'
diff --git a/rssadd b/rssadd
new file mode 100755
index 0000000..910fca3
--- /dev/null
+++ b/rssadd
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+if echo "$1" | grep -q "https*://\S\+\.[A-Za-z]\+\S*" ; then
+ url="$1"
+else
+ url="$(grep -Eom1 '<[^>]+(rel="self"|application/[a-z]+\+xml)[^>]+>' "$1" |
+ grep -o "https?://[^\" ]")"
+
+ echo "$url" | grep -q "https*://\S\+\.[A-Za-z]\+\S*" ||
+ notify-send "That doesn't look like a full URL." && exit 1
+fi
+
+RSSFILE="${XDG_CONFIG_HOME:-$HOME/.config}/newsboat/urls"
+if awk '{print $1}' "$RSSFILE" | grep "^$url$" >/dev/null; then
+ notify-send "You already have this RSS feed."
+else
+ echo "$url" >> "$RSSFILE" && notify-send "RSS feed added."
+fi
diff --git a/samedir b/samedir
new file mode 100755
index 0000000..0a19707
--- /dev/null
+++ b/samedir
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Open a terminal window in the same directory as the currently active window.
+
+PID=$(xprop -id "$(xprop -root | xprop -root | sed -n "/_NET_ACTIVE_WINDOW/ s/^.*# // p")" | sed -n "/PID/ s/^.*= // p")
+PID="$(pstree -lpA "$PID")"
+PID="${PID##*(}"
+PID="${PID%)}"
+cd "$(readlink /proc/"$PID"/cwd)" || return 1
+"$TERMINAL"
diff --git a/saved_model_cli b/saved_model_cli
new file mode 100755
index 0000000..8598ef4
--- /dev/null
+++ b/saved_model_cli
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.python.tools.saved_model_cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/set_wallpaper b/set_wallpaper
new file mode 100755
index 0000000..ccbe75e
--- /dev/null
+++ b/set_wallpaper
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Dependencies:
+# convert wal xdotool xwallpaper
+
+wall_dir=~/pix/wall
+
+if [ -z "$1" ]; then
+ wall="$(find "$wall_dir" -type f -name "*.jpg" -o -name "*.png" | shuf -n1)"
+else
+ wall="$1"
+fi
+
+convert "$wall" ~/.local/share/bg.jpg
+xwallpaper --zoom ~/.local/share/bg.jpg
+wal -c
+wal -i ~/.local/share/bg.jpg
+xdotool key super+F5
diff --git a/setbg b/setbg
new file mode 100755
index 0000000..2829896
--- /dev/null
+++ b/setbg
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# This script does the following:
+# Run by itself, set the wallpaper (at X start).
+# If given a file, set that as the new wallpaper.
+# If given a directory, choose random file in it.
+# If wal is installed, also generates a colorscheme.
+
+# Location of link to wallpaper link.
+bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/bg"
+
+# Configuration files of applications that have their themes changed by pywal.
+dunstconf="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc"
+zathuraconf="${XDG_CONFIG_HOME:-$HOME/.config}/zathura/zathurarc"
+
+trueloc="$(readlink -f "$1")" &&
+case "$(file --mime-type -b "$trueloc")" in
+ image/* ) ln -sf "$(readlink -f "$1")" "$bgloc" && notify-send -i "$bgloc" "Changing wallpaper..." ;;
+ inode/directory ) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && notify-send -i "$bgloc" "Random Wallpaper chosen." ;;
+ *) notify-send "Error" "Not a valid image." ; exit 1;;
+esac
+
+# If pywal is installed, use it.
+if command -v wal >/dev/null 2>&1 ; then
+ wal -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1 &&
+ pidof dwm >/dev/null && xdotool key super+F12
+# If pywal is removed, return config files to normal.
+else
+ [ -f "$dunstconf.bak" ] && unlink "$dunstconf" && mv "$dunstconf.bak" "$dunstconf"
+ [ -f "$zathuraconf.bak" ] && unlink "$zathuraconf" && mv "$zathuraconf.bak" "$zathuraconf"
+fi
+
+xwallpaper --zoom "$bgloc"
diff --git a/shortcuts b/shortcuts
new file mode 100755
index 0000000..8fecea2
--- /dev/null
+++ b/shortcuts
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+bmdirs="${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs"
+bmfiles="${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-files"
+
+# Output locations. Unactivated progs should go to /dev/null.
+shell_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/shell/shortcutrc"
+zsh_named_dirs="${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshnameddirrc"
+lf_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/lf/shortcutrc"
+vim_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/nvim/shortcuts.vim"
+ranger_shortcuts="/dev/null"
+qute_shortcuts="/dev/null"
+fish_shortcuts="/dev/null"
+vifm_shortcuts="/dev/null"
+
+# Remove, prepare files
+rm -f "$lf_shortcuts" "$ranger_shortcuts" "$qute_shortcuts" "$zsh_named_dirs" "$vim_shortcuts" 2>/dev/null
+printf "# vim: filetype=sh\\n" > "$fish_shortcuts"
+printf "# vim: filetype=sh\\nalias " > "$shell_shortcuts"
+printf "\" vim: filetype=vim\\n" > "$vifm_shortcuts"
+
+# Format the `directories` file in the correct syntax and sent it to all three configs.
+eval "echo \"$(cat "$bmdirs")\"" | \
+awk "!/^\s*#/ && !/^\s*\$/ {gsub(\"\\\s*#.*$\",\"\");
+ printf(\"%s=\42cd %s && ls -a\42 \\\\\n\",\$1,\$2) >> \"$shell_shortcuts\" ;
+ printf(\"hash -d %s=%s \n\",\$1,\$2) >> \"$zsh_named_dirs\" ;
+ printf(\"abbr %s \42cd %s; and ls -a\42\n\",\$1,\$2) >> \"$fish_shortcuts\" ;
+ printf(\"map g%s :cd %s<CR>\nmap t%s <tab>:cd %s<CR><tab>\nmap M%s <tab>:cd %s<CR><tab>:mo<CR>\nmap Y%s <tab>:cd %s<CR><tab>:co<CR> \n\",\$1,\$2, \$1, \$2, \$1, \$2, \$1, \$2) >> \"$vifm_shortcuts\" ;
+ printf(\"config.bind(';%s', \42set downloads.location.directory %s ;; hint links download\42) \n\",\$1,\$2) >> \"$qute_shortcuts\" ;
+ printf(\"map g%s cd %s\nmap t%s tab_new %s\nmap m%s shell mv -v %%s %s\nmap Y%s shell cp -rv %%s %s \n\",\$1,\$2,\$1,\$2, \$1, \$2, \$1, \$2) >> \"$ranger_shortcuts\" ;
+ printf(\"map C%s cd \42%s\42 \n\",\$1,\$2) >> \"$lf_shortcuts\" ;
+ printf(\"cmap ;%s %s\n\",\$1,\$2) >> \"$vim_shortcuts\" }"
+
+# Format the `files` file in the correct syntax and sent it to both configs.
+eval "echo \"$(cat "$bmfiles")\"" | \
+awk "!/^\s*#/ && !/^\s*\$/ {gsub(\"\\\s*#.*$\",\"\");
+ printf(\"%s=\42\$EDITOR %s\42 \\\\\n\",\$1,\$2) >> \"$shell_shortcuts\" ;
+ printf(\"hash -d %s=%s \n\",\$1,\$2) >> \"$zsh_named_dirs\" ;
+ printf(\"abbr %s \42\$EDITOR %s\42 \n\",\$1,\$2) >> \"$fish_shortcuts\" ;
+ printf(\"map %s :e %s<CR> \n\",\$1,\$2) >> \"$vifm_shortcuts\" ;
+ printf(\"map %s shell \$EDITOR %s \n\",\$1,\$2) >> \"$ranger_shortcuts\" ;
+ printf(\"map E%s \$\$EDITOR \42%s\42 \n\",\$1,\$2) >> \"$lf_shortcuts\" ;
+ printf(\"cmap ;%s %s\n\",\$1,\$2) >> \"$vim_shortcuts\" }"
diff --git a/slider b/slider
new file mode 100755
index 0000000..674781a
--- /dev/null
+++ b/slider
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+# Give a file with images and timecodes and creates a video slideshow of them.
+#
+# Timecodes must be in format 00:00:00.
+#
+# Imagemagick and ffmpeg required.
+
+# Application cache if not stated elsewhere.
+cache="${XDG_CACHE_HOME:-$HOME/.cache}/slider"
+
+while getopts "hvrpi:c:a:o:d:f:t:e:x:" o; do case "${o}" in
+ c) bgc="$OPTARG" ;;
+ t) fgc="$OPTARG" ;;
+ f) font="$OPTARG" ;;
+ i) file="$OPTARG" ;;
+ a) audio="$OPTARG" ;;
+ o) outfile="$OPTARG" ;;
+ d) prepdir="$OPTARG" ;;
+ r) redo="$OPTARG" ;;
+ s) ppt="$OPTARG" ;;
+ e) endtime="$OPTARG" ;;
+ x) res="$OPTARG"
+ echo "$res" | grep -qv "^[0-9]\+x[0-9]\+$" &&
+ echo "Resolution must be dimensions separated by a 'x': 1280x720, etc." &&
+ exit 1 ;;
+ p) echo "Purge old build files in $cache? [y/N]"
+ read -r confirm
+ echo "$confirm" | grep -iq "^y$" && rm -rf "$cache" && echo "Done."
+ exit ;;
+ v) verbose=True ;;
+ *) echo "$(basename "$0") usage:
+ -i input timecode list (required)
+ -a audio file
+ -c color of background (use html names, black is default)
+ -t text color for text slides (white is default)
+ -s text font size for text slides (150 is default)
+ -f text font for text slides (sans serif is default)
+ -o output video file
+ -e if no audio given, the time in seconds that the last slide will be shown (5 is default)
+ -x resolution (1920x1080 is default)
+ -d tmp directory
+ -r rerun imagemagick commands even if done previously (in case files or background has changed)
+ -p purge old build files instead of running
+ -v be verbose" && exit 1
+
+esac done
+
+# Check that the input file looks like it should.
+{ head -n 1 "$file" 2>/dev/null | grep -q "^00:00:00 " ;} || {
+ echo "Give an input file with -i." &&
+ echo "The file should look as this example:
+
+00:00:00 first_image.jpg
+00:00:03 otherdirectory/next_image.jpg
+00:00:09 this_image_starts_at_9_seconds.jpg
+etc...
+
+Timecodes and filenames must be separated by Tabs." &&
+ exit 1
+ }
+
+if [ -n "${audio+x}" ]; then
+ # Check that the audio file looks like an actual audio file.
+ case "$(file --dereference --brief --mime-type -- "$audio")" in
+ audio/*) ;;
+ *) echo "That doesn't look like an audio file."; exit 1 ;;
+ esac
+ totseconds="$(date '+%s' -d $(ffmpeg -i "$audio" 2>&1 | awk '/Duration/ {print $2}' | sed s/,//))"
+ endtime="$((totseconds-seconds))"
+fi
+
+prepdir="${prepdir:-$cache/$file}"
+outfile="${outfile:-$file.mp4}"
+prepfile="$prepdir/$file.prep"
+
+[ -n "${verbose+x}" ] && echo "Preparing images... May take a while depending on the number of files."
+mkdir -p "$prepdir"
+
+{
+while read -r x;
+do
+ # Get the time from the first column.
+ time="${x%% *}"
+ seconds="$(date '+%s' -d "$time")"
+ # Duration is not used on the first looped item.
+ duration="$((seconds - prevseconds))"
+
+ # Get the filename/text content from the rest.
+ content="${x#* }"
+ base="$(basename "$content")"
+ base="${base%.*}.jpg"
+
+ if [ -f "$content" ]; then
+ # If images have already been made in a previous run, do not recreate
+ # them unless -r was given.
+ { [ ! -f "$prepdir/$base" ] || [ -n "${redo+x}" ] ;} &&
+ convert -size "${res:-1920x1080}" canvas:"${bgc:-black}" -gravity center "$content" -resize 1920x1080 -composite "$prepdir/$base"
+ else
+ { [ ! -f "$prepdir/$base" ] || [ -n "${redo+x}" ] ;} &&
+ convert -size "${res:-1920x1080}" -background "${bgc:-black}" -fill "${fgc:-white}" -font "${font:-Sans}" -pointsize "${ppt:-150}" -gravity center label:"$content" "$prepdir/$base"
+ fi
+
+ # If the first line, do not write yet.
+ [ "$time" = "00:00:00" ] || echo "file '$prevbase'
+duration $duration"
+
+ # Keep the information required for the next file.
+ prevbase="$base"
+ prevtime="$time"
+ prevseconds="$(date '+%s' -d "$prevtime")"
+done < "$file"
+# Do last file which must be given twice as follows
+echo "file '$base'
+duration ${endtime:-5}
+file '$base'"
+} > "$prepfile"
+if [ -n "${audio+x}" ]; then
+ ffmpeg -hide_banner -y -f concat -safe 0 -i "$prepfile" -i "$audio" -c:a aac -vsync vfr -c:v libx264 -pix_fmt yuv420p "$outfile"
+else
+ ffmpeg -hide_banner -y -f concat -safe 0 -i "$prepfile" -vsync vfr -c:v libx264 -pix_fmt yuv420p "$outfile"
+fi
+
+# Might also try:
+# -vf "fps=${fps:-24},format=yuv420p" "$outfile"
+# but has given some problems.
diff --git a/socialscan b/socialscan
new file mode 100755
index 0000000..d20e2f3
--- /dev/null
+++ b/socialscan
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from socialscan.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/statusbar/sb-battery b/statusbar/sb-battery
new file mode 100755
index 0000000..93cbe08
--- /dev/null
+++ b/statusbar/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/statusbar/sb-clock b/statusbar/sb-clock
new file mode 100755
index 0000000..d25e8d0
--- /dev/null
+++ b/statusbar/sb-clock
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+clock=$(date '+%I')
+
+case "$clock" in
+ "00") icon="πŸ•›" ;;
+ "01") icon="πŸ•" ;;
+ "02") icon="πŸ•‘" ;;
+ "03") icon="πŸ•’" ;;
+ "04") icon="πŸ•“" ;;
+ "05") icon="πŸ•”" ;;
+ "06") icon="πŸ••" ;;
+ "07") icon="πŸ•–" ;;
+ "08") icon="πŸ•—" ;;
+ "09") icon="πŸ•˜" ;;
+ "10") icon="πŸ•™" ;;
+ "11") icon="πŸ•š" ;;
+ "12") icon="πŸ•›" ;;
+esac
+
+case $BLOCK_BUTTON in
+ 1) notify-send "This Month" "$(cal --color=always | sed "s/..7m/<b><span color=\"red\">/;s/..27m/<\/span><\/b>/")" && notify-send "Appointments" "$(calcurse -d3)" ;;
+ 2) setsid -f "$TERMINAL" -e calcurse ;;
+ 3) notify-send "πŸ“… Time/date module" "\- Left click to show upcoming appointments for the next three days via \`calcurse -d3\` and show the month via \`cal\`
+- Middle click opens calcurse if installed" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+date "+%Y %b %d (%a) $icon%I:%M%p"
diff --git a/statusbar/sb-cpu b/statusbar/sb-cpu
new file mode 100755
index 0000000..1572b52
--- /dev/null
+++ b/statusbar/sb-cpu
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "πŸ–₯ CPU hogs" "$(ps axch -o cmd:15,%cpu --sort=-%cpu | head)\\n(100% per core)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "πŸ–₯ CPU module " "\- Shows CPU temperature.
+- Click to show intensive processes.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+sensors | awk '/Core 0/ {print "🌑" $3}'
diff --git a/statusbar/sb-cpubars b/statusbar/sb-cpubars
new file mode 100755
index 0000000..297424e
--- /dev/null
+++ b/statusbar/sb-cpubars
@@ -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/statusbar/sb-disk b/statusbar/sb-disk
new file mode 100755
index 0000000..e947509
--- /dev/null
+++ b/statusbar/sb-disk
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Status bar module for disk space
+# $1 should be drive mountpoint, otherwise assumed /.
+
+location=${1:-/}
+
+[ -d "$location" ] || exit
+
+case $BLOCK_BUTTON in
+ 1) notify-send "πŸ’½ Disk space" "$(df -h --output=target,used,size)" ;;
+ 3) notify-send "πŸ’½ Disk module" "\- Shows used hard drive space.
+- Click to show all disk info." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+case "$location" in
+ "/home"* ) icon="🏠" ;;
+ "/mnt"* ) icon="πŸ’Ύ" ;;
+ *) icon="πŸ–₯";;
+esac
+
+printf "%s: %s\n" "$icon" "$(df -h "$location" | awk ' /[0-9]/ {print $3 "/" $2}')"
diff --git a/statusbar/sb-doppler b/statusbar/sb-doppler
new file mode 100755
index 0000000..dabf18b
--- /dev/null
+++ b/statusbar/sb-doppler
@@ -0,0 +1,260 @@
+#!/bin/sh
+
+# Show a Doppler RADAR of a user's preferred location.
+
+secs=600 # Download a new doppler radar if one hasn't been downloaded in $secs seconds.
+radarloc="${XDG_CACHE_HOME:-$HOME/.cache}/radar"
+doppler="${XDG_CACHE_HOME:-$HOME/.cache}/doppler.gif"
+
+pickloc() { chosen="$(echo "US: Northeast
+US: Southeast
+US: PacNorthWest
+US: PacSouthWest
+US: UpperMissVly
+US: SouthMissVly
+US: SouthPlains
+US: NorthRockies
+US: SouthRockies
+US: Alaska
+US: Carib
+US: Hawaii
+US: CentGrLakes
+US: Conus-Large
+US: KABR: Aberdeen, SD
+US: KBIS: Bismarck, ND
+US: KFTG: Denver/Boulder, CO
+US: KDMX: Des Moines, IA
+US: KDTX: Detroit, MI
+US: KDDC: Dodge City, KS
+US: KDLH: Duluth, MN
+US: KCYS: Cheyenne, WY
+US: KLOT: Chicago, IL
+US: KGLD: Goodland, KS
+US: KUEX: Hastings, NE
+US: KGJX: Grand Junction, CO
+US: KGRR: Grand Rapids, MI
+US: KMVX: Fargo/Grand Forks, ND
+US: KGRB: Green Bay, WI
+US: KIND: Indianapolis, IN
+US: KJKL: Jackson, KY
+US: KARX: La Crosse, WI
+US: KILX: Lincoln/Central Illinois, IL
+US: KLVX: Louisville, KY
+US: KMQT: Marquette
+US: KMKX: Milwaukee, WI
+US: KMPX: Minneapolis, MN
+US: KAPX: Gaylord/Alpena, MI
+US: KLNX: North Platte, NE
+US: KIWX: N. Webster/Northern, IN
+US: KOAX: Omaha, NE
+US: KPAH: Paducah, KY
+US: KEAX: Pleasant Hill, MO
+US: KPUX: Pueblo, CO
+US: KDVN: Quad Cities, IA
+US: KUDX: Rapid City, SD
+US: KRIW: Riverton, WY
+US: KSGF: Springfield, MO
+US: KLSX: St. LOUIS, MO
+US: KFSD: Sioux Falls, IA
+US: KTWX: Topeka, KS
+US: KICT: Wichita, KS
+US: KVWX: Paducah, KY
+US: ICAO: Responsible Wfo
+US: KLTX: WILMINGTON, NC
+US: KCCX: State College/Central, PA
+US: KLWX: Sterling, VA
+US: KFCX: Blacksburg/Roanoke, VA
+US: KRAX: Raleigh/Durham, NC
+US: KGYX: Portland, ME
+US: KDIX: Mt Holly/Philadelphia, PA
+US: KPBZ: Pittsburgh, PA
+US: KAKQ: Wakefield, VA
+US: KMHX: Morehead City, NC
+US: KGSP: Greer/Greenville/Sprtbg, SC
+US: KILN: Wilmington/Cincinnati, OH
+US: KCLE: Cleveland, OH
+US: KCAE: Columbia, SC
+US: KBGM: Binghamton, NY
+US: KENX: Albany, NY
+US: KBUF: Buffalo, NY
+US: KCXX: Burlington, VT
+US: KCBW: Caribou, ME
+US: KBOX: Boston /Taunton, MA
+US: KOKX: New York City, NY
+US: KCLX: Charleston, SC
+US: KRLX: Charleston, WV
+US: ICAO: Responsible WFO
+US: KBRO: Brownsville, TX
+US: KABX: Albuquerque, NM
+US: KAMA: Amarillo, TX
+US: KFFC: Peachtree City/Atlanta, GA
+US: KEWX: Austin/Sanantonio, TX
+US: KBMX: Birmingham, AL
+US: KCRP: Corpus Christi, TX
+US: KFWS: Dallas / Ft. Worth, TX
+US: KEPZ: El Paso, TX
+US: KHGX: Houston/ Galveston, TX
+US: KJAX: Jacksonville, FL
+US: KBYX: Key West, FL
+US: KMRX: Morristown/knoxville, TN
+US: KLBB: Lubbock, TX
+US: KLZK: Little Rock, AR
+US: KLCH: Lake Charles, LA
+US: KOHX: Nashville, TN
+US: KMLB: Melbourne, FL
+US: KNQA: Memphis, TN
+US: KAMX: Miami, FL
+US: KMAF: Midland/odessa, TX
+US: KTLX: Norman, OK
+US: KHTX: Huntsville, AL
+US: KMOB: Mobile, AL
+US: KTLH: Tallahassee, FL
+US: KTBW: Tampa Bay Area, FL
+US: KSJT: San Angelo, TX
+US: KINX: Tulsa, OK
+US: KSRX: Tulsa, OK
+US: KLIX: New Orleans/slidell, LA
+US: KDGX: Jackson, MS
+US: KSHV: Shreveport, LA
+US: ICAO: Responsible WFO
+US: KLGX: Seattle / Tacoma, WA
+US: KOTX: Spokane, WA
+US: KEMX: Tucson, AZ
+US: KYUX: Phoenix, AZ
+US: KNKX: San Diego, CA
+US: KMUX: Monterey/san Francisco, CA
+US: KHNX: San Joaquin/hanford, CA
+US: KSOX: San Diego, CA
+US: KATX: Seattle / Tacoma, WA
+US: KIWA: Phoenix, AZ
+US: KRTX: Portland, OR
+US: KSFX: Pocatello, ID
+US: KRGX: Reno, NV
+US: KDAX: Sacramento, CA
+US: KMTX: Salt Lake City, UT
+US: KPDT: Pendleton, OR
+US: KMSX: Missoula, MT
+US: KESX: Las Vegas, NV
+US: KVTX: Los Angeles, CA
+US: KMAX: Medford, OR
+US: KFSX: Flagstaff, AZ
+US: KGGW: Glasgow, MT
+US: KLRX: Elko, NV
+US: KBHX: Eureka, CA
+US: KTFX: Great Falls, MT
+US: KCBX: Boise, ID
+US: KBLX: Billings, MT
+US: KICX: Salt Lake City, UT
+US: ICAO: Responsible Wfo W/ MSCF
+US: PABC: Anchorage, AK
+US: PAPD: Fairbanks, AK
+US: PHKM: Honolulu, HI
+US: PAHG: Anchorage, AK
+US: PAKC: Anchorage, AK
+US: PAIH: Anchorage, AK
+US: PHMO: Honolulu, HI
+US: PAEC: Fairbanks, AK
+US: TJUA: San Juan, PR
+US: PACG: Juneau, AK
+US: PHKI: Honolulu, HI
+US: PHWA: Honolulu, HI
+US: ICAO: Responsible Wfo W/ MSCF
+US: KFDR: Norman, OK
+US: PGUA: Guam
+US: KBBX: Sacramento, CA
+US: KFDX: Albuquerque, NM
+US: KGWX: Jackson, MS
+US: KDOX: Wakefield, VA
+US: KDYX: San Angelo, TX
+US: KEYX: Las Vegas, NV
+US: KEVX: Mobile, AL
+US: KHPX: Paducah, KY
+US: KTYX: Burlington, VT
+US: KGRK: Dallas / Ft. Worth, TX
+US: KPOE: Lake Charles, LA
+US: KEOX: Tallahassee, FL
+US: KHDX: El Paso, TX
+US: KDFX: San Antonio, TX
+US: KMXX: Birmingham, AL
+US: KMBX: Bismarck, ND
+US: KVAX: Jacksonville, FL
+US: KJGX: Peachtree City/atlanta, GA
+US: KVNX: Norman, OK
+US: KVBX: Vandenberg Afb: Orcutt, CA
+EU: Europe
+EU: GB: Great Brittain
+EU: SCAN: Scandinavia
+EU: ALPS: The Alps
+EU: NL: The Netherlands
+EU: DE: Germany
+EU: SP: Spain
+EU: FR: France
+EU: IT: Italy
+EU: PL: Poland
+EU: GR: Greece
+EU: TU: Turkey
+EU: RU: Russia
+EU: BA: Bahrain
+EU: BC: Botswana
+EU: SE: Republic of Seychelles
+EU: HU: Hungary
+EU: UK: Ukraine
+AF: AF: Africa
+AF: WA: West Africa
+AF: ZA: South Africa
+AF: DZ: Algeria
+AF: CE: Canary Islands
+AF: NG: Nigeria
+AF: TD: Chad
+AF: CG: Democratic Republic of Congo
+AF: EG: Egypt
+AF: ET: Ethiopia
+AF: CM: Cameroon
+AF: IS: Israel
+AF: LY: Libya
+AF: MG: Madagascar
+AF: MO: Morocco
+AF: BW: Namibia
+AF: SA: Saudi Arabia
+AF: SO: Somalia
+AF: SD: Sudan
+AF: TZ: Tanzania
+AF: TN: Tunisia
+AF: ZM: Zambia
+AF: KE: Kenya
+AF: AO: Angola" | dmenu -r -i -l 50 -p "Select a radar to use as default:" | tr "[:lower:]" "[:upper:]")"
+
+# Set continent code and radar code.
+continentcode=$(echo "$chosen" | sed "s/:.*//")
+radarcode=$(echo "$chosen" | sed "s/..: // ; s/:.*//")
+
+# Sanity check of selection and ensure user did not escape.
+echo "$radarcode" | grep -q "^[A-Z]\+$" && printf "%s,%s\\n" "$continentcode" "$radarcode" > "$radarloc" ;}
+
+getdoppler() {
+ cont="$(sed "s/,.*//" "$radarloc")"
+ loc="$(cut -c 4- "$radarloc")"
+ notify-send "🌦️ Doppler RADAR" "Pulling most recent Doppler RADAR for $loc."
+ if [ "$cont" = "US" ] ; then
+ curl -sL "https://radar.weather.gov/ridge/lite/${loc}_loop.gif" > "$doppler" ;
+ elif [ "$cont" = "EU" ] ; then
+ curl -sL "https://api.sat24.com/animated/${loc}/rainTMC/2/" > "$doppler" ;
+ elif [ "$cont" = "AF" ] ; then
+ curl -sL "https://api.sat24.com/animated/${loc}/rain/2/" > "$doppler" ;
+ fi
+}
+
+showdoppler() { setsid -f mpv --no-osc --loop=inf --no-terminal "$doppler" ;}
+
+case $BLOCK_BUTTON in
+ 1) [ ! -f "$radarloc" ] && pickloc && getdoppler
+ [ $(($(date '+%s') - $(stat -c %Y "$doppler"))) -gt "$secs" ] && getdoppler
+ showdoppler ;;
+ 2) pickloc && getdoppler && showdoppler ;;
+ 3) notify-send "πŸ—ΊοΈ Doppler RADAR module" "\- Left click for local Doppler RADAR.
+- Middle click to update RADAR location.
+After $secs seconds, new clicks will also automatically update the doppler RADAR." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo πŸ—ΊοΈ
diff --git a/statusbar/sb-forecast b/statusbar/sb-forecast
new file mode 100755
index 0000000..7b8416e
--- /dev/null
+++ b/statusbar/sb-forecast
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Displays todays precipication chance (β˜”) and daily low (πŸ₯Ά) and high (🌞).
+# Usually intended for the statusbar.
+
+# If we have internet, get a weather report from wttr.in and store it locally.
+# You could set up a shell alias to view the full file in a pager in the
+# terminal if desired. This function will only be run once a day when needed.
+weatherreport="${XDG_DATA_HOME:-$HOME/.local/share}/weatherreport"
+getforecast() { curl -sf "wttr.in/$LOCATION" > "$weatherreport" || exit 1 ;}
+
+# Some very particular and terse stream manipulation. We get the maximum
+# precipitation chance and the daily high and low from the downloaded file and
+# display them with coresponding emojis.
+showweather() { printf "%s" "$(sed '16q;d' "$weatherreport" |
+ grep -wo "[0-9]*%" | sort -rn | sed "s/^/β˜”/g;1q" | tr -d '\n')"
+sed '13q;d' "$weatherreport" | grep -o "m\\([-+]\\)*[0-9]\\+" | sed 's/+//g' | sort -n -t 'm' -k 2n | sed -e 1b -e '$!d' | tr '\n|m' ' ' | awk '{print " πŸ₯Ά" $1 "Β°","🌞" $2 "Β°"}' ;}
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e less -Srf "$weatherreport" ;;
+ 2) getforecast && showweather ;;
+ 3) notify-send "🌈 Weather module" "\- Left click for full forecast.
+- Middle click to update forecast.
+β˜”: Chance of rain/snow
+πŸ₯Ά: Daily low
+🌞: Daily high" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# The test if our forcecast is updated to the day. If it isn't download a new
+# weather report from wttr.in with the above function.
+[ "$(stat -c %y "$weatherreport" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
+ getforecast
+
+showweather
diff --git a/statusbar/sb-help-icon b/statusbar/sb-help-icon
new file mode 100755
index 0000000..8fa4a52
--- /dev/null
+++ b/statusbar/sb-help-icon
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# The clickable help menu. Middle click to restart wm.
+
+# If dwm is running, use dwm's readme and restart.
+pidof dwm >/dev/null &&
+ READMEFILE=/usr/local/share/dwm/larbs.mom
+ restartwm() { pkill -HUP dwm ;} ||
+ restartwm() { i3 restart ;}
+
+case $BLOCK_BUTTON in
+ 1) groff -mom "${READMEFILE:-${XDG_DATA_HOME:-$HOME/.local/share}/larbs/readme.mom}" -Tpdf | zathura - ;;
+ 2) restartwm ;;
+ 3) notify-send "❓ Help module" "\- Left click to open LARBS guide.
+- Middle click to refresh window manager." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac; echo "❓"
diff --git a/statusbar/sb-internet b/statusbar/sb-internet
new file mode 100755
index 0000000..94b7da2
--- /dev/null
+++ b/statusbar/sb-internet
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Show wifi πŸ“Ά and percent strength or πŸ“‘ if none.
+# Show 🌐 if connected to ethernet or ❎ if none.
+# Show πŸ”’ if a vpn connection is active
+
+case $BLOCK_BUTTON in
+ 1) "$TERMINAL" -e nmtui; pkill -RTMIN+4 dwmblocks ;;
+ 3) notify-send "🌐 Internet module" "\- Click to connect
+❌: wifi disabled
+πŸ“‘: no wifi connection
+πŸ“Ά: wifi connection with quality
+❎: no ethernet
+🌐: ethernet working
+πŸ”’: vpn is active
+" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+if grep -xq 'up' /sys/class/net/w*/operstate 2>/dev/null ; then
+ wifiicon="$(awk '/^\s*w/ { print "πŸ“Ά", int($3 * 100 / 70) "% " }' /proc/net/wireless)"
+elif grep -xq 'down' /sys/class/net/w*/operstate 2>/dev/null ; then
+ grep -xq '0x1003' /sys/class/net/w*/flags && wifiicon="πŸ“‘ " || wifiicon="❌ "
+fi
+
+printf "%s%s%s\n" "$wifiicon" "$(sed "s/down/❎/;s/up/🌐/" /sys/class/net/e*/operstate 2>/dev/null)" "$(sed "s/.*/πŸ”’/" /sys/class/net/tun*/operstate 2>/dev/null)"
diff --git a/statusbar/sb-iplocate b/statusbar/sb-iplocate
new file mode 100755
index 0000000..02adab8
--- /dev/null
+++ b/statusbar/sb-iplocate
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Gets your public ip address checks which country you are in and
+# displays that information in the statusbar
+#
+# https://www.maketecheasier.com/ip-address-geolocation-lookups-linux/
+
+ifinstalled "geoip" || exit
+addr="$(curl ifconfig.me 2>/dev/null)" || exit
+grep "flag: " "${XDG_DATA_HOME:-$HOME/.local/share}/larbs/emoji" | grep "$(geoiplookup "$addr" | sed 's/.*, //')" | sed "s/flag: //;s/;.*//"
diff --git a/statusbar/sb-kbselect b/statusbar/sb-kbselect
new file mode 100755
index 0000000..f0c923f
--- /dev/null
+++ b/statusbar/sb-kbselect
@@ -0,0 +1,16 @@
+#!/bin/sh
+# works on any init system
+# requirements: dmenu, xorg-setxkbmap
+kb="$(setxkbmap -query | grep -oP 'layout:\s*\K\w+')" || exit 1
+
+case $BLOCK_BUTTON in
+ 1) kb_choice="$(awk '/! layout/{flag=1; next} /! variant/{flag=0} flag {print $2, "- " $1}' /usr/share/X11/xkb/rules/base.lst | dmenu -l 15)"
+ kb="$(echo "$kb_choice" | awk '{print $3}')"
+ setxkbmap "$kb"
+ pkill -RTMIN+30 "${STATUSBAR:-dwmblocks}";;
+ 3) notify-send "⌨ Keyboard/language module" "$(printf "%s" "\- Current layout: $(setxkbmap -query | grep -oP 'layout:\s*\K\w+')")
+- Left click to change keyboard.";;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo "$kb"
diff --git a/statusbar/sb-mailbox b/statusbar/sb-mailbox
new file mode 100755
index 0000000..2132184
--- /dev/null
+++ b/statusbar/sb-mailbox
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Displays number of unread mail and an loading icon if updating.
+# When clicked, brings up `neomutt`.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e neomutt ;;
+ 2) setsid -f mw -Y >/dev/null ;;
+ 3) notify-send "πŸ“¬ Mail module" "\- Shows unread mail
+- Shows πŸ”ƒ if syncing mail
+- Left click opens neomutt
+- Middle click syncs mail" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+unread="$(find "${XDG_DATA_HOME:-$HOME/.local/share}"/mail/*/[Ii][Nn][Bb][Oo][Xx]/new/* -type f | wc -l 2>/dev/null)"
+
+pidof mbsync >/dev/null 2>&1 && icon="πŸ”ƒ"
+
+[ "$unread" = "0" ] && [ "$icon" = "" ] || echo "πŸ“¬$unread$icon"
diff --git a/statusbar/sb-memory b/statusbar/sb-memory
new file mode 100755
index 0000000..01d3daf
--- /dev/null
+++ b/statusbar/sb-memory
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+case $BLOCK_BUTTON in
+ 1) notify-send "🧠 Memory hogs" "$(ps axch -o cmd:15,%mem --sort=-%mem | head)" ;;
+ 2) setsid -f "$TERMINAL" -e htop ;;
+ 3) notify-send "🧠 Memory module" "\- Shows Memory Used/Total.
+- Click to show memory hogs.
+- Middle click to open htop." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+free --mebi | sed -n '2{p;q}' | awk '{printf ("🧠%2.2fGiB/%2.2fGiB\n", ( $3 / 1024), ($2 / 1024))}'
diff --git a/statusbar/sb-moonphase b/statusbar/sb-moonphase
new file mode 100755
index 0000000..fab8b4d
--- /dev/null
+++ b/statusbar/sb-moonphase
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Shows the current moon phase.
+
+moonfile="${XDG_DATA_HOME:-$HOME/.local/share}/moonphase"
+
+[ "$(stat -c %y "$moonfile" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
+ { curl -sf "wttr.in/?format=%m" > "$moonfile" || exit 1 ;}
+
+icon="$(cat "$moonfile")"
+
+case "$icon" in
+ πŸŒ‘) name="New" ;;
+ πŸŒ’) name="Waxing Crescent" ;;
+ πŸŒ“) name="First Quarter" ;;
+ πŸŒ”) name="Waxing Gibbous" ;;
+ πŸŒ•) name="Full" ;;
+ πŸŒ–) name="Waning Gibbous" ;;
+ πŸŒ—) name="Last Quarter" ;;
+ 🌘) name="Waning Crescent" ;;
+ *) exit 1 ;;
+esac
+
+echo "${icon-?}"
+
+case $BLOCK_BUTTON in
+ 3) notify-send "🌜 Moon phase module" "Displays current moon phase.
+- πŸŒ‘: New
+- πŸŒ’: Waxing Crescent
+- πŸŒ“: First Quarter
+- πŸŒ”: Waxing Gibbous
+- πŸŒ•: Full
+- πŸŒ–: Waning Gibbous
+- πŸŒ—: Last Quarter
+- 🌘: Waning Crescent" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/statusbar/sb-mpdup b/statusbar/sb-mpdup
new file mode 100755
index 0000000..af81a7d
--- /dev/null
+++ b/statusbar/sb-mpdup
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# This loop will update the mpd statusbar module whenever a command changes the
+# music player's status. mpd must be running on X's start for this to work.
+
+while : ; do
+ mpc idle >/dev/null && kill -45 "$(pidof "${STATUSBAR:-dwmblocks}")" || break
+done
diff --git a/statusbar/sb-music b/statusbar/sb-music
new file mode 100755
index 0000000..7ea7032
--- /dev/null
+++ b/statusbar/sb-music
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+filter() { mpc | sed "/^volume:/d;s/\\&/&amp;/g;s/\\[paused\\].*/⏸/g;/\\[playing\\].*/d;/^ERROR/Q" | paste -sd ' ' -;}
+
+pidof -x sb-mpdup >/dev/null 2>&1 || sb-mpdup >/dev/null 2>&1 &
+
+case $BLOCK_BUTTON in
+ 1) mpc status | filter ; setsid -f "$TERMINAL" -e ncmpcpp ;; # right click, pause/unpause
+ 2) mpc toggle | filter ;; # right click, pause/unpause
+ 3) mpc status | filter ; notify-send "🎡 Music module" "\- Shows mpd song playing.
+- ⏸ when paused.
+- Left click opens ncmpcpp.
+- Middle click pauses.
+- Scroll changes track.";; # right click, pause/unpause
+ 4) mpc prev | filter ;; # scroll up, previous
+ 5) mpc next | filter ;; # scroll down, next
+ 6) mpc status | filter ; "$TERMINAL" -e "$EDITOR" "$0" ;;
+ *) mpc status | filter ;;
+esac
diff --git a/statusbar/sb-nettraf b/statusbar/sb-nettraf
new file mode 100755
index 0000000..c71d38e
--- /dev/null
+++ b/statusbar/sb-nettraf
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Module showing network traffic. Shows how much data has been received (RX) or
+# transmitted (TX) since the previous time this script ran. So if run every
+# second, gives network traffic per second.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e bmon ;;
+ 3) notify-send "🌐 Network traffic module" "πŸ”»: Traffic received
+πŸ”Ί: Traffic transmitted" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+update() {
+ sum=0
+ for arg; do
+ read -r i < "$arg"
+ sum=$(( sum + i ))
+ done
+ cache=${XDG_CACHE_HOME:-$HOME/.cache}/${1##*/}
+ [ -f "$cache" ] && read -r old < "$cache" || old=0
+ printf %d\\n "$sum" > "$cache"
+ printf %d\\n $(( sum - old ))
+}
+
+rx=$(update /sys/class/net/[ew]*/statistics/rx_bytes)
+tx=$(update /sys/class/net/[ew]*/statistics/tx_bytes)
+
+printf "πŸ”»%4sB πŸ”Ί%4sB\\n" $(numfmt --to=iec $rx $tx)
diff --git a/statusbar/sb-news b/statusbar/sb-news
new file mode 100755
index 0000000..fe701db
--- /dev/null
+++ b/statusbar/sb-news
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Displays number of unread news items and an loading icon if updating.
+# When clicked, brings up `newsboat`.
+
+case $BLOCK_BUTTON in
+ 1) setsid "$TERMINAL" -e newsboat ;;
+ 2) setsid -f newsup >/dev/null exit ;;
+ 3) notify-send "πŸ“° News module" "\- Shows unread news items
+- Shows πŸ”ƒ if updating with \`newsup\`
+- Left click opens newsboat
+- Middle click syncs RSS feeds
+<b>Note:</b> Only one instance of newsboat (including updates) may be running at a time." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+ cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ if($1>0) print "πŸ“°" $1}')$(cat "${XDG_CONFIG_HOME:-$HOME/.config}"/newsboat/.update 2>/dev/null)"
diff --git a/statusbar/sb-pacpackages b/statusbar/sb-pacpackages
new file mode 100755
index 0000000..37ebed3
--- /dev/null
+++ b/statusbar/sb-pacpackages
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Displays number of upgradeable packages.
+# For this to work, have a `pacman -Sy` command run in the background as a
+# cronjob every so often as root. This script will then read those packages.
+# When clicked, it will run an upgrade via pacman.
+#
+# Add the following text as a file in /usr/share/libalpm/hooks/statusbar.hook:
+#
+# [Trigger]
+# Operation = Upgrade
+# Type = Package
+# Target = *
+#
+# [Action]
+# Description = Updating statusbar...
+# When = PostTransaction
+# Exec = /usr/bin/pkill -RTMIN+8 dwmblocks # Or i3blocks if using i3.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e sb-popupgrade ;;
+ 2) notify-send "$(/usr/bin/pacman -Qu)" ;;
+ 3) notify-send "🎁 Upgrade module" "πŸ“¦: number of upgradable packages
+- Left click to upgrade packages
+- Middle click to show upgradable packages" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+pacman -Qu | grep -Fcv "[ignored]" | sed "s/^/πŸ“¦/;s/^πŸ“¦0$//g"
diff --git a/statusbar/sb-popupgrade b/statusbar/sb-popupgrade
new file mode 100755
index 0000000..29d6230
--- /dev/null
+++ b/statusbar/sb-popupgrade
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+printf "Beginning upgrade.\\n"
+
+yay -Syu
+pkill -RTMIN+8 "${STATUSBAR:-dwmblocks}"
+
+printf "\\nUpgrade complete.\\nPress <Enter> to exit window.\\n\\n"
+read -r _
diff --git a/statusbar/sb-price b/statusbar/sb-price
new file mode 100755
index 0000000..42c84c1
--- /dev/null
+++ b/statusbar/sb-price
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Usage:
+# price <url> <Name of currency> <icon> <Price to show in>
+# price bat "Basic Attention Token" 🦁
+# When the name of the currency is multi-word, put it in quotes.
+
+[ -z "$3" ] && exit 1
+
+# use $4 as currency, if not passed in use "usd" as default
+currency="${4:-usd}"
+interval="@14d" # History contained in chart preceded by '@' (7d = 7 days)
+dir="${XDG_DATA_HOME:-$HOME/.local/share}/crypto-prices"
+pricefile="$dir/$1-$currency"
+chartfile="$dir/$1-$currency-chart"
+
+updateprice() { temp="$(mktemp)"
+ curl -s "$currency.rate.sx/1$1" > "$temp" &&
+ mv -f "$temp" "$pricefile" &&
+ curl -s "$currency.rate.sx/$1$interval" > "$temp" &&
+ mv -f "$temp" "$chartfile" ;}
+
+[ -d "$dir" ] || mkdir -p "$dir"
+
+[ "$(stat -c %x "$pricefile" 2>/dev/null | cut -d' ' -f1)" != "$(date '+%Y-%m-%d')" ] &&
+ updateprice "$1"
+
+case $BLOCK_BUTTON in
+ 1) setsid "$TERMINAL" -e less -Srf "$chartfile" ;;
+ 2) notify-send -u low "$3 Updating..." "Updating $2 price..."
+ updateprice "$1" && notify-send "$3 Update complete." "$2 price is now
+\$$(cat "$pricefile")" ;;
+ 3) uptime="$(date -d "$(stat -c %x "$pricefile")" '+%D at %T' | sed "s|$(date '+%D')|Today|")"
+ notify-send "$3 $2 module" "\- <b>Exact price: \$$(cat "$pricefile")</b>
+- Left click for chart of changes.
+- Middle click to update.
+- Shows πŸ”ƒ if updating prices.
+- <b>Last updated:
+ $uptime</b>" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+case "$currency" in
+ usd) symb="$" ;;
+ gbp) symb="Β£" ;;
+ eur) symb="€" ;;
+ btc) symb="β‚Ώ" ;;
+esac
+
+printf "$3$symb%0.2f$after" "$(cat "$pricefile")"
diff --git a/statusbar/sb-tasks b/statusbar/sb-tasks
new file mode 100755
index 0000000..586300e
--- /dev/null
+++ b/statusbar/sb-tasks
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Originally by Andr3as07 <https://github.com/Andr3as07>
+# Some changes by Luke
+# Rebuild by Tenyun
+
+# This block displays the number running background tasks. Requires tsp.
+
+num=$(tsp -l | awk -v numr=0 -v numq=0 '{if (/running/)numr++; if (/queued/)numq++} END{print numr+numq"("numq")"}')
+
+# Handle mouse clicks
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e tsp -l ;;
+ 3) notify-send "Tasks module" "πŸ€–: number of running/queued background tasks
+- Left click opens tsp" ;; # Right click
+ 2) $EDITOR "$0" ;; # Middle click
+esac
+
+[ "$num" != "0(0)" ] &&
+ echo "πŸ€–$num"
diff --git a/statusbar/sb-torrent b/statusbar/sb-torrent
new file mode 100755
index 0000000..6527005
--- /dev/null
+++ b/statusbar/sb-torrent
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+transmission-remote -l | grep % |
+ sed " # The letters are for sorting and will not appear.
+ s/.*Stopped.*/A πŸ›‘/;
+ s/.*Seeding.*/Z 🌱/;
+ s/.*100%.*/N βœ…/;
+ s/.*Idle.*/B πŸ•°οΈ/;
+ s/.*Uploading.*/L ⬆️/;
+ s/.*%.*/M ⬇️/" |
+ sort -h | uniq -c | awk '{print $3 $1}' | paste -sd ' ' -
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e tremc ;;
+ 2) td-toggle ;;
+ 3) notify-send "🌱 Torrent module" "\- Left click to open tremc.
+- Middle click to toggle transmission.
+- Shift click to edit script.
+Module shows number of torrents:
+πŸ›‘: paused
+πŸ•°: idle (seeds needed)
+πŸ”Ό: uploading (unfinished)
+πŸ”½: downloading
+βœ…: done
+🌱: done and seeding" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/statusbar/sb-volume b/statusbar/sb-volume
new file mode 100755
index 0000000..3cfdc45
--- /dev/null
+++ b/statusbar/sb-volume
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Prints the current volume or πŸ”‡ if muted.
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e pulsemixer ;;
+ 2) pamixer -t ;;
+ 4) pamixer --allow-boost -i 1 ;;
+ 5) pamixer --allow-boost -d 1 ;;
+ 3) notify-send "πŸ“’ Volume module" "\- Shows volume πŸ”Š, πŸ”‡ if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+[ $(pamixer --get-mute) = true ] && echo πŸ”‡ && exit
+
+vol="$(pamixer --get-volume)"
+
+if [ "$vol" -gt "70" ]; then
+ icon="πŸ”Š"
+elif [ "$vol" -gt "30" ]; then
+ icon="πŸ”‰"
+elif [ "$vol" -gt "0" ]; then
+ icon="πŸ”ˆ"
+else
+ echo πŸ”‡ && exit
+fi
+
+echo "$icon$vol%"
diff --git a/switch_audio b/switch_audio
new file mode 100755
index 0000000..db01fee
--- /dev/null
+++ b/switch_audio
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+#devices
+hdmi="alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1"
+headphone="alsa_output.pci-0000_00_1f.3.analog-stereo"
+
+curr_device="$(pactl get-default-sink)"
+
+if [ "$curr_device" = $hdmi ]
+then
+ pactl set-default-sink $headphone
+else
+ pactl set-default-sink $hdmi
+fi
diff --git a/symilar b/symilar
new file mode 100755
index 0000000..8e62aa6
--- /dev/null
+++ b/symilar
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pylint import run_symilar
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run_symilar())
diff --git a/sysact b/sysact
new file mode 100755
index 0000000..eb9390f
--- /dev/null
+++ b/sysact
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# A dmenu wrapper script for system functions.
+export WM="dwm"
+case "$(readlink -f /sbin/init)" in
+ *systemd*) ctl='systemctl' ;;
+ *) ctl='loginctl' ;;
+esac
+
+wmpid(){ # This function is needed if there are multiple instances of the window manager.
+ tree="$(pstree -ps $$)"
+ tree="${tree#*$WM(}"
+ echo "${tree%%)*}"
+}
+
+case "$(printf "πŸ”’ lock\nπŸšͺ leave $WM\n♻️ renew $WM\n🐻 hibernate\nπŸ”ƒ reboot\nπŸ–₯️shutdown\nπŸ’€ sleep\nπŸ“Ί display off" | dmenu -i -p 'Action: ')" in
+ 'πŸ”’ lock') slock ;;
+ "πŸšͺ leave $WM") kill -TERM "$(wmpid)" ;;
+ "♻️ renew $WM") kill -HUP "$(wmpid)" ;;
+ '🐻 hibernate') slock $ctl hibernate ;;
+ 'πŸ’€ sleep') slock $ctl suspend ;;
+ 'πŸ”ƒ reboot') $ctl reboot -i ;;
+ 'πŸ–₯️shutdown') $ctl poweroff -i ;;
+ 'πŸ“Ί display off') xset dpms force off ;;
+ *) exit 1 ;;
+esac
diff --git a/system_action b/system_action
new file mode 100755
index 0000000..32fe118
--- /dev/null
+++ b/system_action
@@ -0,0 +1,16 @@
+#!/bin/sh
+# A dmenu wrapper script for system functions.
+case "$(readlink -f /sbin/init)" in
+ *systemd*) ctl='systemctl' ;;
+ *) ctl='loginctl' ;;
+esac
+
+case "$(printf "ο€£ lock\nο“’ display off\nο”« logout\n sleep\nο€ž reboot\n shutdown" | dmenu -i -p 'Action: ')" in
+ 'ο€£ lock') slock ;;
+ 'ο“’ display off') xset dpms force off ;;
+ 'ο”« logout') kill -TERM "$(pgrep -u "$USER" "\bdwm$")" ;;
+ ' sleep') slock $ctl suspend ;;
+ 'ο€ž reboot') $ctl reboot ;;
+ ' shutdown') $ctl poweroff ;;
+ *) exit 1 ;;
+esac
diff --git a/tag b/tag
new file mode 100755
index 0000000..8462b99
--- /dev/null
+++ b/tag
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+err() { echo "Usage:
+ tag [OPTIONS] file
+Options:
+ -a: artist/author
+ -t: song/chapter title
+ -A: album/book title
+ -n: track/chapter number
+ -N: total number of tracks/chapters
+ -d: year of publication
+ -g: genre
+ -c: comment
+You will be prompted for title, artist, album and track if not given." && exit 1 ;}
+
+while getopts "a:t:A:n:N:d:g:c:f:" o; do case "${o}" in
+ a) artist="${OPTARG}" ;;
+ t) title="${OPTARG}" ;;
+ A) album="${OPTARG}" ;;
+ n) track="${OPTARG}" ;;
+ N) total="${OPTARG}" ;;
+ d) date="${OPTARG}" ;;
+ g) genre="${OPTARG}" ;;
+ c) comment="${OPTARG}" ;;
+ f) file="${OPTARG}" ;;
+ *) printf "Invalid option: -%s\\n" "$OPTARG" && err ;;
+esac done
+
+shift $((OPTIND - 1))
+
+file="$1"
+
+[ ! -f "$file" ] && echo "Provide file to tag." && err
+
+[ -z "$title" ] && echo "Enter a title." && read -r title
+[ -z "$artist" ] && echo "Enter an artist." && read -r artist
+[ -z "$album" ] && echo "Enter an album." && read -r album
+[ -z "$track" ] && echo "Enter a track number." && read -r track
+
+case "$file" in
+ *.ogg) echo "Title=$title
+Artist=$artist
+Album=$album
+Track=$track
+Total=$total
+Date=$date
+Genre=$genre
+Comment=$comment" | vorbiscomment -w "$file" ;;
+ *.opus) echo "Title=$title
+Artist=$artist
+Album=$album
+Track=$track
+Total=$total
+Date=$date
+Genre=$genre
+Comment=$comment" | opustags -i -S "$file" ;;
+ *.mp3) eyeD3 -Q --remove-all -a "$artist" -A "$album" -t "$title" -n "$track" -N "$total" -Y "$date" "$file" ;;
+ *.flac) echo "TITLE=$title
+ARTIST=$artist
+ALBUM=$album
+TRACKNUMBER=$track
+TOTALTRACKS=$total
+DATE=$date
+GENRE=$genre
+DESCRIPTION=$comment" | metaflac --remove-all-tags --import-tags-from=- "$file" ;;
+ *) echo "File type not implemented yet." ;;
+esac
diff --git a/td-toggle b/td-toggle
new file mode 100755
index 0000000..3c20ea1
--- /dev/null
+++ b/td-toggle
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# If transmission-daemon is running, will ask to kill, else will ask to start.
+
+if pidof transmission-daemon >/dev/null ;
+then
+ [ "$(printf "No\\nYes" | dmenu -i -p "Turn off transmission-daemon?")" = "Yes" ] && killall transmission-da && notify-send "transmission-daemon disabled."
+else
+ ifinstalled transmission-cli || exit
+ [ "$(printf "No\\nYes" | dmenu -i -p "Turn on transmission daemon?")" = "Yes" ] && transmission-daemon && notify-send "transmission-daemon enabled."
+fi
+sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}"
diff --git a/tensorboard b/tensorboard
new file mode 100755
index 0000000..1d31332
--- /dev/null
+++ b/tensorboard
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorboard.main import run_main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(run_main())
diff --git a/texclear b/texclear
new file mode 100755
index 0000000..f38f7be
--- /dev/null
+++ b/texclear
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Clears the build files of a LaTeX/XeLaTeX build.
+# I have vim run this file whenever I exit a .tex file.
+
+case "$1" in
+ *.tex)
+ file=$(readlink -f "$1")
+ dir=$(dirname "$file")
+ base="${file%.*}"
+ find "$dir" -maxdepth 1 -type f -regextype gnu-awk -regex "^$base\\.(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
+ rm -rdf "$dir/_minted-$(basename -- $base)"
+ ;;
+ *) printf "Give .tex file as argument.\\n" ;;
+esac
+
diff --git a/tf_upgrade_v2 b/tf_upgrade_v2
new file mode 100755
index 0000000..8324a59
--- /dev/null
+++ b/tf_upgrade_v2
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.tools.compatibility.tf_upgrade_v2_main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/tflite_convert b/tflite_convert
new file mode 100755
index 0000000..0739b41
--- /dev/null
+++ b/tflite_convert
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.lite.python.tflite_convert import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/toco b/toco
new file mode 100755
index 0000000..0739b41
--- /dev/null
+++ b/toco
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.lite.python.tflite_convert import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/toco_from_protos b/toco_from_protos
new file mode 100755
index 0000000..191ec30
--- /dev/null
+++ b/toco_from_protos
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tensorflow.lite.toco.python.toco_from_protos import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/torwrap b/torwrap
new file mode 100755
index 0000000..8b20ad4
--- /dev/null
+++ b/torwrap
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+ifinstalled tremc transmission-cli || exit
+
+! pidof transmission-daemon >/dev/null && transmission-daemon && notify-send "Starting torrent daemon..."
+
+$TERMINAL -e tremc; pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}"
diff --git a/tqdm b/tqdm
new file mode 100755
index 0000000..af6ce08
--- /dev/null
+++ b/tqdm
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from tqdm.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/transadd b/transadd
new file mode 100755
index 0000000..a598fad
--- /dev/null
+++ b/transadd
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Mimeapp script for adding torrent to transmission-daemon, but will also start the daemon first if not running.
+
+# transmission-daemon sometimes fails to take remote requests in its first moments, hence the sleep.
+
+pidof transmission-daemon >/dev/null || (transmission-daemon && notify-send "Starting transmission daemon..." && sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}")
+
+transmission-remote -a "$@" && notify-send "πŸ”½ Torrent added."
diff --git a/ttx b/ttx
new file mode 100755
index 0000000..cbf3142
--- /dev/null
+++ b/ttx
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from fontTools.ttx import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/tutorialvids b/tutorialvids
new file mode 100755
index 0000000..6d4914b
--- /dev/null
+++ b/tutorialvids
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# This gives the user a list of videos they can select and watch without a
+# browser. If you want to check a tutorial video, it makes it easy. I'll
+# add/remove videos from this list as I go on.
+
+vidlist="
+dwm (window manager) https://videos.lukesmith.xyz/videos/watch/f6b78db7-b368-4647-bc64-28c08fff1988
+pacman (installing/managing programs) https://videos.lukesmith.xyz/videos/watch/8e7cadb9-0fed-47ce-a2a8-6635fa48614b
+status bar https://videos.lukesmith.xyz/videos/watch/a4d5326b-0aac-496e-bfc3-5acd5cee89f0
+sxiv (image viewer) https://videos.lukesmith.xyz/videos/watch/ad4c8d85-90c3-4f3d-a1f3-89129e64a3c2
+st (terminal) https://videos.lukesmith.xyz/videos/watch/efddd39d-bac5-4599-b572-177beb4ce6e8
+i3 (old window manager) https://videos.lukesmith.xyz/videos/watch/b861525c-7ada-40ee-a2bb-b5e1ffe0f48b
+neomutt (email) https://videos.lukesmith.xyz/videos/watch/83122e83-52d9-4278-ae1a-7d1beeb50c8e
+ncmpcpp (music player) https://videos.lukesmith.xyz/videos/watch/b5ac6f0d-a220-4433-88e3-e98fc791dc0a
+newsboat (RSS reader) https://videos.lukesmith.xyz/videos/watch/bd2c3fff-40fa-47ea-aa98-5b1ec0c903b6
+lf (file manager) https://videos.lukesmith.xyz/w/rKeHsF5ZHDNDbR1buUKB1c
+zathura (pdf viewer) https://videos.lukesmith.xyz/videos/watch/c780f75a-11f6-48a9-a191-d079ebc36ea4
+gpg keys https://videos.lukesmith.xyz/videos/watch/040f5530-4830-4583-9ddc-2080b421531b
+calcurse (calendar) https://videos.lukesmith.xyz/videos/watch/4b937e8b-7654-46e3-8d01-79392ec5b3d1
+urlview https://videos.lukesmith.xyz/videos/watch/31a4918f-633b-4bd6-b08e-956ac75d0324
+colorschemes with pywal https://videos.lukesmith.xyz/videos/watch/1b476003-61b2-4609-ac4b-820c3d128643
+vi mode in shell https://videos.lukesmith.xyz/videos/watch/228aa50c-836f-456f-9f0d-a45157fe4313
+pass (password manager) https://videos.lukesmith.xyz/videos/watch/432fc942-5e28-4682-9beb-f5cb237a1dd6
+"
+echo "$vidlist" | grep -P "^$(echo "$vidlist" | grep "https:" | sed 's/\t.*//g' | dmenu -i -p "Learn about what? (ESC to cancel)" -l 20 | awk '{print $1}')\s" | sed 's/.*\t//' | xargs -r mpv
diff --git a/undill b/undill
new file mode 100755
index 0000000..1362d75
--- /dev/null
+++ b/undill
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+#
+# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
+# Copyright (c) 2008-2016 California Institute of Technology.
+# Copyright (c) 2016-2022 The Uncertainty Quantification Foundation.
+# License: 3-clause BSD. The full license text is available at:
+# - https://github.com/uqfoundation/dill/blob/master/LICENSE
+"""
+unpickle the contents of a pickled object file
+
+Examples::
+
+ $ undill hello.pkl
+ ['hello', 'world']
+"""
+
+if __name__ == '__main__':
+ import sys
+ import dill
+ for file in sys.argv[1:]:
+ print (dill.load(open(file,'rb')))
+
diff --git a/unix b/unix
new file mode 100755
index 0000000..a9fb96e
--- /dev/null
+++ b/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/upload.py b/upload.py
new file mode 100644
index 0000000..a4ee091
--- /dev/null
+++ b/upload.py
@@ -0,0 +1,181 @@
+#!/usr/bin/python
+
+import httplib
+import httplib2
+import os
+import random
+import sys
+import time
+
+from apiclient.discovery import build
+from apiclient.errors import HttpError
+from apiclient.http import MediaFileUpload
+from oauth2client.client import flow_from_clientsecrets
+from oauth2client.file import Storage
+from oauth2client.tools import argparser, run_flow
+
+
+# Explicitly tell the underlying HTTP transport library not to retry, since
+# we are handling retry logic ourselves.
+httplib2.RETRIES = 1
+
+# Maximum number of times to retry before giving up.
+MAX_RETRIES = 10
+
+# Always retry when these exceptions are raised.
+RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected,
+ httplib.IncompleteRead, httplib.ImproperConnectionState,
+ httplib.CannotSendRequest, httplib.CannotSendHeader,
+ httplib.ResponseNotReady, httplib.BadStatusLine)
+
+# Always retry when an apiclient.errors.HttpError with one of these status
+# codes is raised.
+RETRIABLE_STATUS_CODES = [500, 502, 503, 504]
+
+# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
+# the OAuth 2.0 information for this application, including its client_id and
+# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
+# the Google API Console at
+# https://console.developers.google.com/.
+# Please ensure that you have enabled the YouTube Data API for your project.
+# For more information about using OAuth2 to access the YouTube Data API, see:
+# https://developers.google.com/youtube/v3/guides/authentication
+# For more information about the client_secrets.json file format, see:
+# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
+CLIENT_SECRETS_FILE = "client_secrets.json"
+
+# This OAuth 2.0 access scope allows an application to upload files to the
+# authenticated user's YouTube channel, but doesn't allow other types of access.
+YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload"
+YOUTUBE_API_SERVICE_NAME = "youtube"
+YOUTUBE_API_VERSION = "v3"
+
+# This variable defines a message to display if the CLIENT_SECRETS_FILE is
+# missing.
+MISSING_CLIENT_SECRETS_MESSAGE = """
+WARNING: Please configure OAuth 2.0
+
+To make this sample run you will need to populate the client_secrets.json file
+found at:
+
+ %s
+
+with information from the API Console
+https://console.developers.google.com/
+
+For more information about the client_secrets.json file format, please visit:
+https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
+""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
+ CLIENT_SECRETS_FILE))
+
+VALID_PRIVACY_STATUSES = ("public", "private", "unlisted")
+
+
+def get_authenticated_service(args):
+ flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,
+ scope=YOUTUBE_UPLOAD_SCOPE,
+ message=MISSING_CLIENT_SECRETS_MESSAGE)
+
+ storage = Storage("%s-oauth2.json" % sys.argv[0])
+ credentials = storage.get()
+
+ if credentials is None or credentials.invalid:
+ credentials = run_flow(flow, storage, args)
+
+ return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
+ http=credentials.authorize(httplib2.Http()))
+
+def initialize_upload(youtube, options):
+ tags = None
+ if options.keywords:
+ tags = options.keywords.split(",")
+
+ body=dict(
+ snippet=dict(
+ title=options.title,
+ description=options.description,
+ tags=tags,
+ categoryId=options.category
+ ),
+ status=dict(
+ privacyStatus=options.privacyStatus
+ )
+ )
+
+ # Call the API's videos.insert method to create and upload the video.
+ insert_request = youtube.videos().insert(
+ part=",".join(body.keys()),
+ body=body,
+ # The chunksize parameter specifies the size of each chunk of data, in
+ # bytes, that will be uploaded at a time. Set a higher value for
+ # reliable connections as fewer chunks lead to faster uploads. Set a lower
+ # value for better recovery on less reliable connections.
+ #
+ # Setting "chunksize" equal to -1 in the code below means that the entire
+ # file will be uploaded in a single HTTP request. (If the upload fails,
+ # it will still be retried where it left off.) This is usually a best
+ # practice, but if you're using Python older than 2.6 or if you're
+ # running on App Engine, you should set the chunksize to something like
+ # 1024 * 1024 (1 megabyte).
+ media_body=MediaFileUpload(options.file, chunksize=-1, resumable=True)
+ )
+
+ resumable_upload(insert_request)
+
+# This method implements an exponential backoff strategy to resume a
+# failed upload.
+def resumable_upload(insert_request):
+ response = None
+ error = None
+ retry = 0
+ while response is None:
+ try:
+ print "Uploading file..."
+ status, response = insert_request.next_chunk()
+ if response is not None:
+ if 'id' in response:
+ print "Video id '%s' was successfully uploaded." % response['id']
+ else:
+ exit("The upload failed with an unexpected response: %s" % response)
+ except HttpError, e:
+ if e.resp.status in RETRIABLE_STATUS_CODES:
+ error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status,
+ e.content)
+ else:
+ raise
+ except RETRIABLE_EXCEPTIONS, e:
+ error = "A retriable error occurred: %s" % e
+
+ if error is not None:
+ print error
+ retry += 1
+ if retry > MAX_RETRIES:
+ exit("No longer attempting to retry.")
+
+ max_sleep = 2 ** retry
+ sleep_seconds = random.random() * max_sleep
+ print "Sleeping %f seconds and then retrying..." % sleep_seconds
+ time.sleep(sleep_seconds)
+
+if __name__ == '__main__':
+ argparser.add_argument("--file", required=True, help="Video file to upload")
+ argparser.add_argument("--title", help="Video title", default="Test Title")
+ argparser.add_argument("--description", help="Video description",
+ default="Test Description")
+ argparser.add_argument("--category", default="22",
+ help="Numeric video category. " +
+ "See https://developers.google.com/youtube/v3/docs/videoCategories/list")
+ argparser.add_argument("--keywords", help="Video keywords, comma separated",
+ default="")
+ argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES,
+ default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.")
+ args = argparser.parse_args()
+
+ if not os.path.exists(args.file):
+ exit("Please specify a valid file using the --file= parameter.")
+
+ youtube = get_authenticated_service(args)
+ try:
+ initialize_upload(youtube, args)
+ except HttpError, e:
+ print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
diff --git a/wheel b/wheel
new file mode 100755
index 0000000..8149efb
--- /dev/null
+++ b/wheel
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from wheel.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/ytplay b/ytplay
new file mode 100755
index 0000000..e505a3b
--- /dev/null
+++ b/ytplay
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+query=$(printf '%s' "$*" | tr ' ' '+' )
+mpv "https://youtube.com/$(curl -s "https://vid.puffyan.us/search?q=$query" | grep -Eo "watch\?v=.{11}" | head -n 1)"