summaryrefslogtreecommitdiffstats
path: root/.local/bin
diff options
context:
space:
mode:
Diffstat (limited to '.local/bin')
-rw-r--r--.local/bin/__pycache__/clear_comtypes_cache.cpython-310.pycbin0 -> 1303 bytes
-rwxr-xr-x.local/bin/alembic8
-rwxr-xr-x.local/bin/alert3
-rwxr-xr-x.local/bin/arkenfox-auto-update23
-rwxr-xr-x.local/bin/base588
-rwxr-xr-x.local/bin/booksplit43
-rwxr-xr-x.local/bin/brom_to_offs8
-rwxr-xr-x.local/bin/chardetect8
-rwxr-xr-x.local/bin/classic-radio4
-rw-r--r--.local/bin/clear_comtypes_cache.py57
-rw-r--r--.local/bin/client_secrets.json1
-rwxr-xr-x.local/bin/compiler52
-rwxr-xr-x.local/bin/convert-json8
-rw-r--r--.local/bin/cron/README.md11
-rwxr-xr-x.local/bin/cron/checkup17
-rwxr-xr-x.local/bin/cron/crontog6
-rwxr-xr-x.local/bin/cron/newsup15
-rwxr-xr-x.local/bin/da_parser8
-rwxr-xr-x.local/bin/displayselect82
-rwxr-xr-x.local/bin/django-admin8
-rwxr-xr-x.local/bin/dmenuhandler21
-rwxr-xr-x.local/bin/dmenumount67
-rwxr-xr-x.local/bin/dmenumountcifs19
-rwxr-xr-x.local/bin/dmenupass6
-rwxr-xr-x.local/bin/dmenurecord123
-rwxr-xr-x.local/bin/dmenuumount44
-rwxr-xr-x.local/bin/dmenuunicode18
-rwxr-xr-x.local/bin/dwm_bar67
-rwxr-xr-x.local/bin/emoji3
-rwxr-xr-x.local/bin/epylint8
-rwxr-xr-x.local/bin/estimator_ckpt_converter8
-rwxr-xr-x.local/bin/ext45
-rwxr-xr-x.local/bin/f2py8
-rwxr-xr-x.local/bin/f2py38
-rwxr-xr-x.local/bin/f2py3.108
-rwxr-xr-x.local/bin/f2py3.88
-rwxr-xr-x.local/bin/flake88
-rwxr-xr-x.local/bin/flask8
-rwxr-xr-x.local/bin/fonttools8
-rwxr-xr-x.local/bin/get_objgraph54
-rwxr-xr-x.local/bin/getbib14
-rwxr-xr-x.local/bin/getcomproot9
-rwxr-xr-x.local/bin/getkeys5
-rwxr-xr-x.local/bin/google-oauthlib-tool8
-rwxr-xr-x.local/bin/holehe8
-rwxr-xr-x.local/bin/httpx8
-rwxr-xr-x.local/bin/ifinstalled12
-rwxr-xr-x.local/bin/import_pb_to_tensorboard8
-rwxr-xr-x.local/bin/isort8
-rwxr-xr-x.local/bin/isort-identify-imports8
-rwxr-xr-x.local/bin/jsonschema8
-rwxr-xr-x.local/bin/keystone-manage8
-rwxr-xr-x.local/bin/keystone-status8
-rwxr-xr-x.local/bin/keystone-wsgi-admin53
-rwxr-xr-x.local/bin/keystone-wsgi-public53
-rwxr-xr-x.local/bin/layoutmenu7
-rwxr-xr-x.local/bin/lfub24
-rwxr-xr-x.local/bin/linkhandler26
-rwxr-xr-x.local/bin/lockutils-wrapper8
-rwxr-xr-x.local/bin/maimpick20
-rwxr-xr-x.local/bin/make_metadata8
-rwxr-xr-x.local/bin/mako-render8
-rwxr-xr-x.local/bin/markdown_py8
-rwxr-xr-x.local/bin/mdexport8
-rwxr-xr-x.local/bin/merge_metadata8
-rwxr-xr-x.local/bin/mounter119
-rwxr-xr-x.local/bin/mtk8
-rwxr-xr-x.local/bin/mtk_gui8
-rwxr-xr-x.local/bin/nasad8
-rwxr-xr-x.local/bin/netaddr8
-rwxr-xr-x.local/bin/newword6
-rwxr-xr-x.local/bin/noisereduce81
-rwxr-xr-x.local/bin/normalizer8
-rwxr-xr-x.local/bin/notflix6
-rwxr-xr-x.local/bin/opout13
-rwxr-xr-x.local/bin/oslo-config-generator8
-rwxr-xr-x.local/bin/oslo-config-validator8
-rwxr-xr-x.local/bin/oslo-messaging-send-notification8
-rwxr-xr-x.local/bin/oslo-metrics8
-rwxr-xr-x.local/bin/oslopolicy-checker8
-rwxr-xr-x.local/bin/oslopolicy-convert-json-to-yaml8
-rwxr-xr-x.local/bin/oslopolicy-list-redundant8
-rwxr-xr-x.local/bin/oslopolicy-policy-generator8
-rwxr-xr-x.local/bin/oslopolicy-policy-upgrade8
-rwxr-xr-x.local/bin/oslopolicy-sample-generator8
-rwxr-xr-x.local/bin/oslopolicy-validator8
-rwxr-xr-x.local/bin/osprofiler8
-rwxr-xr-x.local/bin/otp50
-rwxr-xr-x.local/bin/pagalnew50
-rwxr-xr-x.local/bin/parse_xsd28
-rwxr-xr-x.local/bin/pauseallmpv10
-rwxr-xr-x.local/bin/pbr8
-rwxr-xr-x.local/bin/peertubetorrent9
-rwxr-xr-x.local/bin/pip8
-rwxr-xr-x.local/bin/pip38
-rwxr-xr-x.local/bin/pip3.88
-rwxr-xr-x.local/bin/podentr7
-rwxr-xr-x.local/bin/prompt8
-rwxr-xr-x.local/bin/py.test8
-rwxr-xr-x.local/bin/pycodestyle8
-rwxr-xr-x.local/bin/pyflakes8
-rwxr-xr-x.local/bin/pyftmerge8
-rwxr-xr-x.local/bin/pyftsubset8
-rwxr-xr-x.local/bin/pylint8
-rwxr-xr-x.local/bin/pyreverse8
-rwxr-xr-x.local/bin/pyrsa-decrypt8
-rwxr-xr-x.local/bin/pyrsa-encrypt8
-rwxr-xr-x.local/bin/pyrsa-keygen8
-rwxr-xr-x.local/bin/pyrsa-priv2pub8
-rwxr-xr-x.local/bin/pyrsa-sign8
-rwxr-xr-x.local/bin/pyrsa-verify8
-rwxr-xr-x.local/bin/pyserial-miniterm8
-rwxr-xr-x.local/bin/pyserial-ports8
-rwxr-xr-x.local/bin/pyside6-android-deploy8
-rwxr-xr-x.local/bin/pyside6-assistant8
-rwxr-xr-x.local/bin/pyside6-deploy8
-rwxr-xr-x.local/bin/pyside6-designer8
-rwxr-xr-x.local/bin/pyside6-genpyi8
-rwxr-xr-x.local/bin/pyside6-linguist8
-rwxr-xr-x.local/bin/pyside6-lrelease8
-rwxr-xr-x.local/bin/pyside6-lupdate8
-rwxr-xr-x.local/bin/pyside6-metaobjectdump8
-rwxr-xr-x.local/bin/pyside6-project8
-rwxr-xr-x.local/bin/pyside6-qml8
-rwxr-xr-x.local/bin/pyside6-qmlcachegen8
-rwxr-xr-x.local/bin/pyside6-qmlformat8
-rwxr-xr-x.local/bin/pyside6-qmlimportscanner8
-rwxr-xr-x.local/bin/pyside6-qmllint8
-rwxr-xr-x.local/bin/pyside6-qmlls8
-rwxr-xr-x.local/bin/pyside6-qmltyperegistrar8
-rwxr-xr-x.local/bin/pyside6-qtpy2cpp8
-rwxr-xr-x.local/bin/pyside6-rcc8
-rwxr-xr-x.local/bin/pyside6-uic8
-rwxr-xr-x.local/bin/pytest8
-rwxr-xr-x.local/bin/pywalfox8
-rwxr-xr-x.local/bin/qndl12
-rwxr-xr-x.local/bin/queueandnotify14
-rwxr-xr-x.local/bin/randompass31
-rwxr-xr-x.local/bin/remapd8
-rwxr-xr-x.local/bin/remaps11
-rwxr-xr-x.local/bin/rotdir12
-rwxr-xr-x.local/bin/rssadd18
-rwxr-xr-x.local/bin/samedir10
-rwxr-xr-x.local/bin/saved_model_cli8
-rwxr-xr-x.local/bin/sd22
-rwxr-xr-x.local/bin/set_wallpaper21
-rwxr-xr-x.local/bin/setbg42
-rwxr-xr-x.local/bin/shortcuts44
-rwxr-xr-x.local/bin/simplex-chatbin0 -> 104330520 bytes
-rwxr-xr-x.local/bin/slider126
-rwxr-xr-x.local/bin/socialscan8
-rwxr-xr-x.local/bin/sqlformat8
-rwxr-xr-x.local/bin/srt57
-rwxr-xr-x.local/bin/srt-deduplicate96
-rwxr-xr-x.local/bin/srt-fixed-timeshift47
-rwxr-xr-x.local/bin/srt-linear-timeshift105
-rwxr-xr-x.local/bin/srt-lines-matching85
-rwxr-xr-x.local/bin/srt-mux112
-rwxr-xr-x.local/bin/srt-normalise28
-rwxr-xr-x.local/bin/srt-play59
-rwxr-xr-x.local/bin/srt-process57
-rwxr-xr-x.local/bin/stage28
-rwxr-xr-x.local/bin/statusbar/sb-battery37
-rwxr-xr-x.local/bin/statusbar/sb-brightness23
-rwxr-xr-x.local/bin/statusbar/sb-clock29
-rwxr-xr-x.local/bin/statusbar/sb-cpu12
-rwxr-xr-x.local/bin/statusbar/sb-cpubars44
-rwxr-xr-x.local/bin/statusbar/sb-disk23
-rwxr-xr-x.local/bin/statusbar/sb-doppler280
-rwxr-xr-x.local/bin/statusbar/sb-forecast53
-rwxr-xr-x.local/bin/statusbar/sb-help-icon17
-rwxr-xr-x.local/bin/statusbar/sb-internet33
-rwxr-xr-x.local/bin/statusbar/sb-iplocate15
-rwxr-xr-x.local/bin/statusbar/sb-kbselect17
-rwxr-xr-x.local/bin/statusbar/sb-mailbox20
-rwxr-xr-x.local/bin/statusbar/sb-memory12
-rwxr-xr-x.local/bin/statusbar/sb-moonphase37
-rwxr-xr-x.local/bin/statusbar/sb-mpdup8
-rwxr-xr-x.local/bin/statusbar/sb-music19
-rwxr-xr-x.local/bin/statusbar/sb-nettraf29
-rwxr-xr-x.local/bin/statusbar/sb-news17
-rwxr-xr-x.local/bin/statusbar/sb-pacpackages29
-rwxr-xr-x.local/bin/statusbar/sb-popupgrade9
-rwxr-xr-x.local/bin/statusbar/sb-price56
-rwxr-xr-x.local/bin/statusbar/sb-tasks20
-rwxr-xr-x.local/bin/statusbar/sb-torrent27
-rwxr-xr-x.local/bin/statusbar/sb-volume39
-rwxr-xr-x.local/bin/switch_audio14
-rwxr-xr-x.local/bin/symilar8
-rwxr-xr-x.local/bin/sysact26
-rwxr-xr-x.local/bin/system_action16
-rwxr-xr-x.local/bin/tag49
-rwxr-xr-x.local/bin/td-toggle12
-rwxr-xr-x.local/bin/tensorboard8
-rwxr-xr-x.local/bin/texclear9
-rwxr-xr-x.local/bin/tf_upgrade_v28
-rwxr-xr-x.local/bin/tflite_convert8
-rwxr-xr-x.local/bin/toco8
-rwxr-xr-x.local/bin/toco_from_protos8
-rwxr-xr-x.local/bin/torwrap7
-rwxr-xr-x.local/bin/tqdm8
-rwxr-xr-x.local/bin/transadd9
-rwxr-xr-x.local/bin/ttx8
-rwxr-xr-x.local/bin/tutorialvids26
-rwxr-xr-x.local/bin/undill22
-rwxr-xr-x.local/bin/unix26
-rwxr-xr-x.local/bin/unmounter28
-rw-r--r--.local/bin/upload.py181
-rwxr-xr-x.local/bin/vosk-transcriber8
-rwxr-xr-x.local/bin/waldl161
-rw-r--r--.local/bin/weath25
-rwxr-xr-x.local/bin/wheel8
-rwxr-xr-x.local/bin/xdg-terminal-exec3
-rwxr-xr-x.local/bin/xmlschema-json2xml8
-rwxr-xr-x.local/bin/xmlschema-validate8
-rwxr-xr-x.local/bin/xmlschema-xml2json8
-rwxr-xr-x.local/bin/yappi8
-rwxr-xr-x.local/bin/ytplay4
218 files changed, 4767 insertions, 0 deletions
diff --git a/.local/bin/__pycache__/clear_comtypes_cache.cpython-310.pyc b/.local/bin/__pycache__/clear_comtypes_cache.cpython-310.pyc
new file mode 100644
index 0000000..6eb21b9
--- /dev/null
+++ b/.local/bin/__pycache__/clear_comtypes_cache.cpython-310.pyc
Binary files differ
diff --git a/.local/bin/alembic b/.local/bin/alembic
new file mode 100755
index 0000000..9e13e98
--- /dev/null
+++ b/.local/bin/alembic
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from alembic.config import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/alert b/.local/bin/alert
new file mode 100755
index 0000000..4237f2c
--- /dev/null
+++ b/.local/bin/alert
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+paplay ~/.local/share/sounds/noti.ogg
diff --git a/.local/bin/arkenfox-auto-update b/.local/bin/arkenfox-auto-update
new file mode 100755
index 0000000..7664a4f
--- /dev/null
+++ b/.local/bin/arkenfox-auto-update
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# A wrapper for the arkenfox-updater that runs it on all pre-existing Arkenfox
+# user.js files on the machine.
+
+# On installation of LARBS, this file is copied to /usr/local/lib/ where it is
+# run by a pacman hook set up. The user should not have to run this manually.
+
+# Search for all Firefox and Librewolf profiles using Arkenfox.
+profiles="$(grep -sH "arkenfox user.js" \
+ /home/*/.librewolf/*.default-release/user.js \
+ /home/*/.mozilla/firefox/*.default-release/user.js)"
+
+IFS='
+'
+
+# Update each found profile.
+for profile in $profiles; do
+ userjs=${profile%%/user.js*}
+ user=$(stat -c '%U' "$userjs") || continue
+
+ su -l "$user" -c "arkenfox-updater -c -p $userjs -s"
+done
diff --git a/.local/bin/base58 b/.local/bin/base58
new file mode 100755
index 0000000..1e291f0
--- /dev/null
+++ b/.local/bin/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/.local/bin/booksplit b/.local/bin/booksplit
new file mode 100755
index 0000000..079d85f
--- /dev/null
+++ b/.local/bin/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 -c -f 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 -c -f 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/.local/bin/brom_to_offs b/.local/bin/brom_to_offs
new file mode 100755
index 0000000..366e4e0
--- /dev/null
+++ b/.local/bin/brom_to_offs
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mtkclient.Tools.brom_to_offs import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/chardetect b/.local/bin/chardetect
new file mode 100755
index 0000000..09f9ed1
--- /dev/null
+++ b/.local/bin/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/.local/bin/classic-radio b/.local/bin/classic-radio
new file mode 100755
index 0000000..fba302d
--- /dev/null
+++ b/.local/bin/classic-radio
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+url="https://live.musopen.org:8085/streamvbr0"
+pkill -f $url || mpv "$url"
diff --git a/.local/bin/clear_comtypes_cache.py b/.local/bin/clear_comtypes_cache.py
new file mode 100644
index 0000000..bd743cd
--- /dev/null
+++ b/.local/bin/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/.local/bin/client_secrets.json b/.local/bin/client_secrets.json
new file mode 100644
index 0000000..7a935fc
--- /dev/null
+++ b/.local/bin/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/.local/bin/compiler b/.local/bin/compiler
new file mode 100755
index 0000000..5713590
--- /dev/null
+++ b/.local/bin/compiler
@@ -0,0 +1,52 @@
+#!/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="${1}"
+ext="${file##*.}"
+dir=${file%/*}
+base="${file%.*}"
+
+cd "${dir}" || exit "1"
+
+case "${ext}" in
+ [0-9]) preconv "${file}" | refer -PS -e | groff -mandoc -T pdf > "${base}.pdf" ;;
+ mom|ms) preconv "${file}" | refer -PS -e | groff -T pdf -m"${ext}" > "${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 "${base}" ;;
+ m) octave "${file}" ;;
+ md) [ -x "$(command -v lowdown)" ] && \
+ lowdown --parse-no-intraemph "${file}" -Tms | groff -mpdfmark -ms -kept -T pdf > "${base}.pdf" || \
+ [ -x "$(command -v groffdown)" ] && \
+ groffdown -i "${file}" | groff -T pdf > "${base}.pdf" || \
+ pandoc -t ms --highlight-style="kate" -s -o "${base}.pdf" "${file}" ;;
+ 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)
+ textarget="$(getcomproot "${file}" || echo "${file}")"
+ command="pdflatex"
+ head -n5 "${textarget}" | grep -qi "xelatex" && command="xelatex"
+ ${command} --output-directory="${textarget%/*}" "${textarget%.*}" &&
+ grep -qi addbibresource "${textarget}" &&
+ biber --input-directory "${textarget%/*}" "${textarget%.*}" &&
+ ${command} --output-directory="${textarget%/*}" "${textarget%.*}" &&
+ ${command} --output-directory="${textarget%/*}" "${textarget%.*}"
+ ;;
+ *) sed -n '/^#!/s/^#!//p; q' "${file}" | xargs -r -I % "${file}" ;;
+esac
diff --git a/.local/bin/convert-json b/.local/bin/convert-json
new file mode 100755
index 0000000..3907a18
--- /dev/null
+++ b/.local/bin/convert-json
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_log.cmds.convert_json import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/cron/README.md b/.local/bin/cron/README.md
new file mode 100644
index 0000000..fa0c354
--- /dev/null
+++ b/.local/bin/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/.local/bin/cron/checkup b/.local/bin/cron/checkup
new file mode 100755
index 0000000..bd3c634
--- /dev/null
+++ b/.local/bin/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/.local/bin/cron/crontog b/.local/bin/cron/crontog
new file mode 100755
index 0000000..c9a640f
--- /dev/null
+++ b/.local/bin/cron/crontog
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Toggles all cronjobs off/on.
+# Stores disabled crontabs in ~/.config/cronsaved 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/.local/bin/cron/newsup b/.local/bin/cron/newsup
new file mode 100755
index 0000000..ed266d7
--- /dev/null
+++ b/.local/bin/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/.local/bin/da_parser b/.local/bin/da_parser
new file mode 100755
index 0000000..9924f84
--- /dev/null
+++ b/.local/bin/da_parser
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mtkclient.Tools.da_parser import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/displayselect b/.local/bin/displayselect
new file mode 100755
index 0000000..51dd468
--- /dev/null
+++ b/.local/bin/displayselect
@@ -0,0 +1,82 @@
+#!/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.
+ { 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/.local/bin/django-admin b/.local/bin/django-admin
new file mode 100755
index 0000000..f92fefa
--- /dev/null
+++ b/.local/bin/django-admin
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from django.core.management import execute_from_command_line
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(execute_from_command_line())
diff --git a/.local/bin/dmenuhandler b/.local/bin/dmenuhandler
new file mode 100755
index 0000000..e50178a
--- /dev/null
+++ b/.local/bin/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:-$(true | dmenu -p 'Paste URL or file path')}"
+
+case "$(printf "copy url\\nnsxiv\\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 -o "%(title)s.%(ext)s" -f bestaudio --embed-metadata --restrict-filenames' ;;
+ "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 ;;
+ nsxiv) curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && nsxiv -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/.local/bin/dmenumount b/.local/bin/dmenumount
new file mode 100755
index 0000000..3cb1f81
--- /dev/null
+++ b/.local/bin/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/.local/bin/dmenumountcifs b/.local/bin/dmenumountcifs
new file mode 100755
index 0000000..46c2b57
--- /dev/null
+++ b/.local/bin/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/.local/bin/dmenupass b/.local/bin/dmenupass
new file mode 100755
index 0000000..2c14e6f
--- /dev/null
+++ b/.local/bin/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/.local/bin/dmenurecord b/.local/bin/dmenurecord
new file mode 100755
index 0000000..ca6b011
--- /dev/null
+++ b/.local/bin/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.
+
+getdim() { xrandr | grep -oP '(?<=current ).*(?=,)' | tr -d ' ' ;}
+
+updateicon() { \
+ echo "$1" > /tmp/recordingicon
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ }
+
+killrecording() {
+ recpid="$(cat /tmp/recordingpid)"
+ kill -15 "$recpid"
+ rm -f /tmp/recordingpid
+ updateicon ""
+ pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
+ }
+
+screencast() { \
+ ffmpeg -y \
+ -f x11grab \
+ -framerate 30 \
+ -s "$(getdim)" \
+ -i "$DISPLAY" \
+ -r 24 \
+ -use_wallclock_as_timestamps 1 \
+ -f alsa -thread_queue_size 1024 -i default \
+ -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 \
+ -framerate 30 \
+ -s "$(getdim)" \
+ -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 30 \
+ -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/.local/bin/dmenuumount b/.local/bin/dmenuumount
new file mode 100755
index 0000000..946d12c
--- /dev/null
+++ b/.local/bin/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/.local/bin/dmenuunicode b/.local/bin/dmenuunicode
new file mode 100755
index 0000000..dd12bc3
--- /dev/null
+++ b/.local/bin/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/chars/* | 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 "%s" "$chosen" | xclip -selection clipboard
+ notify-send "'$chosen' copied to clipboard." &
+fi
diff --git a/.local/bin/dwm_bar b/.local/bin/dwm_bar
new file mode 100755
index 0000000..42013fd
--- /dev/null
+++ b/.local/bin/dwm_bar
@@ -0,0 +1,67 @@
+#!/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 % 1 )) -eq 0 ] && update_memory
+ [ $((sec % 5 )) -eq 0 ] && update_vol
+
+ # how often the display updates ( 5 seconds )
+ [ $((sec % 5 )) -eq 0 ] && display
+ sec=$((sec + 1))
+ }
+done
diff --git a/.local/bin/emoji b/.local/bin/emoji
new file mode 100755
index 0000000..8bfdf32
--- /dev/null
+++ b/.local/bin/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/.local/bin/epylint b/.local/bin/epylint
new file mode 100755
index 0000000..2e104d9
--- /dev/null
+++ b/.local/bin/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/.local/bin/estimator_ckpt_converter b/.local/bin/estimator_ckpt_converter
new file mode 100755
index 0000000..6d357cb
--- /dev/null
+++ b/.local/bin/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/.local/bin/ext b/.local/bin/ext
new file mode 100755
index 0000000..6950ff6
--- /dev/null
+++ b/.local/bin/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/.local/bin/f2py b/.local/bin/f2py
new file mode 100755
index 0000000..33b01cf
--- /dev/null
+++ b/.local/bin/f2py
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/f2py3 b/.local/bin/f2py3
new file mode 100755
index 0000000..33b01cf
--- /dev/null
+++ b/.local/bin/f2py3
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/f2py3.10 b/.local/bin/f2py3.10
new file mode 100755
index 0000000..40ce6f8
--- /dev/null
+++ b/.local/bin/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/.local/bin/f2py3.8 b/.local/bin/f2py3.8
new file mode 100755
index 0000000..33b01cf
--- /dev/null
+++ b/.local/bin/f2py3.8
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/flake8 b/.local/bin/flake8
new file mode 100755
index 0000000..c6e249d
--- /dev/null
+++ b/.local/bin/flake8
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/flask b/.local/bin/flask
new file mode 100755
index 0000000..6fb03bf
--- /dev/null
+++ b/.local/bin/flask
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from flask.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/fonttools b/.local/bin/fonttools
new file mode 100755
index 0000000..49c4cd1
--- /dev/null
+++ b/.local/bin/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/.local/bin/get_objgraph b/.local/bin/get_objgraph
new file mode 100755
index 0000000..be3da53
--- /dev/null
+++ b/.local/bin/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/.local/bin/getbib b/.local/bin/getbib
new file mode 100755
index 0000000..121dd6e
--- /dev/null
+++ b/.local/bin/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 - | sed -n '/[dD][oO][iI]:/{s/.*[dD][oO][iI]:\s*\(\S\+[[:alnum:]]\).*/\1/p;q}') ||
+ 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/.local/bin/getcomproot b/.local/bin/getcomproot
new file mode 100755
index 0000000..dbee348
--- /dev/null
+++ b/.local/bin/getcomproot
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# A helper script for LaTeX/groff files used by `compiler` and `opout`.
+# The user can add the root file of a larger project as a comment as below:
+# % root = mainfile.tex
+# And the compiler script will run on that instead of the opened file.
+
+texroot="$(sed -n 's/^\s*%.*root\s*=\s*\(\S\+\).*/\1/p' "${1}")"
+[ -f "${texroot}" ] && readlink -f "${texroot}" || exit "1"
diff --git a/.local/bin/getkeys b/.local/bin/getkeys
new file mode 100755
index 0000000..266f29a
--- /dev/null
+++ b/.local/bin/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/.local/bin/google-oauthlib-tool b/.local/bin/google-oauthlib-tool
new file mode 100755
index 0000000..d84b136
--- /dev/null
+++ b/.local/bin/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/.local/bin/holehe b/.local/bin/holehe
new file mode 100755
index 0000000..786cf49
--- /dev/null
+++ b/.local/bin/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/.local/bin/httpx b/.local/bin/httpx
new file mode 100755
index 0000000..3d3d397
--- /dev/null
+++ b/.local/bin/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/.local/bin/ifinstalled b/.local/bin/ifinstalled
new file mode 100755
index 0000000..c192eba
--- /dev/null
+++ b/.local/bin/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/.local/bin/import_pb_to_tensorboard b/.local/bin/import_pb_to_tensorboard
new file mode 100755
index 0000000..2b77b14
--- /dev/null
+++ b/.local/bin/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/.local/bin/isort b/.local/bin/isort
new file mode 100755
index 0000000..daca689
--- /dev/null
+++ b/.local/bin/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/.local/bin/isort-identify-imports b/.local/bin/isort-identify-imports
new file mode 100755
index 0000000..a772abd
--- /dev/null
+++ b/.local/bin/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/.local/bin/jsonschema b/.local/bin/jsonschema
new file mode 100755
index 0000000..d9ddcd4
--- /dev/null
+++ b/.local/bin/jsonschema
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from jsonschema.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/keystone-manage b/.local/bin/keystone-manage
new file mode 100755
index 0000000..0c22162
--- /dev/null
+++ b/.local/bin/keystone-manage
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from keystone.cmd.manage import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/keystone-status b/.local/bin/keystone-status
new file mode 100755
index 0000000..40dbeca
--- /dev/null
+++ b/.local/bin/keystone-status
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from keystone.cmd.status import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/keystone-wsgi-admin b/.local/bin/keystone-wsgi-admin
new file mode 100755
index 0000000..f14cfcb
--- /dev/null
+++ b/.local/bin/keystone-wsgi-admin
@@ -0,0 +1,53 @@
+#!/usr/local/bin/python3.8
+#PBR Generated from 'wsgi_scripts'
+
+import threading
+
+from keystone.server.wsgi import initialize_admin_application
+
+if __name__ == "__main__":
+ import argparse
+ import socket
+ import sys
+ import wsgiref.simple_server as wss
+
+ parser = argparse.ArgumentParser(
+ description=initialize_admin_application.__doc__,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ usage='%(prog)s [-h] [--port PORT] [--host IP] -- [passed options]')
+ parser.add_argument('--port', '-p', type=int, default=8000,
+ help='TCP port to listen on')
+ parser.add_argument('--host', '-b', default='',
+ help='IP to bind the server to')
+ parser.add_argument('args',
+ nargs=argparse.REMAINDER,
+ metavar='-- [passed options]',
+ help="'--' is the separator of the arguments used "
+ "to start the WSGI server and the arguments passed "
+ "to the WSGI application.")
+ args = parser.parse_args()
+ if args.args:
+ if args.args[0] == '--':
+ args.args.pop(0)
+ else:
+ parser.error("unrecognized arguments: %s" % ' '.join(args.args))
+ sys.argv[1:] = args.args
+ server = wss.make_server(args.host, args.port, initialize_admin_application())
+
+ print("*" * 80)
+ print("STARTING test server keystone.server.wsgi.initialize_admin_application")
+ url = "http://%s:%d/" % (server.server_name, server.server_port)
+ print("Available at %s" % url)
+ print("DANGER! For testing only, do not use in production")
+ print("*" * 80)
+ sys.stdout.flush()
+
+ server.serve_forever()
+else:
+ application = None
+ app_lock = threading.Lock()
+
+ with app_lock:
+ if application is None:
+ application = initialize_admin_application()
+
diff --git a/.local/bin/keystone-wsgi-public b/.local/bin/keystone-wsgi-public
new file mode 100755
index 0000000..ff92438
--- /dev/null
+++ b/.local/bin/keystone-wsgi-public
@@ -0,0 +1,53 @@
+#!/usr/local/bin/python3.8
+#PBR Generated from 'wsgi_scripts'
+
+import threading
+
+from keystone.server.wsgi import initialize_public_application
+
+if __name__ == "__main__":
+ import argparse
+ import socket
+ import sys
+ import wsgiref.simple_server as wss
+
+ parser = argparse.ArgumentParser(
+ description=initialize_public_application.__doc__,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ usage='%(prog)s [-h] [--port PORT] [--host IP] -- [passed options]')
+ parser.add_argument('--port', '-p', type=int, default=8000,
+ help='TCP port to listen on')
+ parser.add_argument('--host', '-b', default='',
+ help='IP to bind the server to')
+ parser.add_argument('args',
+ nargs=argparse.REMAINDER,
+ metavar='-- [passed options]',
+ help="'--' is the separator of the arguments used "
+ "to start the WSGI server and the arguments passed "
+ "to the WSGI application.")
+ args = parser.parse_args()
+ if args.args:
+ if args.args[0] == '--':
+ args.args.pop(0)
+ else:
+ parser.error("unrecognized arguments: %s" % ' '.join(args.args))
+ sys.argv[1:] = args.args
+ server = wss.make_server(args.host, args.port, initialize_public_application())
+
+ print("*" * 80)
+ print("STARTING test server keystone.server.wsgi.initialize_public_application")
+ url = "http://%s:%d/" % (server.server_name, server.server_port)
+ print("Available at %s" % url)
+ print("DANGER! For testing only, do not use in production")
+ print("*" * 80)
+ sys.stdout.flush()
+
+ server.serve_forever()
+else:
+ application = None
+ app_lock = threading.Lock()
+
+ with app_lock:
+ if application is None:
+ application = initialize_public_application()
+
diff --git a/.local/bin/layoutmenu b/.local/bin/layoutmenu
new file mode 100755
index 0000000..1bf95f2
--- /dev/null
+++ b/.local/bin/layoutmenu
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+cat <<EOF | xmenu
+[]= Tiled Layout 0
+><> Floating Layout 1
+[M] Monocle Layout 2
+EOF
diff --git a/.local/bin/lfub b/.local/bin/lfub
new file mode 100755
index 0000000..f9bb2df
--- /dev/null
+++ b/.local/bin/lfub
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# This is a wrapper script for lf 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/.local/bin/linkhandler b/.local/bin/linkhandler
new file mode 100755
index 0000000..d372d84
--- /dev/null
+++ b/.local/bin/linkhandler
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Feed script a url or file location.
+# If an image, it will view in nsxiv,
+# 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 [ -z "$1" ]; then
+ url="$(xclip -o)"
+else
+ url="$1"
+fi
+
+case "$url" in
+ *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtube.com/shorts*|*youtu.be*|*hooktube.com*|*bitchute.com*|*videos.lukesmith.xyz*|*odysee.com*)
+ setsid -f mpv -quiet "$url" >/dev/null 2>&1 ;;
+ *png|*jpg|*jpe|*jpeg|*gif|*webp)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && nsxiv -a "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *pdf|*cbz|*cbr)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *mp3|*flac|*opus|*mp3?source*)
+ qndl "$url" 'curl -LO' >/dev/null 2>&1 ;;
+ *)
+ [ -f "$url" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$url" >/dev/null 2>&1 || setsid -f "$BROWSER" "$url" >/dev/null 2>&1
+esac
diff --git a/.local/bin/lockutils-wrapper b/.local/bin/lockutils-wrapper
new file mode 100755
index 0000000..e43f339
--- /dev/null
+++ b/.local/bin/lockutils-wrapper
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_concurrency.lockutils import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/maimpick b/.local/bin/maimpick
new file mode 100755
index 0000000..67b9983
--- /dev/null
+++ b/.local/bin/maimpick
@@ -0,0 +1,20 @@
+#!/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.
+
+# variables
+output="$(date '+%y%m%d-%H%M-%S').png"
+xclip_cmd="xclip -sel clip -t image/png"
+ocr_cmd="xclip -sel clip"
+
+case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)\\ncopy selected image to text" | dmenu -l 7 -i -p "Screenshot which area?")" in
+ "a selected area") maim -u -s pic-selected-"${output}" ;;
+ "current window") maim -B -q -d 0.2 -i "$(xdotool getactivewindow)" pic-window-"${output}" ;;
+ "full screen") maim -q -d 0.2 pic-full-"${output}" ;;
+ "a selected area (copy)") maim -u -s | ${xclip_cmd} ;;
+ "current window (copy)") maim -q -d 0.2 -i "$(xdotool getactivewindow)" | ${xclip_cmd} ;;
+ "full screen (copy)") maim -q -d 0.2 | ${xclip_cmd} ;;
+ "copy selected image to text") tmpfile=$(mktemp /tmp/ocr-XXXXXX.png) && maim -u -s > "$tmpfile" && tesseract "$tmpfile" - -l eng | ${ocr_cmd} && rm "$tmpfile" ;;
+esac
diff --git a/.local/bin/make_metadata b/.local/bin/make_metadata
new file mode 100755
index 0000000..c33ca1b
--- /dev/null
+++ b/.local/bin/make_metadata
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from saml2.tools.make_metadata import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/mako-render b/.local/bin/mako-render
new file mode 100755
index 0000000..307cb62
--- /dev/null
+++ b/.local/bin/mako-render
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mako.cmd import cmdline
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(cmdline())
diff --git a/.local/bin/markdown_py b/.local/bin/markdown_py
new file mode 100755
index 0000000..ca0b785
--- /dev/null
+++ b/.local/bin/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/.local/bin/mdexport b/.local/bin/mdexport
new file mode 100755
index 0000000..49cd01a
--- /dev/null
+++ b/.local/bin/mdexport
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from saml2.tools.mdexport import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/merge_metadata b/.local/bin/merge_metadata
new file mode 100755
index 0000000..51ada89
--- /dev/null
+++ b/.local/bin/merge_metadata
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from saml2.tools.merge_metadata import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/mounter b/.local/bin/mounter
new file mode 100755
index 0000000..389f2d3
--- /dev/null
+++ b/.local/bin/mounter
@@ -0,0 +1,119 @@
+#!/bin/bash
+
+# Mounts Android Phones and USB drives (encrypted or not). This script will
+# replace the older `dmenumount` which had extra steps and couldn't handle
+# encrypted drives.
+# TODO: Try decrypt for drives in crtypttab
+# TODO: Add some support for connecting iPhones (although they are annoying).
+
+IFS='
+'
+# Function for escaping cell-phone names.
+escape(){ echo "$@" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g" ;}
+
+# Check for phones.
+phones="$(simple-mtpfs -l 2>/dev/null | sed "s/^/📱/")"
+mountedphones="$(grep "simple-mtpfs" /etc/mtab)"
+# If there are already mounted phones, remove them from the list of mountables.
+[ -n "$mountedphones" ] && phones="$(for phone in $phones; do
+ for mounted in $mountedphones; do
+ escphone="$(escape "$phone")"
+ [[ "$mounted" =~ "$escphone" ]] && break 1
+ done && continue 1
+ echo "$phone"
+done)"
+
+# Check for drives.
+lsblkoutput="$(lsblk -rpo "uuid,name,type,size,label,mountpoint,fstype")"
+# Get all LUKS drives
+allluks="$(echo "$lsblkoutput" | grep crypto_LUKS)"
+# Get a list of the LUKS drive UUIDs already decrypted.
+decrypted="$(find /dev/disk/by-id/dm-uuid-CRYPT-LUKS2-* | sed "s|.*LUKS2-||;s|-.*||")"
+# Functioning for formatting drives correctly for dmenu:
+filter() { sed "s/ /:/g" | awk -F':' '$7==""{printf "%s%s (%s) %s\n",$1,$3,$5,$6}' ; }
+
+# Get only LUKS drives that are not decrypted.
+unopenedluks="$(for drive in $allluks; do
+ uuid="${drive%% *}"
+ uuid="${uuid//-}" # This is a bashism.
+ [ -n "$decrypted" ] && for open in $decrypted; do
+ [ "$uuid" = "$open" ] && break 1
+ done && continue 1
+ echo "🔒 $drive"
+done | filter)"
+
+# Get all normal, non-encrypted or decrypted partitions that are not mounted.
+normalparts="$(echo "$lsblkoutput"| grep -v crypto_LUKS | grep 'part\|rom\|crypt' | sed "s/^/💾 /" | filter )"
+
+# Add all to one variable. If no mountable drives found, exit.
+alldrives="$(echo "$phones
+$unopenedluks
+$normalparts" | sed "/^$/d;s/ *$//")"
+
+# Quit the script if a sequential command fails.
+set -e
+
+test -n "$alldrives"
+
+# Feed all found drives to dmenu and get user choice.
+chosen="$(echo "$alldrives" | dmenu -p "Mount which drive?" -i)"
+
+# Function for prompting user for a mountpoint.
+getmount(){
+ mp="$(find /mnt /media /mount /home -maxdepth 1 -type d 2>/dev/null | dmenu -i -p "Mount this drive where?")"
+ test -n "$mp"
+ if [ ! -d "$mp" ]; then
+ mkdiryn=$(printf "No\\nYes" | dmenu -i -p "$mp does not exist. Create it?")
+ [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp")
+ fi
+}
+
+attemptmount(){
+ # Attempt to mount without a mountpoint, to see if drive is in fstab.
+ sudo -A mount "$chosen" || return 1
+ notify-send "💾Drive Mounted." "$chosen mounted."
+ exit
+}
+
+case "$chosen" in
+ 💾*)
+ chosen="${chosen%% *}"
+ chosen="${chosen:1}" # This is a bashism.
+ parttype="$(echo "$lsblkoutput" | grep "$chosen")"
+ attemptmount || getmount
+ case "${parttype##* }" in
+ vfat) sudo -A mount -t vfat "$chosen" "$mp" -o rw,umask=0000 ;;
+ btrfs) sudo -A mount "$chosen" "$mp" ;;
+ *) sudo -A mount "$chosen" "$mp" -o uid="$(id -u)",gid="$(id -g)" ;;
+ esac
+ notify-send "💾Drive Mounted." "$chosen mounted to $mp."
+ ;;
+
+ 🔒*)
+ chosen="${chosen%% *}"
+ chosen="${chosen:1}" # This is a bashism.
+ # Number the drive.
+ while true; do
+ [ -f "/dev/mapper/usb$num" ] || break
+ num="$(printf "%02d" "$((num +1))")"
+ done
+
+ # Decrypt in a terminal window
+ ${TERMINAL:-st} -n floatterm -g 60x1 -e sudo cryptsetup open "$chosen" "usb$num"
+ # Check if now decrypted.
+ test -b "/dev/mapper/usb$num"
+
+ attemptmount || getmount
+ sudo -A mount "/dev/mapper/usb$num" "$mp" -o uid="$(id -u)",gid="$(id -g)"
+ notify-send "🔓Decrypted drive Mounted." "$chosen decrypted and mounted to $mp."
+ ;;
+
+ 📱*)
+ notify-send "❗Note" "Remember to allow file access on your phone now."
+ getmount
+ number="${chosen%%:*}"
+ number="${chosen:1}" # This is a bashism.
+ sudo -A simple-mtpfs -o allow_other -o fsname="simple-mtpfs-$(escape "$chosen")" --device "$number" "$mp"
+ notify-send "🤖 Android Mounted." "Android device mounted to $mp."
+ ;;
+esac
diff --git a/.local/bin/mtk b/.local/bin/mtk
new file mode 100755
index 0000000..285d3a7
--- /dev/null
+++ b/.local/bin/mtk
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mtkclient.mtk import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/mtk_gui b/.local/bin/mtk_gui
new file mode 100755
index 0000000..93ddd5a
--- /dev/null
+++ b/.local/bin/mtk_gui
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mtkclient.mtk_gui import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/nasad b/.local/bin/nasad
new file mode 100755
index 0000000..af148de
--- /dev/null
+++ b/.local/bin/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/.local/bin/netaddr b/.local/bin/netaddr
new file mode 100755
index 0000000..f7a2182
--- /dev/null
+++ b/.local/bin/netaddr
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from netaddr.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/newword b/.local/bin/newword
new file mode 100755
index 0000000..778605e
--- /dev/null
+++ b/.local/bin/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/.local/bin/noisereduce b/.local/bin/noisereduce
new file mode 100755
index 0000000..c344760
--- /dev/null
+++ b/.local/bin/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/.local/bin/normalizer b/.local/bin/normalizer
new file mode 100755
index 0000000..f10b70c
--- /dev/null
+++ b/.local/bin/normalizer
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3
+# -*- coding: utf-8 -*-
+import re
+import sys
+from charset_normalizer.cli 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/.local/bin/notflix b/.local/bin/notflix
new file mode 100755
index 0000000..24598a7
--- /dev/null
+++ b/.local/bin/notflix
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+query="$(echo $1 | sed 's/ /+/g')"
+movie=$(curl -s https://1337x.wtf/search/$query/1/ | grep -Eo "torrent\/[0-9]{7}\/[a-zA-Z0-9./?=_%:-]*" |head -n 1)
+magnet=$(curl -s https://1337x.wtf/$movie | grep -Po "magnet:\?xt=urn:btih:[a-zA-Z0-9]*" | head -n 1)
+peerflix -k $magnet
diff --git a/.local/bin/opout b/.local/bin/opout
new file mode 100755
index 0000000..d2b447a
--- /dev/null
+++ b/.local/bin/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|*.sil|*.m[dse]|*.[rR]md|*.mom|*.[0-9]) target="$(getcomproot "$1" || echo "$1")" ; setsid -f xdg-open "${target%.*}".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/.local/bin/oslo-config-generator b/.local/bin/oslo-config-generator
new file mode 100755
index 0000000..8f714e2
--- /dev/null
+++ b/.local/bin/oslo-config-generator
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_config.generator import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/oslo-config-validator b/.local/bin/oslo-config-validator
new file mode 100755
index 0000000..0ccb7be
--- /dev/null
+++ b/.local/bin/oslo-config-validator
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_config.validator import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/oslo-messaging-send-notification b/.local/bin/oslo-messaging-send-notification
new file mode 100755
index 0000000..b5aeb5b
--- /dev/null
+++ b/.local/bin/oslo-messaging-send-notification
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_messaging.notify.notifier import _send_notification
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(_send_notification())
diff --git a/.local/bin/oslo-metrics b/.local/bin/oslo-metrics
new file mode 100755
index 0000000..165b313
--- /dev/null
+++ b/.local/bin/oslo-metrics
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_metrics.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/oslopolicy-checker b/.local/bin/oslopolicy-checker
new file mode 100755
index 0000000..eec7d99
--- /dev/null
+++ b/.local/bin/oslopolicy-checker
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.shell import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/oslopolicy-convert-json-to-yaml b/.local/bin/oslopolicy-convert-json-to-yaml
new file mode 100755
index 0000000..7bf49f3
--- /dev/null
+++ b/.local/bin/oslopolicy-convert-json-to-yaml
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import convert_policy_json_to_yaml
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(convert_policy_json_to_yaml())
diff --git a/.local/bin/oslopolicy-list-redundant b/.local/bin/oslopolicy-list-redundant
new file mode 100755
index 0000000..4150562
--- /dev/null
+++ b/.local/bin/oslopolicy-list-redundant
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import list_redundant
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(list_redundant())
diff --git a/.local/bin/oslopolicy-policy-generator b/.local/bin/oslopolicy-policy-generator
new file mode 100755
index 0000000..52de9d0
--- /dev/null
+++ b/.local/bin/oslopolicy-policy-generator
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import generate_policy
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(generate_policy())
diff --git a/.local/bin/oslopolicy-policy-upgrade b/.local/bin/oslopolicy-policy-upgrade
new file mode 100755
index 0000000..6b8a0f8
--- /dev/null
+++ b/.local/bin/oslopolicy-policy-upgrade
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import upgrade_policy
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(upgrade_policy())
diff --git a/.local/bin/oslopolicy-sample-generator b/.local/bin/oslopolicy-sample-generator
new file mode 100755
index 0000000..a49a3d8
--- /dev/null
+++ b/.local/bin/oslopolicy-sample-generator
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import generate_sample
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(generate_sample())
diff --git a/.local/bin/oslopolicy-validator b/.local/bin/oslopolicy-validator
new file mode 100755
index 0000000..d0cab86
--- /dev/null
+++ b/.local/bin/oslopolicy-validator
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from oslo_policy.generator import validate_policy
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(validate_policy())
diff --git a/.local/bin/osprofiler b/.local/bin/osprofiler
new file mode 100755
index 0000000..4e3f6df
--- /dev/null
+++ b/.local/bin/osprofiler
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from osprofiler.cmd.shell import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/otp b/.local/bin/otp
new file mode 100755
index 0000000..7e471db
--- /dev/null
+++ b/.local/bin/otp
@@ -0,0 +1,50 @@
+#!/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 || exit 1
+
+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 || exit 1
+
+ temp=$(mktemp -p "$XDG_RUNTIME_DIR" --suffix=.png)
+ otp="otp-test-script"
+ trap 'rm -f $temp; pass rm -f $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:}"
+
+ if echo "$info" | pass otp insert "$otp"; then
+ while true ; do
+ export name="$(echo | 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/.local/bin/pagalnew b/.local/bin/pagalnew
new file mode 100755
index 0000000..cf5a1cf
--- /dev/null
+++ b/.local/bin/pagalnew
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+printf "Enter Album Name: "
+read albumname
+
+# Create directory for the album
+mkdir -p "$albumname"
+
+# Replace spaces with '+' for search
+searchname=$(echo "$albumname" | sed 's/ /+/g')
+
+# Fetch the search results page
+search_url="https://pagalnew.com/search.php?find=$searchname"
+echo "Searching for album: $albumname..."
+
+# Extract album URLs and names that belong to the /album/ directory
+albums=$(curl -s "$search_url" | grep -oiE "/album/[^\" ]+" | uniq)
+
+if [ -z "$albums" ]; then
+ echo "No albums found!"
+ exit 1
+fi
+
+# Use fzf to let the user choose the album interactively
+chosen_album=$(echo "$albums" | fzf --prompt="Select an album: " --preview="curl -s https://pagalnew.com{} | grep -oP '(?<=<title>)(.*)(?=</title>)'")
+
+if [ -z "$chosen_album" ]; then
+ echo "No album selected!"
+ exit 1
+fi
+
+album_url="https://pagalnew.com$chosen_album"
+echo "Selected album: $album_url"
+
+# Extract and download all song URLs
+urls=$(curl -s "$album_url" | grep -oiE "https://pagalnew.com/songs/.*" | cut -d\" -f1 | sort | uniq)
+
+for url in $urls; do
+ echo "Downloading $url..."
+ song_url=$(curl -s "$url" | grep "320 KBPS Song Download" | cut -d'"' -f8)
+
+ if [ -z "$song_url" ]; then
+ echo "Download link not found for $url"
+ continue
+ fi
+
+ # Download using aria2c
+ aria2c -d "$albumname" "https://pagalnew.com$song_url"
+done
+
diff --git a/.local/bin/parse_xsd2 b/.local/bin/parse_xsd2
new file mode 100755
index 0000000..bf8ffe7
--- /dev/null
+++ b/.local/bin/parse_xsd2
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from saml2.tools.parse_xsd2 import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/pauseallmpv b/.local/bin/pauseallmpv
new file mode 100755
index 0000000..d69a414
--- /dev/null
+++ b/.local/bin/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/.local/bin/pbr b/.local/bin/pbr
new file mode 100755
index 0000000..4ee8492
--- /dev/null
+++ b/.local/bin/pbr
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pbr.cmd.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/peertubetorrent b/.local/bin/peertubetorrent
new file mode 100755
index 0000000..4d8f630
--- /dev/null
+++ b/.local/bin/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/.local/bin/pip b/.local/bin/pip
new file mode 100755
index 0000000..c73b5b9
--- /dev/null
+++ b/.local/bin/pip
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/pip3 b/.local/bin/pip3
new file mode 100755
index 0000000..c73b5b9
--- /dev/null
+++ b/.local/bin/pip3
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/pip3.8 b/.local/bin/pip3.8
new file mode 100755
index 0000000..c73b5b9
--- /dev/null
+++ b/.local/bin/pip3.8
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/podentr b/.local/bin/podentr
new file mode 100755
index 0000000..9454b07
--- /dev/null
+++ b/.local/bin/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/.local/bin/prompt b/.local/bin/prompt
new file mode 100755
index 0000000..666434f
--- /dev/null
+++ b/.local/bin/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/.local/bin/py.test b/.local/bin/py.test
new file mode 100755
index 0000000..3dbd45f
--- /dev/null
+++ b/.local/bin/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/.local/bin/pycodestyle b/.local/bin/pycodestyle
new file mode 100755
index 0000000..fd2c948
--- /dev/null
+++ b/.local/bin/pycodestyle
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/pyflakes b/.local/bin/pyflakes
new file mode 100755
index 0000000..a3df89b
--- /dev/null
+++ b/.local/bin/pyflakes
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/pyftmerge b/.local/bin/pyftmerge
new file mode 100755
index 0000000..1e4c3a8
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyftsubset b/.local/bin/pyftsubset
new file mode 100755
index 0000000..6f56bcb
--- /dev/null
+++ b/.local/bin/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/.local/bin/pylint b/.local/bin/pylint
new file mode 100755
index 0000000..d21a75d
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyreverse b/.local/bin/pyreverse
new file mode 100755
index 0000000..433cf32
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-decrypt b/.local/bin/pyrsa-decrypt
new file mode 100755
index 0000000..13fe183
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-encrypt b/.local/bin/pyrsa-encrypt
new file mode 100755
index 0000000..2fd0772
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-keygen b/.local/bin/pyrsa-keygen
new file mode 100755
index 0000000..0fcfad8
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-priv2pub b/.local/bin/pyrsa-priv2pub
new file mode 100755
index 0000000..f497202
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-sign b/.local/bin/pyrsa-sign
new file mode 100755
index 0000000..5a45815
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyrsa-verify b/.local/bin/pyrsa-verify
new file mode 100755
index 0000000..ff68ce9
--- /dev/null
+++ b/.local/bin/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/.local/bin/pyserial-miniterm b/.local/bin/pyserial-miniterm
new file mode 100755
index 0000000..a043217
--- /dev/null
+++ b/.local/bin/pyserial-miniterm
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from serial.tools.miniterm import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/pyserial-ports b/.local/bin/pyserial-ports
new file mode 100755
index 0000000..8affbe7
--- /dev/null
+++ b/.local/bin/pyserial-ports
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from serial.tools.list_ports import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/pyside6-android-deploy b/.local/bin/pyside6-android-deploy
new file mode 100755
index 0000000..ed1ddc6
--- /dev/null
+++ b/.local/bin/pyside6-android-deploy
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import android_deploy
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(android_deploy())
diff --git a/.local/bin/pyside6-assistant b/.local/bin/pyside6-assistant
new file mode 100755
index 0000000..6a938e6
--- /dev/null
+++ b/.local/bin/pyside6-assistant
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import assistant
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(assistant())
diff --git a/.local/bin/pyside6-deploy b/.local/bin/pyside6-deploy
new file mode 100755
index 0000000..886947c
--- /dev/null
+++ b/.local/bin/pyside6-deploy
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import deploy
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(deploy())
diff --git a/.local/bin/pyside6-designer b/.local/bin/pyside6-designer
new file mode 100755
index 0000000..ac76f39
--- /dev/null
+++ b/.local/bin/pyside6-designer
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import designer
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(designer())
diff --git a/.local/bin/pyside6-genpyi b/.local/bin/pyside6-genpyi
new file mode 100755
index 0000000..c6cdb7f
--- /dev/null
+++ b/.local/bin/pyside6-genpyi
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import genpyi
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(genpyi())
diff --git a/.local/bin/pyside6-linguist b/.local/bin/pyside6-linguist
new file mode 100755
index 0000000..4046fff
--- /dev/null
+++ b/.local/bin/pyside6-linguist
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import linguist
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(linguist())
diff --git a/.local/bin/pyside6-lrelease b/.local/bin/pyside6-lrelease
new file mode 100755
index 0000000..cc9dbe3
--- /dev/null
+++ b/.local/bin/pyside6-lrelease
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import lrelease
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(lrelease())
diff --git a/.local/bin/pyside6-lupdate b/.local/bin/pyside6-lupdate
new file mode 100755
index 0000000..77df8a2
--- /dev/null
+++ b/.local/bin/pyside6-lupdate
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import lupdate
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(lupdate())
diff --git a/.local/bin/pyside6-metaobjectdump b/.local/bin/pyside6-metaobjectdump
new file mode 100755
index 0000000..49273c1
--- /dev/null
+++ b/.local/bin/pyside6-metaobjectdump
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import metaobjectdump
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(metaobjectdump())
diff --git a/.local/bin/pyside6-project b/.local/bin/pyside6-project
new file mode 100755
index 0000000..952fec7
--- /dev/null
+++ b/.local/bin/pyside6-project
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import project
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(project())
diff --git a/.local/bin/pyside6-qml b/.local/bin/pyside6-qml
new file mode 100755
index 0000000..6779dea
--- /dev/null
+++ b/.local/bin/pyside6-qml
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qml
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qml())
diff --git a/.local/bin/pyside6-qmlcachegen b/.local/bin/pyside6-qmlcachegen
new file mode 100755
index 0000000..8e796d4
--- /dev/null
+++ b/.local/bin/pyside6-qmlcachegen
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmlcachegen
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmlcachegen())
diff --git a/.local/bin/pyside6-qmlformat b/.local/bin/pyside6-qmlformat
new file mode 100755
index 0000000..5f4e7dd
--- /dev/null
+++ b/.local/bin/pyside6-qmlformat
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmlformat
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmlformat())
diff --git a/.local/bin/pyside6-qmlimportscanner b/.local/bin/pyside6-qmlimportscanner
new file mode 100755
index 0000000..ce14628
--- /dev/null
+++ b/.local/bin/pyside6-qmlimportscanner
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmlimportscanner
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmlimportscanner())
diff --git a/.local/bin/pyside6-qmllint b/.local/bin/pyside6-qmllint
new file mode 100755
index 0000000..c9ebaf5
--- /dev/null
+++ b/.local/bin/pyside6-qmllint
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmllint
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmllint())
diff --git a/.local/bin/pyside6-qmlls b/.local/bin/pyside6-qmlls
new file mode 100755
index 0000000..ca92c58
--- /dev/null
+++ b/.local/bin/pyside6-qmlls
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmlls
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmlls())
diff --git a/.local/bin/pyside6-qmltyperegistrar b/.local/bin/pyside6-qmltyperegistrar
new file mode 100755
index 0000000..a8fa631
--- /dev/null
+++ b/.local/bin/pyside6-qmltyperegistrar
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qmltyperegistrar
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qmltyperegistrar())
diff --git a/.local/bin/pyside6-qtpy2cpp b/.local/bin/pyside6-qtpy2cpp
new file mode 100755
index 0000000..1aa75ca
--- /dev/null
+++ b/.local/bin/pyside6-qtpy2cpp
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import qtpy2cpp
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(qtpy2cpp())
diff --git a/.local/bin/pyside6-rcc b/.local/bin/pyside6-rcc
new file mode 100755
index 0000000..c2306da
--- /dev/null
+++ b/.local/bin/pyside6-rcc
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import rcc
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(rcc())
diff --git a/.local/bin/pyside6-uic b/.local/bin/pyside6-uic
new file mode 100755
index 0000000..0817958
--- /dev/null
+++ b/.local/bin/pyside6-uic
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from PySide6.scripts.pyside_tool import uic
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(uic())
diff --git a/.local/bin/pytest b/.local/bin/pytest
new file mode 100755
index 0000000..3dbd45f
--- /dev/null
+++ b/.local/bin/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/.local/bin/pywalfox b/.local/bin/pywalfox
new file mode 100755
index 0000000..fba9fab
--- /dev/null
+++ b/.local/bin/pywalfox
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pywalfox.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/qndl b/.local/bin/qndl
new file mode 100755
index 0000000..48bc61e
--- /dev/null
+++ b/.local/bin/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/.local/bin/queueandnotify b/.local/bin/queueandnotify
new file mode 100755
index 0000000..1c3025c
--- /dev/null
+++ b/.local/bin/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/.local/bin/randompass b/.local/bin/randompass
new file mode 100755
index 0000000..fca095d
--- /dev/null
+++ b/.local/bin/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/.local/bin/remapd b/.local/bin/remapd
new file mode 100755
index 0000000..ee4cf39
--- /dev/null
+++ b/.local/bin/remapd
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Rerun the remaps script whenever a new input device is added.
+
+while :; do
+ remaps
+ grep -qP -m1 '[^un]bind.+\/[^:]+\(usb\)' <(udevadm monitor -u -t seat -s input -s usb)
+done
diff --git a/.local/bin/remaps b/.local/bin/remaps
new file mode 100755
index 0000000..6d7d54e
--- /dev/null
+++ b/.local/bin/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 -q "Caps Lock:\s*on" && xdotool key Caps_Lock
diff --git a/.local/bin/rotdir b/.local/bin/rotdir
new file mode 100755
index 0000000..d171f29
--- /dev/null
+++ b/.local/bin/rotdir
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# When I open an image from the file manager in nsxiv (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 nsxiv 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/.local/bin/rssadd b/.local/bin/rssadd
new file mode 100755
index 0000000..910fca3
--- /dev/null
+++ b/.local/bin/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/.local/bin/samedir b/.local/bin/samedir
new file mode 100755
index 0000000..0a19707
--- /dev/null
+++ b/.local/bin/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/.local/bin/saved_model_cli b/.local/bin/saved_model_cli
new file mode 100755
index 0000000..8598ef4
--- /dev/null
+++ b/.local/bin/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/.local/bin/sd b/.local/bin/sd
new file mode 100755
index 0000000..a0ff84c
--- /dev/null
+++ b/.local/bin/sd
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Open a terminal window in the same directory as the currently active window.
+
+windowPID=$(xprop -id "$(xprop -root | sed -n "/_NET_ACTIVE_WINDOW/ s/^.*# // p")" | sed -n "/PID/ s/^.*= // p")
+PIDlist=$(pstree -lpATna "$windowPID" | sed -En 's/.*,([0-9]+).*/\1/p' | tac)
+for PID in $PIDlist; do
+ cmdline=$(ps -o args= -p "$PID")
+ process_group_leader=$(ps -o comm= -p "$(ps -o pgid= -p "$PID" | tr -d ' ')")
+ cwd=$(readlink /proc/"$PID"/cwd)
+ # zsh and lf won't be ignored even if it shows ~ or /
+ case "$cmdline" in
+ 'lf -server') continue ;;
+ "${SHELL##*/}"|'lf'|'lf '*) break ;;
+ esac
+ # git (and its sub-processes) will show the root of a repository instead of the actual cwd, so they're ignored
+ [ "$process_group_leader" = 'git' ] || [ ! -d "$cwd" ] && continue
+ # This is to ignore programs that show ~ or / instead of the actual working directory
+ [ "$cwd" != "$HOME" ] && [ "$cwd" != '/' ] && break
+done
+[ "$PWD" != "$cwd" ] && [ -d "$cwd" ] && { cd "$cwd" || exit 1; }
+"$TERMINAL"
diff --git a/.local/bin/set_wallpaper b/.local/bin/set_wallpaper
new file mode 100755
index 0000000..38dc3c7
--- /dev/null
+++ b/.local/bin/set_wallpaper
@@ -0,0 +1,21 @@
+#!/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
+pywalfox update
+wal-telegram -w
+pywal-discord -t biswa
diff --git a/.local/bin/setbg b/.local/bin/setbg
new file mode 100755
index 0000000..4c21d02
--- /dev/null
+++ b/.local/bin/setbg
@@ -0,0 +1,42 @@
+#!/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"
+
+# Give -s as parameter to make notifications silent.
+while getopts "s" o; do case "${o}" in
+ s) silent='1' ;;
+esac done
+
+shift $((OPTIND - 1))
+
+trueloc="$(readlink -f "$1")" &&
+case "$(file --mime-type -b "$trueloc")" in
+ image/* ) ln -sf "$trueloc" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Changing wallpaper..." ;;
+ inode/directory ) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Random Wallpaper chosen." ;;
+ *) [ -z "$silent" ] && notify-send "🖼️ Error" "Not a valid image or directory." ; exit 1;;
+esac
+
+# If pywal is installed, use it.
+if command -v wal >/dev/null 2>&1 ; then
+ wal -n -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1
+# 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"
+# If running, dwm hit the key to refresh the color scheme.
+pidof dwm >/dev/null && xdotool key super+F5 && pywalfox update && pywal-discord -t biswa
+wal-telegram -w > /dev/null 2>&1 &
diff --git a/.local/bin/shortcuts b/.local/bin/shortcuts
new file mode 100755
index 0000000..08a2f57
--- /dev/null
+++ b/.local/bin/shortcuts
@@ -0,0 +1,44 @@
+#!/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"
+shell_env_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/shell/shortcutenvrc"
+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"
+qute_shortcuts="/dev/null"
+fish_shortcuts="/dev/null"
+vifm_shortcuts="/dev/null"
+
+# Remove, prepare files
+rm -f "$lf_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=sh\\n" > "$shell_env_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(\"[ -n \42%s\42 ] && export %s=\42%s\42 \n\",\$1,\$1,\$2) >> \"$shell_env_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 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(\"[ -n \42%s\42 ] && export %s=\42%s\42 \n\",\$1,\$1,\$2) >> \"$shell_env_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 E%s \$\$EDITOR \42%s\42 \n\",\$1,\$2) >> \"$lf_shortcuts\" ;
+ printf(\"cmap ;%s %s\n\",\$1,\$2) >> \"$vim_shortcuts\" }"
diff --git a/.local/bin/simplex-chat b/.local/bin/simplex-chat
new file mode 100755
index 0000000..887d5f6
--- /dev/null
+++ b/.local/bin/simplex-chat
Binary files differ
diff --git a/.local/bin/slider b/.local/bin/slider
new file mode 100755
index 0000000..b412e95
--- /dev/null
+++ b/.local/bin/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:s:" 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/,//))"
+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}" ] ;} &&
+ magick -size "${res:-1920x1080}" canvas:"${bgc:-black}" -gravity center "$content" -resize 1920x1080 -composite "$prepdir/$base"
+ else
+ { [ ! -f "$prepdir/$base" ] || [ -n "${redo+x}" ] ;} &&
+ magick -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
+endtime="$((totseconds-seconds))"
+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/.local/bin/socialscan b/.local/bin/socialscan
new file mode 100755
index 0000000..d20e2f3
--- /dev/null
+++ b/.local/bin/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/.local/bin/sqlformat b/.local/bin/sqlformat
new file mode 100755
index 0000000..5b0376b
--- /dev/null
+++ b/.local/bin/sqlformat
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from sqlparse.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/srt b/.local/bin/srt
new file mode 100755
index 0000000..e7c2a1e
--- /dev/null
+++ b/.local/bin/srt
@@ -0,0 +1,57 @@
+#!/usr/local/bin/python3
+
+import os
+import sys
+import errno
+
+
+SRT_BIN_PREFIX = "srt-"
+
+
+def find_srt_commands_in_path():
+ paths = os.environ.get("PATH", "").split(os.pathsep)
+
+ for path in paths:
+ try:
+ path_files = os.listdir(path)
+ except OSError as thrown_exc:
+ if thrown_exc.errno in (errno.ENOENT, errno.ENOTDIR):
+ continue
+ else:
+ raise
+
+ for path_file in path_files:
+ if path_file.startswith(SRT_BIN_PREFIX):
+ yield path_file[len(SRT_BIN_PREFIX) :]
+
+
+def show_help():
+ print(
+ "Available commands "
+ "(pass --help to a specific command for usage information):\n"
+ )
+ commands = sorted(set(find_srt_commands_in_path()))
+ for command in commands:
+ print("- {}".format(command))
+
+
+def main():
+ if len(sys.argv) < 2 or sys.argv[1].startswith("-"):
+ show_help()
+ sys.exit(0)
+
+ command = sys.argv[1]
+
+ available_commands = find_srt_commands_in_path()
+
+ if command not in available_commands:
+ print('Unknown command: "{}"\n'.format(command))
+ show_help()
+ sys.exit(1)
+
+ real_command = SRT_BIN_PREFIX + command
+ os.execvp(real_command, [real_command] + sys.argv[2:])
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-deduplicate b/.local/bin/srt-deduplicate
new file mode 100755
index 0000000..8fe8f63
--- /dev/null
+++ b/.local/bin/srt-deduplicate
@@ -0,0 +1,96 @@
+#!/usr/local/bin/python3
+
+"""Deduplicate repeated subtitles."""
+
+import datetime
+import srt_tools.utils
+import logging
+import operator
+
+log = logging.getLogger(__name__)
+
+try: # Python 2
+ range = xrange # pytype: disable=name-error
+except NameError:
+ pass
+
+
+def parse_args():
+ examples = {
+ "Remove duplicated subtitles within 5 seconds of each other": "srt deduplicate -i duplicated.srt",
+ "Remove duplicated subtitles within 500 milliseconds of each other": "srt deduplicate -t 500 -i duplicated.srt",
+ "Remove duplicated subtitles regardless of temporal proximity": "srt deduplicate -t 0 -i duplicated.srt",
+ }
+ parser = srt_tools.utils.basic_parser(
+ description=__doc__,
+ examples=examples,
+ )
+ parser.add_argument(
+ "-t",
+ "--ms",
+ metavar="MILLISECONDS",
+ default=datetime.timedelta(milliseconds=5000),
+ type=lambda ms: datetime.timedelta(milliseconds=int(ms)),
+ help="how many milliseconds distance a subtitle start time must be "
+ "within of another to be considered a duplicate "
+ "(default: 5000ms)",
+ )
+
+ return parser.parse_args()
+
+
+def deduplicate_subs(orig_subs, acceptable_diff):
+ """Remove subtitles with duplicated content."""
+ indices_to_remove = []
+
+ # If we only store the subtitle itself and compare that, it's possible that
+ # we'll not only remove the duplicate, but also the _original_ subtitle if
+ # they have the same sub index/times/etc.
+ #
+ # As such, we need to also store the index in the original subs list that
+ # this entry belongs to for each subtitle prior to sorting.
+ sorted_subs = sorted(
+ enumerate(orig_subs), key=lambda sub: (sub[1].content, sub[1].start)
+ )
+
+ for subs in srt_tools.utils.sliding_window(sorted_subs, width=2, inclusive=False):
+ cur_idx, cur_sub = subs[0]
+ next_idx, next_sub = subs[1]
+
+ if cur_sub.content == next_sub.content and (
+ not acceptable_diff or cur_sub.start + acceptable_diff >= next_sub.start
+ ):
+ log.debug(
+ "Marking l%d/s%d for removal, duplicate of l%d/s%d",
+ next_idx,
+ next_sub.index,
+ cur_idx,
+ cur_sub.index,
+ )
+ indices_to_remove.append(next_idx)
+
+ offset = 0
+ for idx in indices_to_remove:
+ del orig_subs[idx - offset]
+ offset += 1
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+
+ srt_tools.utils.set_basic_args(args)
+
+ subs = list(args.input)
+ deduplicate_subs(subs, args.ms)
+
+ output = srt_tools.utils.compose_suggest_on_fail(subs, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-fixed-timeshift b/.local/bin/srt-fixed-timeshift
new file mode 100755
index 0000000..607e7e7
--- /dev/null
+++ b/.local/bin/srt-fixed-timeshift
@@ -0,0 +1,47 @@
+#!/usr/local/bin/python3
+
+"""Shifts a subtitle by a fixed number of seconds."""
+
+import datetime
+import srt_tools.utils
+import logging
+
+log = logging.getLogger(__name__)
+
+
+def parse_args():
+ examples = {
+ "Make all subtitles 5 seconds later": "srt fixed-timeshift --seconds 5",
+ "Make all subtitles 5 seconds earlier": "srt fixed-timeshift --seconds -5",
+ }
+
+ parser = srt_tools.utils.basic_parser(description=__doc__, examples=examples)
+ parser.add_argument(
+ "--seconds", type=float, required=True, help="how many seconds to shift"
+ )
+ return parser.parse_args()
+
+
+def scalar_correct_subs(subtitles, seconds_to_shift):
+ td_to_shift = datetime.timedelta(seconds=seconds_to_shift)
+ for subtitle in subtitles:
+ subtitle.start += td_to_shift
+ subtitle.end += td_to_shift
+ yield subtitle
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+ srt_tools.utils.set_basic_args(args)
+ corrected_subs = scalar_correct_subs(args.input, args.seconds)
+ output = srt_tools.utils.compose_suggest_on_fail(corrected_subs, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-linear-timeshift b/.local/bin/srt-linear-timeshift
new file mode 100755
index 0000000..952cb3a
--- /dev/null
+++ b/.local/bin/srt-linear-timeshift
@@ -0,0 +1,105 @@
+#!/usr/local/bin/python3
+
+"""Perform linear time correction on a subtitle."""
+
+from __future__ import division
+
+import srt
+import datetime
+import srt_tools.utils
+import logging
+
+log = logging.getLogger(__name__)
+
+
+def timedelta_to_milliseconds(delta):
+ return delta.days * 86400000 + delta.seconds * 1000 + delta.microseconds / 1000
+
+
+def parse_args():
+ def srt_timestamp_to_milliseconds(parser, arg):
+ try:
+ delta = srt.srt_timestamp_to_timedelta(arg)
+ except ValueError:
+ parser.error("not a valid SRT timestamp: %s" % arg)
+ else:
+ return timedelta_to_milliseconds(delta)
+
+ examples = {
+ "Stretch out a subtitle so that second 1 is 1, 2 is 3, 3 is 5, etc": "srt linear-timeshift --f1 00:00:01,000 --t1 00:00:01,000 --f2 00:00:02,000 --t2 00:00:03,000"
+ }
+
+ parser = srt_tools.utils.basic_parser(description=__doc__, examples=examples)
+ parser.add_argument(
+ "--from-start",
+ "--f1",
+ type=lambda arg: srt_timestamp_to_milliseconds(parser, arg),
+ required=True,
+ help="the first desynchronised timestamp",
+ )
+ parser.add_argument(
+ "--to-start",
+ "--t1",
+ type=lambda arg: srt_timestamp_to_milliseconds(parser, arg),
+ required=True,
+ help="the first synchronised timestamp",
+ )
+ parser.add_argument(
+ "--from-end",
+ "--f2",
+ type=lambda arg: srt_timestamp_to_milliseconds(parser, arg),
+ required=True,
+ help="the second desynchronised timestamp",
+ )
+ parser.add_argument(
+ "--to-end",
+ "--t2",
+ type=lambda arg: srt_timestamp_to_milliseconds(parser, arg),
+ required=True,
+ help="the second synchronised timestamp",
+ )
+ return parser.parse_args()
+
+
+def calc_correction(to_start, to_end, from_start, from_end):
+ angular = (to_end - to_start) / (from_end - from_start)
+ linear = to_end - angular * from_end
+ return angular, linear
+
+
+def correct_time(current_msecs, angular, linear):
+ return round(current_msecs * angular + linear)
+
+
+def correct_timedelta(bad_delta, angular, linear):
+ bad_msecs = timedelta_to_milliseconds(bad_delta)
+ good_msecs = correct_time(bad_msecs, angular, linear)
+ good_delta = datetime.timedelta(milliseconds=good_msecs)
+ return good_delta
+
+
+def linear_correct_subs(subtitles, angular, linear):
+ for subtitle in subtitles:
+ subtitle.start = correct_timedelta(subtitle.start, angular, linear)
+ subtitle.end = correct_timedelta(subtitle.end, angular, linear)
+ yield subtitle
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+ angular, linear = calc_correction(
+ args.to_start, args.to_end, args.from_start, args.from_end
+ )
+ srt_tools.utils.set_basic_args(args)
+ corrected_subs = linear_correct_subs(args.input, angular, linear)
+ output = srt_tools.utils.compose_suggest_on_fail(corrected_subs, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-lines-matching b/.local/bin/srt-lines-matching
new file mode 100755
index 0000000..accabb1
--- /dev/null
+++ b/.local/bin/srt-lines-matching
@@ -0,0 +1,85 @@
+#!/usr/local/bin/python3
+
+"""Filter subtitles that match or don't match a particular pattern."""
+
+import importlib
+import srt_tools.utils
+import logging
+
+log = logging.getLogger(__name__)
+
+
+def strip_to_matching_lines_only(subtitles, imports, func_str, invert, per_sub):
+ for import_name in imports:
+ real_import = importlib.import_module(import_name)
+ globals()[import_name] = real_import
+
+ raw_func = eval(func_str) # pylint: disable-msg=eval-used
+
+ if invert:
+ func = lambda line: not raw_func(line)
+ else:
+ func = raw_func
+
+ for subtitle in subtitles:
+ if per_sub:
+ if not func(subtitle.content):
+ subtitle.content = ""
+ else:
+ subtitle.content = "\n".join(
+ line for line in subtitle.content.splitlines() if func(line)
+ )
+
+ yield subtitle
+
+
+def parse_args():
+ examples = {
+ "Only include Chinese lines": "srt lines-matching -m hanzidentifier -f hanzidentifier.has_chinese",
+ "Exclude all lines which only contain numbers": "srt lines-matching -v -f 'lambda x: x.isdigit()'",
+ }
+ parser = srt_tools.utils.basic_parser(description=__doc__, examples=examples)
+ parser.add_argument(
+ "-f", "--func", help="a function to use to match lines", required=True
+ )
+ parser.add_argument(
+ "-m",
+ "--module",
+ help="modules to import in the function context",
+ action="append",
+ default=[],
+ )
+ parser.add_argument(
+ "-s",
+ "--per-subtitle",
+ help="match the content of each subtitle, not each line",
+ action="store_true",
+ )
+ parser.add_argument(
+ "-v",
+ "--invert",
+ help="invert matching -- only match lines returning False",
+ action="store_true",
+ )
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+ srt_tools.utils.set_basic_args(args)
+ matching_subtitles_only = strip_to_matching_lines_only(
+ args.input, args.module, args.func, args.invert, args.per_subtitle
+ )
+ output = srt_tools.utils.compose_suggest_on_fail(
+ matching_subtitles_only, strict=args.strict
+ )
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-mux b/.local/bin/srt-mux
new file mode 100755
index 0000000..3e26621
--- /dev/null
+++ b/.local/bin/srt-mux
@@ -0,0 +1,112 @@
+#!/usr/local/bin/python3
+
+"""Merge multiple subtitles together into one."""
+
+import datetime
+import srt_tools.utils
+import logging
+import operator
+
+log = logging.getLogger(__name__)
+
+TOP = r"{\an8}"
+BOTTOM = r"{\an2}"
+
+
+def parse_args():
+ examples = {
+ "Merge English and Chinese subtitles": "srt mux -i eng.srt -i chs.srt -o both.srt",
+ "Merge subtitles, with one on top and one at the bottom": "srt mux -t -i eng.srt -i chs.srt -o both.srt",
+ }
+ parser = srt_tools.utils.basic_parser(
+ description=__doc__, examples=examples, multi_input=True
+ )
+ parser.add_argument(
+ "--ms",
+ metavar="MILLISECONDS",
+ default=datetime.timedelta(milliseconds=600),
+ type=lambda ms: datetime.timedelta(milliseconds=int(ms)),
+ help="if subs being muxed are within this number of milliseconds "
+ "of each other, they will have their times matched (default: 600)",
+ )
+ parser.add_argument(
+ "-w",
+ "--width",
+ default=5,
+ type=int,
+ help="how many subs to consider for time matching at once (default: %(default)s)",
+ )
+ parser.add_argument(
+ "-t",
+ "--top-and-bottom",
+ action="store_true",
+ help="use SSA-style tags to place files at the top and bottom, respectively. Turns off time matching",
+ )
+ parser.add_argument(
+ "--no-time-matching",
+ action="store_true",
+ help="don't try to do time matching for close subtitles (see --ms)",
+ )
+ return parser.parse_args()
+
+
+def merge_subs(subs, acceptable_diff, attr, width):
+ """
+ Merge subs with similar start/end times together. This prevents the
+ subtitles jumping around the screen.
+
+ The merge is done in-place.
+ """
+ sorted_subs = sorted(subs, key=operator.attrgetter(attr))
+
+ for subs in srt_tools.utils.sliding_window(sorted_subs, width=width):
+ current_sub = subs[0]
+ future_subs = subs[1:]
+ current_comp = getattr(current_sub, attr)
+
+ for future_sub in future_subs:
+ future_comp = getattr(future_sub, attr)
+ if current_comp + acceptable_diff > future_comp:
+ log.debug(
+ "Merging %d's %s time into %d",
+ future_sub.index,
+ attr,
+ current_sub.index,
+ )
+ setattr(future_sub, attr, current_comp)
+ else:
+ # Since these are sorted, and this one didn't match, we can be
+ # sure future ones won't match either.
+ break
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+
+ srt_tools.utils.set_basic_args(args)
+
+ muxed_subs = []
+ for idx, subs in enumerate(args.input):
+ for sub in subs:
+ if args.top_and_bottom:
+ if idx % 2 == 0:
+ sub.content = TOP + sub.content
+ else:
+ sub.content = BOTTOM + sub.content
+ muxed_subs.append(sub)
+
+ if args.no_time_matching or not args.top_and_bottom:
+ merge_subs(muxed_subs, args.ms, "start", args.width)
+ merge_subs(muxed_subs, args.ms, "end", args.width)
+
+ output = srt_tools.utils.compose_suggest_on_fail(muxed_subs, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-normalise b/.local/bin/srt-normalise
new file mode 100755
index 0000000..51461ce
--- /dev/null
+++ b/.local/bin/srt-normalise
@@ -0,0 +1,28 @@
+#!/usr/local/bin/python3
+
+"""Takes a badly formatted SRT file and outputs a strictly valid one."""
+
+import srt_tools.utils
+import logging
+
+log = logging.getLogger(__name__)
+
+
+def main():
+ examples = {"Normalise a subtitle": "srt normalise -i bad.srt -o good.srt"}
+
+ args = srt_tools.utils.basic_parser(
+ description=__doc__, examples=examples, hide_no_strict=True
+ ).parse_args()
+ logging.basicConfig(level=args.log_level)
+ srt_tools.utils.set_basic_args(args)
+ output = srt_tools.utils.compose_suggest_on_fail(args.input, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-play b/.local/bin/srt-play
new file mode 100755
index 0000000..e967a16
--- /dev/null
+++ b/.local/bin/srt-play
@@ -0,0 +1,59 @@
+#!/usr/local/bin/python3
+
+"""Play subtitles with correct timing to stdout."""
+
+from __future__ import print_function
+import logging
+from threading import Timer, Lock
+import srt_tools.utils
+import sys
+import time
+
+log = logging.getLogger(__name__)
+output_lock = Lock()
+
+
+def print_sub(sub, encoding):
+ log.debug("Timer woke up to print %s", sub.content)
+
+ with output_lock:
+ try:
+ sys.stdout.write(sub.content + "\n\n")
+ except UnicodeEncodeError: # Python 2 fallback
+ sys.stdout.write(sub.content.encode(encoding) + "\n\n")
+ sys.stdout.flush()
+
+
+def schedule(subs, encoding):
+ timers = set()
+ log.debug("Scheduling subtitles")
+
+ for sub in subs:
+ secs = sub.start.total_seconds()
+ cur_timer = Timer(secs, print_sub, [sub, encoding])
+ cur_timer.name = "%s:%s" % (sub.index, secs)
+ cur_timer.daemon = True
+ log.debug('Adding "%s" to schedule queue', cur_timer.name)
+ timers.add(cur_timer)
+
+ for timer in timers:
+ log.debug('Starting timer for "%s"', timer.name)
+ timer.start()
+
+ while any(t.is_alive() for t in timers):
+ time.sleep(0.5)
+
+
+def main():
+ examples = {"Play a subtitle": "srt play -i foo.srt"}
+
+ args = srt_tools.utils.basic_parser(
+ description=__doc__, examples=examples, no_output=True
+ ).parse_args()
+ logging.basicConfig(level=args.log_level)
+ srt_tools.utils.set_basic_args(args)
+ schedule(args.input, args.encoding)
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/srt-process b/.local/bin/srt-process
new file mode 100755
index 0000000..cba3695
--- /dev/null
+++ b/.local/bin/srt-process
@@ -0,0 +1,57 @@
+#!/usr/local/bin/python3
+
+"""Process subtitle text content using arbitrary Python code."""
+
+import importlib
+import srt_tools.utils
+import logging
+
+log = logging.getLogger(__name__)
+
+
+def strip_to_matching_lines_only(subtitles, imports, func_str):
+ for import_name in imports:
+ real_import = importlib.import_module(import_name)
+ globals()[import_name] = real_import
+
+ func = eval(func_str) # pylint: disable-msg=eval-used
+
+ for subtitle in subtitles:
+ subtitle.content = func(subtitle.content)
+ yield subtitle
+
+
+def parse_args():
+ examples = {
+ "Strip HTML-like symbols from a subtitle": """srt process -m re -f 'lambda sub: re.sub("<[^<]+?>", "", sub)'"""
+ }
+
+ parser = srt_tools.utils.basic_parser(description=__doc__, examples=examples)
+ parser.add_argument(
+ "-f", "--func", help="a function to use to process lines", required=True
+ )
+ parser.add_argument(
+ "-m",
+ "--module",
+ help="modules to import in the function context",
+ action="append",
+ default=[],
+ )
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+ logging.basicConfig(level=args.log_level)
+ srt_tools.utils.set_basic_args(args)
+ processed_subs = strip_to_matching_lines_only(args.input, args.module, args.func)
+ output = srt_tools.utils.compose_suggest_on_fail(processed_subs, strict=args.strict)
+
+ try:
+ args.output.write(output)
+ except (UnicodeEncodeError, TypeError): # Python 2 fallback
+ args.output.write(output.encode(args.encoding))
+
+
+if __name__ == "__main__": # pragma: no cover
+ main()
diff --git a/.local/bin/stage2 b/.local/bin/stage2
new file mode 100755
index 0000000..4f06c0d
--- /dev/null
+++ b/.local/bin/stage2
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from mtkclient.stage2 import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/statusbar/sb-battery b/.local/bin/statusbar/sb-battery
new file mode 100755
index 0000000..79030bc
--- /dev/null
+++ b/.local/bin/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) setsid -f "$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/.local/bin/statusbar/sb-brightness b/.local/bin/statusbar/sb-brightness
new file mode 100755
index 0000000..913387b
--- /dev/null
+++ b/.local/bin/statusbar/sb-brightness
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# current brightness
+curr_brightness=$(cat /sys/class/backlight/*/brightness)
+
+# max_brightness
+max_brightness=$(cat /sys/class/backlight/*/max_brightness)
+
+# brightness percentage
+brightness_per=$((100 * curr_brightness / max_brightness))
+
+case $BLOCK_BUTTON in
+ 1)
+ ;;
+ 3)
+ notify-send "💡 Brightness module" "\- Shows current brightness level ☀️."
+ ;;
+ 6)
+ setsid -f "$TERMINAL" -e "$EDITOR" "$0"
+ ;;
+esac
+
+echo "💡 ${brightness_per}%"
diff --git a/.local/bin/statusbar/sb-clock b/.local/bin/statusbar/sb-clock
new file mode 100755
index 0000000..e9c2fe6
--- /dev/null
+++ b/.local/bin/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 | sed "s/\<$(date +'%e'|tr -d ' ')\>/<b><span color='red'>&<\/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+date "+%Y %b %d (%a) $icon%I:%M%p"
diff --git a/.local/bin/statusbar/sb-cpu b/.local/bin/statusbar/sb-cpu
new file mode 100755
index 0000000..5b8fb93
--- /dev/null
+++ b/.local/bin/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+sensors | awk '/Core 0/ {print "🌡" $3}'
diff --git a/.local/bin/statusbar/sb-cpubars b/.local/bin/statusbar/sb-cpubars
new file mode 100755
index 0000000..4015893
--- /dev/null
+++ b/.local/bin/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# id total idle
+stats=$(awk '/cpu[0-9]+/ {printf "%d %d %d\n", substr($1,4), ($2 + $3 + $4 + $5), $5 }' /proc/stat)
+[ ! -f $cache ] && echo "$stats" > "$cache"
+old=$(cat "$cache")
+printf "🪨"
+echo "$stats" | while read -r row; do
+ id=${row%% *}
+ rest=${row#* }
+ total=${rest%% *}
+ idle=${rest##* }
+
+ case "$(echo "$old" | awk '{if ($1 == id)
+ printf "%d\n", (1 - (idle - $3) / (total - $2))*100 /12.5}' \
+ id="$id" total="$total" idle="$idle")" in
+
+ "0") printf "▁";;
+ "1") printf "▂";;
+ "2") printf "▃";;
+ "3") printf "▄";;
+ "4") printf "▅";;
+ "5") printf "▆";;
+ "6") printf "▇";;
+ "7") printf "█";;
+ "8") printf "█";;
+ esac
+done; printf "\\n"
+echo "$stats" > "$cache"
diff --git a/.local/bin/statusbar/sb-disk b/.local/bin/statusbar/sb-disk
new file mode 100755
index 0000000..7f3ff79
--- /dev/null
+++ b/.local/bin/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) setsid -f "$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/.local/bin/statusbar/sb-doppler b/.local/bin/statusbar/sb-doppler
new file mode 100755
index 0000000..a687c68
--- /dev/null
+++ b/.local/bin/statusbar/sb-doppler
@@ -0,0 +1,280 @@
+#!/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: CONUS: Continental United States
+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, SD
+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. Norway, Sweden And Denmark
+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
+DE: BAW: Baden-Württemberg
+DE: BAY: Bavaria
+DE: BBB: Berlin
+DE: BBB: Brandenburg
+DE: HES: Hesse
+DE: MVP: Mecklenburg-Western Pomerania
+DE: NIB: Lower Saxony
+DE: NIB: Bremen
+DE: NRW: North Rhine-Westphalia
+DE: RPS: Rhineland-Palatinate
+DE: RPS: Saarland
+DE: SAC: Saxony
+DE: SAA: Saxony-Anhalt
+DE: SHH: Schleswig-Holstein
+DE: SHH: Hamburg
+DE: THU: Thuringia" | dmenu -r -i -l 50 -p "Select a radar to use as default:" | tr "[:lower:]" "[:upper:]")"
+
+# Ensure user did not escape.
+[ -z "$chosen" ] && exit 1
+
+# Set continent code and radar code.
+continentcode=${chosen%%:*}
+radarcode=${chosen#* } radarcode=${radarcode%:*}
+
+# Print codes to $radarloc file.
+ printf "%s,%s\\n" "$continentcode" "$radarcode" > "$radarloc" ;}
+
+getdoppler() {
+ cont=$(cut -c -2 "$radarloc")
+ loc=$(cut -c 4- "$radarloc")
+ notify-send "🌦️ Doppler RADAR" "Pulling most recent Doppler RADAR for $loc."
+ case "$cont" in
+ "US") curl -sL "https://radar.weather.gov/ridge/standard/${loc}_loop.gif" > "$doppler" ;;
+ "EU") curl -sL "https://api.sat24.com/animated/${loc}/rainTMC/2/" > "$doppler" ;;
+ "AF") curl -sL "https://api.sat24.com/animated/${loc}/rain/2/" > "$doppler" ;;
+ "DE") loc="$(echo "$loc" | tr "[:upper:]" "[:lower:]")"
+ curl -sL "https://www.dwd.de/DWD/wetter/radar/radfilm_${loc}_akt.gif" > "$doppler" ;;
+ esac
+}
+
+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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo 🌅
diff --git a/.local/bin/statusbar/sb-forecast b/.local/bin/statusbar/sb-forecast
new file mode 100755
index 0000000..5225601
--- /dev/null
+++ b/.local/bin/statusbar/sb-forecast
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Displays today's precipication chance (☔), and daily low (🥶) and high (🌞).
+# Usually intended for the statusbar.
+
+url="${WTTRURL:-wttr.in}"
+weatherreport="${XDG_CACHE_HOME:-$HOME/.cache}/weatherreport"
+
+# Get a weather report from 'wttr.in' and save it locally.
+getforecast() { timeout --signal=1 2s curl -sf "$url/$LOCATION" > "$weatherreport" || exit 1; }
+
+# Forecast should be updated only once a day.
+checkforecast() {
+ [ -s "$weatherreport" ] && [ "$(stat -c %y "$weatherreport" 2>/dev/null |
+ cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ]
+}
+
+getprecipchance() {
+ echo "$weatherdata" | sed '16q;d' | # Extract line 16 from file
+ grep -wo "[0-9]*%" | # Find a sequence of digits followed by '%'
+ sort -rn | # Sort in descending order
+ head -1q # Extract first line
+}
+
+getdailyhighlow() {
+ echo "$weatherdata" | sed '13q;d' | # Extract line 13 from file
+ grep -o "m\\([-+]\\)*[0-9]\\+" | # Find temperatures in the format "m<signed number>"
+ sed 's/[+m]//g' | # Remove '+' and 'm'
+ sort -g | # Sort in ascending order
+ sed -e 1b -e '$!d' # Extract the first and last lines
+}
+
+readfile() { weatherdata="$(cat "$weatherreport")" ;}
+
+showweather() {
+ readfile
+ printf "☔%s 🥶%s° 🌞%s°\n" "$(getprecipchance)" $(getdailyhighlow)
+}
+
+case $BLOCK_BUTTON in
+ 1) setsid -f "$TERMINAL" -e less -Sf "$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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+checkforecast || getforecast
+
+showweather
diff --git a/.local/bin/statusbar/sb-help-icon b/.local/bin/statusbar/sb-help-icon
new file mode 100755
index 0000000..8372e6f
--- /dev/null
+++ b/.local/bin/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac; echo "❓"
diff --git a/.local/bin/statusbar/sb-internet b/.local/bin/statusbar/sb-internet
new file mode 100755
index 0000000..6d0c513
--- /dev/null
+++ b/.local/bin/statusbar/sb-internet
@@ -0,0 +1,33 @@
+#!/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# Wifi
+if [ "$(cat /sys/class/net/w*/operstate 2>/dev/null)" = 'up' ] ; then
+ wifiicon="$(awk '/^\s*w/ { print "📶", int($3 * 100 / 70) "% " }' /proc/net/wireless)"
+elif [ "$(cat /sys/class/net/w*/operstate 2>/dev/null)" = 'down' ] ; then
+ [ "$(cat /sys/class/net/w*/flags 2>/dev/null)" = '0x1003' ] && wifiicon="📡 " || wifiicon="❌ "
+fi
+
+# Ethernet
+[ "$(cat /sys/class/net/e*/operstate 2>/dev/null)" = 'up' ] && ethericon="🌐" || ethericon="❎"
+
+# TUN
+[ -n "$(cat /sys/class/net/tun*/operstate 2>/dev/null)" ] && tunicon=" 🔒"
+
+printf "%s%s%s\n" "$wifiicon" "$ethericon" "$tunicon"
diff --git a/.local/bin/statusbar/sb-iplocate b/.local/bin/statusbar/sb-iplocate
new file mode 100755
index 0000000..a9043e3
--- /dev/null
+++ b/.local/bin/statusbar/sb-iplocate
@@ -0,0 +1,15 @@
+#!/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/
+
+set -e
+
+ifinstalled "geoip"
+addr="$(geoiplookup "$(curl -sfm 1 ifconfig.me 2>/dev/null)")"
+name="${addr##*, }"
+flag="$(grep "flag: $name" "${XDG_DATA_HOME:-$HOME/.local/share}/larbs/emoji")"
+flag="${flag%% *}"
+printf "%s %s\\n" "$flag" "$name"
diff --git a/.local/bin/statusbar/sb-kbselect b/.local/bin/statusbar/sb-kbselect
new file mode 100755
index 0000000..df455c1
--- /dev/null
+++ b/.local/bin/statusbar/sb-kbselect
@@ -0,0 +1,17 @@
+#!/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)"
+ [ -z "$kb_choice" ] && exit 0
+ 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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+echo "$kb"
diff --git a/.local/bin/statusbar/sb-mailbox b/.local/bin/statusbar/sb-mailbox
new file mode 100755
index 0000000..7483aa4
--- /dev/null
+++ b/.local/bin/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 -w -f "$TERMINAL" -e neomutt; pkill -RTMIN+12 "${STATUSBAR:-dwmblocks}" ;;
+ 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) setsid -f "$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/.local/bin/statusbar/sb-memory b/.local/bin/statusbar/sb-memory
new file mode 100755
index 0000000..8178b10
--- /dev/null
+++ b/.local/bin/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) setsid -f "$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/.local/bin/statusbar/sb-moonphase b/.local/bin/statusbar/sb-moonphase
new file mode 100755
index 0000000..d496ae2
--- /dev/null
+++ b/.local/bin/statusbar/sb-moonphase
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Shows the current moon phase.
+
+moonfile="${XDG_DATA_HOME:-$HOME/.local/share}/moonphase"
+
+[ -s "$moonfile" ] && [ "$(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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/.local/bin/statusbar/sb-mpdup b/.local/bin/statusbar/sb-mpdup
new file mode 100755
index 0000000..af81a7d
--- /dev/null
+++ b/.local/bin/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/.local/bin/statusbar/sb-music b/.local/bin/statusbar/sb-music
new file mode 100755
index 0000000..6734eeb
--- /dev/null
+++ b/.local/bin/statusbar/sb-music
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+filter() { sed "/^volume:/d;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 ; setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+ *) mpc status | filter ;;
+esac
diff --git a/.local/bin/statusbar/sb-nettraf b/.local/bin/statusbar/sb-nettraf
new file mode 100755
index 0000000..08cb829
--- /dev/null
+++ b/.local/bin/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+update() {
+ sum=0
+ for arg; do
+ read -r i < "$arg"
+ sum=$(( sum + i ))
+ done
+ cache=/tmp/${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/.local/bin/statusbar/sb-news b/.local/bin/statusbar/sb-news
new file mode 100755
index 0000000..cc481e1
--- /dev/null
+++ b/.local/bin/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) setsid -f "$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/.local/bin/statusbar/sb-pacpackages b/.local/bin/statusbar/sb-pacpackages
new file mode 100755
index 0000000..6acdce6
--- /dev/null
+++ b/.local/bin/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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+pacman -Qu | grep -Fcv "[ignored]" | sed "s/^/📦/;s/^📦0$//g"
diff --git a/.local/bin/statusbar/sb-popupgrade b/.local/bin/statusbar/sb-popupgrade
new file mode 100755
index 0000000..29d6230
--- /dev/null
+++ b/.local/bin/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/.local/bin/statusbar/sb-price b/.local/bin/statusbar/sb-price
new file mode 100755
index 0000000..611ec36
--- /dev/null
+++ b/.local/bin/statusbar/sb-price
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# Usage:
+# price <currency-base currency> <name of currency> <icon> <signal>
+# price bat-btc "Basic Attention Token" 🦁 24
+# This will give the price of BAT denominated in BTC and will update on
+# signal 24.
+# When the name of the currency is multi-word, put it in quotes.
+
+[ -z "$1" ] && exit 1
+
+url="${CRYPTOURL:-rate.sx}"
+target="${1%%-*}"
+denom="${1##*-}"
+name="${2:-$1}"
+icon="${3:-💰}"
+case "$denom" in
+ "$target"|usd) denom="usd"; symb="$" ;;
+ gbp) symb="£" ;;
+ eur) symb="€" ;;
+ btc) symb="" ;;
+esac
+interval="@14d" # History contained in chart preceded by '@' (7d = 7 days)
+dir="${XDG_CACHE_HOME:-$HOME/.cache}/crypto-prices"
+pricefile="$dir/$target-$denom"
+chartfile="$dir/$target-$denom-chart"
+filestat="$(stat -c %x "$pricefile" 2>/dev/null)"
+
+[ -d "$dir" ] || mkdir -p "$dir"
+
+updateprice() { curl -sf -m 1 --fail-early $denom.$url/{1$target,$target$interval} --output "$pricefile" --output "$chartfile" ||
+ rm -f "$pricefile" "$chartfile" ;}
+
+[ "${filestat%% *}" != "$(date '+%Y-%m-%d')" ] &&
+ updateme="1"
+
+case $BLOCK_BUTTON in
+ 1) setsid "$TERMINAL" -e less -Srf "$chartfile" ;;
+ 2) notify-send -u low "$icon Updating..." "Updating $name price..." ; updateme="1" ; showupdate="1" ;;
+ 3) uptime="$(date -d "$filestat" '+%D at %T' | sed "s|$(date '+%D')|Today|")"
+ notify-send "$icon $name 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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+[ -n "$updateme" ] &&
+ updateprice "$target" &&
+ [ -n "$showupdate" ] &&
+ notify-send "$icon Update complete." "$name price is now
+\$$(cat "$pricefile")"
+
+[ -f "$pricefile" ] && printf "%s%s%0.2f" "$icon" "$symb" "$(cat "$pricefile")"
diff --git a/.local/bin/statusbar/sb-tasks b/.local/bin/statusbar/sb-tasks
new file mode 100755
index 0000000..4beb2d0
--- /dev/null
+++ b/.local/bin/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
+ 6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+[ "$num" != "0(0)" ] &&
+ echo "🤖$num"
diff --git a/.local/bin/statusbar/sb-torrent b/.local/bin/statusbar/sb-torrent
new file mode 100755
index 0000000..493631b
--- /dev/null
+++ b/.local/bin/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 stig ;;
+ 2) td-toggle ;;
+ 3) notify-send "🌱 Torrent module" "\- Left click to open stig.
+- 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) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
diff --git a/.local/bin/statusbar/sb-volume b/.local/bin/statusbar/sb-volume
new file mode 100755
index 0000000..f9d406b
--- /dev/null
+++ b/.local/bin/statusbar/sb-volume
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# Prints the current volume or 🔇 if muted.
+
+case $BLOCK_BUTTON in
+ 1) setsid -w -f "$TERMINAL" -e pulsemixer; pkill -RTMIN+10 "${STATUSBAR:-dwmblocks}" ;;
+ 2) wpctl set-mute @DEFAULT_SINK@ toggle ;;
+ 4) wpctl set-volume @DEFAULT_SINK@ 1%+ ;;
+ 5) wpctl set-volume @DEFAULT_SINK@ 1%- ;;
+ 3) notify-send "📢 Volume module" "\- Shows volume 🔊, 🔇 if muted.
+- Middle click to mute.
+- Scroll to change." ;;
+ 6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+vol="$(wpctl get-volume @DEFAULT_AUDIO_SINK@)"
+
+# If muted, print 🔇 and exit.
+[ "$vol" != "${vol%\[MUTED\]}" ] && echo 🔇 && exit
+
+vol="${vol#Volume: }"
+
+split() {
+ # For ommiting the . without calling and external program.
+ IFS=$2
+ set -- $1
+ printf '%s' "$@"
+}
+
+vol="$(printf "%.0f" "$(split "$vol" ".")")"
+
+case 1 in
+ $((vol >= 70)) ) icon="🔊" ;;
+ $((vol >= 30)) ) icon="🔉" ;;
+ $((vol >= 1)) ) icon="🔈" ;;
+ * ) echo 🔇 && exit ;;
+esac
+
+echo "$icon$vol%"
diff --git a/.local/bin/switch_audio b/.local/bin/switch_audio
new file mode 100755
index 0000000..db01fee
--- /dev/null
+++ b/.local/bin/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/.local/bin/symilar b/.local/bin/symilar
new file mode 100755
index 0000000..8e62aa6
--- /dev/null
+++ b/.local/bin/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/.local/bin/sysact b/.local/bin/sysact
new file mode 100755
index 0000000..64c2f32
--- /dev/null
+++ b/.local/bin/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 -i ;;
+ '💤 sleep') slock $ctl suspend -i ;;
+ '🔃 reboot') $ctl reboot -i ;;
+ '🖥️shutdown') $ctl poweroff -i ;;
+ '📺 display off') xset dpms force off ;;
+ *) exit 1 ;;
+esac
diff --git a/.local/bin/system_action b/.local/bin/system_action
new file mode 100755
index 0000000..32fe118
--- /dev/null
+++ b/.local/bin/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/.local/bin/tag b/.local/bin/tag
new file mode 100755
index 0000000..92d6323
--- /dev/null
+++ b/.local/bin/tag
@@ -0,0 +1,49 @@
+#!/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:" 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}" ;;
+ *) printf "Invalid option: -%s\\n" "$OPTARG" && err ;;
+esac done
+
+shift $((OPTIND - 1))
+
+file="$1"
+
+temp="$(mktemp -p "$(dirname "$file")")"
+trap 'rm -f $temp' HUP INT QUIT TERM PWR EXIT
+
+[ ! -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
+
+cp -f "$file" "$temp" && ffmpeg -i "$temp" -map 0 -y -codec copy \
+ -metadata title="$title" \
+ -metadata album="$album" \
+ -metadata artist="$artist" \
+ -metadata track="${track}${total:+/"$total"}" \
+ ${date:+-metadata date="$date"} \
+ ${genre:+-metadata genre="$genre"} \
+ ${comment:+-metadata comment="$comment"} "$file"
diff --git a/.local/bin/td-toggle b/.local/bin/td-toggle
new file mode 100755
index 0000000..de1a0e6
--- /dev/null
+++ b/.local/bin/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-daemon && 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/.local/bin/tensorboard b/.local/bin/tensorboard
new file mode 100755
index 0000000..1d31332
--- /dev/null
+++ b/.local/bin/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/.local/bin/texclear b/.local/bin/texclear
new file mode 100755
index 0000000..6ad3c12
--- /dev/null
+++ b/.local/bin/texclear
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Clears the build files of a LaTeX/XeLaTeX build.
+# I have vim run this file whenever I exit a .tex file.
+
+[ "${1##*.}" = "tex" ] && {
+ find "$(dirname "${1}")" -regex '.*\(_minted.*\|.*\.\(4tc\|xref\|tmp\|pyc\|pyg\|pyo\|fls\|vrb\|fdb_latexmk\|bak\|swp\|aux\|log\|synctex\(busy\)\|lof\|lot\|maf\|idx\|mtc\|mtc0\|nav\|out\|snm\|toc\|bcf\|run\.xml\|synctex\.gz\|blg\|bbl\)\)' -delete
+} || printf "Provide a .tex file.\n"
+
diff --git a/.local/bin/tf_upgrade_v2 b/.local/bin/tf_upgrade_v2
new file mode 100755
index 0000000..8324a59
--- /dev/null
+++ b/.local/bin/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/.local/bin/tflite_convert b/.local/bin/tflite_convert
new file mode 100755
index 0000000..0739b41
--- /dev/null
+++ b/.local/bin/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/.local/bin/toco b/.local/bin/toco
new file mode 100755
index 0000000..0739b41
--- /dev/null
+++ b/.local/bin/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/.local/bin/toco_from_protos b/.local/bin/toco_from_protos
new file mode 100755
index 0000000..191ec30
--- /dev/null
+++ b/.local/bin/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/.local/bin/torwrap b/.local/bin/torwrap
new file mode 100755
index 0000000..39f89b0
--- /dev/null
+++ b/.local/bin/torwrap
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+ifinstalled stig transmission-cli || exit 1
+
+! pidof transmission-daemon >/dev/null && transmission-daemon && notify-send "Starting torrent daemon..."
+
+$TERMINAL -e stig; pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}"
diff --git a/.local/bin/tqdm b/.local/bin/tqdm
new file mode 100755
index 0000000..52ed2be
--- /dev/null
+++ b/.local/bin/tqdm
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3
+# -*- 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/.local/bin/transadd b/.local/bin/transadd
new file mode 100755
index 0000000..a598fad
--- /dev/null
+++ b/.local/bin/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/.local/bin/ttx b/.local/bin/ttx
new file mode 100755
index 0000000..cbf3142
--- /dev/null
+++ b/.local/bin/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/.local/bin/tutorialvids b/.local/bin/tutorialvids
new file mode 100755
index 0000000..1bac3df
--- /dev/null
+++ b/.local/bin/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
+dwmblocks (status bar) https://videos.lukesmith.xyz/w/mmxHMbqZZEr5FManB57Yy1
+pacman (installing/managing programs) https://videos.lukesmith.xyz/videos/watch/8e7cadb9-0fed-47ce-a2a8-6635fa48614b
+sxiv/nsxiv (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/.local/bin/undill b/.local/bin/undill
new file mode 100755
index 0000000..1362d75
--- /dev/null
+++ b/.local/bin/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/.local/bin/unix b/.local/bin/unix
new file mode 100755
index 0000000..a9fb96e
--- /dev/null
+++ b/.local/bin/unix
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#original artwork by http://www.sanderfocus.nl/#/portfolio/tech-heroes
+#converted to shell by #nixers @ irc.unix.chat
+
+cat << 'eof'
+ ,_ ,_==▄▂
+ , ▂▃▄▄▅▅▅▂▅¾. / /
+ ▄▆<´ "»▓▓▓%\ / / / /
+ ,▅7" ´>▓▓▓% / / > / >/%
+ ▐¶▓ ,»▓▓¾´ /> %/%// / /
+ ▓▃▅▅▅▃,,▄▅▅▅Æ\// ///>// />/ /
+ V║«¼.;→ ║<«.,`=// />//%/% / /
+ //╠<´ -²,)(▓~"-╝/¾/ %/>/ />
+ / / / ▐% -./▄▃▄▅▐, /7//;//% / /
+ / ////`▌▐ %zWv xX▓▇▌//&;% / /
+ / / / %//%/¾½´▌▃▄▄▄▄▃▃▐¶\/& /
+ </ /</%//`▓!%▓%╣[38;5;255;╣WY<Y)y&/`\
+ / / %/%//</%//\i7; ╠N>)VY>7; \_ UNIX IS VERY SIMPLE IT JUST NEEDS A
+ / /</ //<///<_/%\▓ V%W%£)XY _/%‾\_, GENIUS TO UNDERSTAND ITS SIMPLICITY
+ / / //%/_,=--^/%/%%\¾%¶%%} /%%%%%%;\,
+ %/< /_/ %%%%%;X%%\%%;, _/%%%;, \
+ / / %%%%%%;, \%%l%%;// _/%;, dmr
+ / %%%;, <;\-=-/ /
+ ;, l
+eof
diff --git a/.local/bin/unmounter b/.local/bin/unmounter
new file mode 100755
index 0000000..7f1dbf5
--- /dev/null
+++ b/.local/bin/unmounter
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Unmount USB drives or Android phones. Replaces the older `dmenuumount`. Fewer
+# prompt and also de-decrypts LUKS drives that are unmounted.
+
+set -e
+
+mounteddroids="$(grep simple-mtpfs /etc/mtab | awk '{print "📱" $2}')"
+lsblkoutput="$(lsblk -nrpo "name,type,size,mountpoint")"
+mounteddrives="$(echo "$lsblkoutput" | awk '($2=="part"||$2="crypt")&&$4!~/\/boot|\/home$|SWAP/&&length($4)>1{printf "💾%s (%s)\n",$4,$3}')"
+
+allunmountable="$(echo "$mounteddroids
+$mounteddrives" | sed "/^$/d;s/ *$//")"
+test -n "$allunmountable"
+
+chosen="$(echo "$allunmountable" | dmenu -i -p "Unmount which drive?")"
+chosen="${chosen%% *}"
+test -n "$chosen"
+
+sudo -A umount -l "/${chosen#*/}"
+notify-send "Device unmounted." "$chosen has been unmounted."
+
+# Close the chosen drive if decrypted.
+cryptid="$(echo "$lsblkoutput" | grep "/${chosen#*/}$")"
+cryptid="${cryptid%% *}"
+test -b /dev/mapper/"${cryptid##*/}"
+sudo -A cryptsetup close "$cryptid"
+notify-send "🔒Device dencryption closed." "Drive is now securely locked again."
diff --git a/.local/bin/upload.py b/.local/bin/upload.py
new file mode 100644
index 0000000..a4ee091
--- /dev/null
+++ b/.local/bin/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/.local/bin/vosk-transcriber b/.local/bin/vosk-transcriber
new file mode 100755
index 0000000..8dd1ccd
--- /dev/null
+++ b/.local/bin/vosk-transcriber
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3
+# -*- coding: utf-8 -*-
+import re
+import sys
+from vosk.transcriber.cli import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/waldl b/.local/bin/waldl
new file mode 100755
index 0000000..d90dec2
--- /dev/null
+++ b/.local/bin/waldl
@@ -0,0 +1,161 @@
+#!/bin/sh
+
+# https://git.surgot.tech/waldl
+# script to find and download wallpapers from wallhaven
+version="0.0.1"
+
+# Usage:
+# waldl <query>
+# if query left empty then sh_menu will be used (dmenu by default)
+# after the thumbnails are cached, sxiv would open up with the thumbnails
+# Select the wallpapers using `m` on the image. ( marking the image in sxiv )
+# press `q` to quit sxiv, the marked images would start downloading
+
+####################
+## User variables ##
+####################
+
+[ -z $VIEWER ] && VIEWER=sxiv
+# the dir where wallpapers are stored
+walldir="$HOME/pix/wall"
+# the dir used to cache thumbnails
+cachedir="$HOME/.cache/wall"
+# sxiv options
+sxiv_otps=" -tfpo -z 200" # o is needed for selection
+# number of pages to show in search results
+# each page contains 24 results
+max_pages=4
+# sorting : date_added, relevance, random, views, favorites, toplist
+sorting=relevance
+# quality : large original small
+quality=large
+# atleast : least res
+atleast=1920x1080
+
+# allow the user to customize the defaults
+[ -e "$HOME/.config/waldlrc" ] && . "$HOME/.config/waldlrc"
+
+# the menu command used when no query is provided
+sh_menu () {
+ : | dmenu -p "search wallhaven:"
+ # ROFI: comment the previous line and uncomment the next line for rofi
+ # rofi -dmenu -l 0 -p "search wallpapers"
+}
+
+##########################
+## getting search query ##
+##########################
+
+[ -n "$*" ] && query="$*" || query=$( sh_menu )
+[ -z "$query" ] && exit 1
+query=$(printf '%s' "$query" | tr ' ' '+' )
+
+######################
+## start up commands #
+######################
+
+rm -rf "$cachedir"
+mkdir -p "$walldir" "$cachedir"
+
+# progress display command
+sh_info () {
+ printf "%s\n" "$1" >&2
+ notify-send "wallhaven" "$1"
+ [ -n "$2" ] && exit "$2"
+}
+
+# dependency checking
+dep_ck () {
+ for pr; do
+ command -v $pr >/dev/null 2>&1 || sh_info "command $pr not found, install: $pr" 1
+ done
+}
+dep_ck "$VIEWER" "curl" "jq"
+
+
+# clean up command that would be called when the program exits
+clean_up () {
+ printf "%s\n" "cleaning up..." >&2
+ rm -rf "$datafile" "$cachedir"
+}
+
+# data file to store the api information
+datafile="/tmp/wald.$$"
+
+# clean up if killed
+trap "exit" INT TERM
+trap "clean_up" EXIT
+
+##################
+## getting data ##
+##################
+
+# request the search results for each page
+get_results () {
+ for page_no in $(seq $max_pages)
+ do
+ {
+ json=$(curl -s -G "https://wallhaven.cc/api/v1/search" \
+ -d "q=$1" \
+ -d "page=$page_no" \
+ -d "atleast=$atleast" \
+ -d "sorting=$sorting"
+ )
+ printf "%s\n" "$json" >> "$datafile"
+ } &
+ sleep 0.001
+ done
+ wait
+}
+
+# search wallpapers
+sh_info "getting data..."
+get_results "$query"
+
+# check if data file is empty, if so then exit
+[ -s "$datafile" ] || sh_info "no images found" 1
+
+############################
+## downloading thumbnails ##
+############################
+
+# get a list of thumnails from the data
+thumbnails=$( jq -r '.data[]?|.thumbs.'"$quality" < "$datafile")
+
+[ -z "$thumbnails" ] && sh_info "no-results found" 1
+
+# download the thumbnails
+sh_info "caching thumbnails..."
+for url in $thumbnails
+do
+ printf "url = %s\n" "$url"
+ printf "output = %s\n" "$cachedir/${url##*/}"
+done | curl -Z -K -
+#sh_info "downloaded thumbnails..."
+
+###########################
+## user selection (sxiv) ##
+###########################
+
+# extract the id's out of the thumbnail name
+image_ids="$($VIEWER $sxiv_otps "$cachedir")"
+[ -z "$image_ids" ] && exit
+
+#########################
+## download wallpapers ##
+#########################
+
+# download the selected wall papers
+cd "$walldir"
+sh_info "downloading wallpapers..."
+for ids in $image_ids
+do
+ ids="${ids##*/}"
+ ids="${ids%.*}"
+ url=$( jq -r '.data[]?|select( .id == "'$ids'" )|.path' < "$datafile" )
+ printf "url = %s\n" "$url"
+ printf -- "-O\n"
+done | curl -K -
+
+sh_info "wallpapers downloaded in:- '$walldir'"
+$VIEWER $(ls -c)
diff --git a/.local/bin/weath b/.local/bin/weath
new file mode 100644
index 0000000..a526411
--- /dev/null
+++ b/.local/bin/weath
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Get the weather on the terminal. You can pass an alternative location as a parameter,
+# and/or use the 'cp' option to copy the forecast as plaintext to the clipboard.
+
+report="${XDG_CACHE_HOME:-$HOME/.cache}/weatherreport"
+
+if [ "$1" = 'cp' ]; then
+ # shellcheck disable=SC2015
+ [ -z "$2" ] && sed 's/\x1b\[[^m]*m//g' "$report" | xclip -selection clipboard &&
+ notify-send "Weather forecast for '${LOCATION:-$(head -n 1 "$report" | cut -d' ' -f3-)}' copied to clipboard." ||
+ { data="$(curl -sfm 5 "${WTTRURL:-wttr.in}/$2?T")" &&
+ notify-send "Weather forecast for '$2' copied to clipboard." &&
+ echo "$data" | xclip -selection clipboard ||
+ notify-send 'Failed to get weather forecast!' 'Check your internet connection and the supplied location.'; }
+else
+ [ -n "$2" ] &&
+ notify-send "Invalid option '$1'! The only valid option is 'cp'." &&
+ exit 1
+
+ # shellcheck disable=SC2015
+ [ -z "$1" ] && less -S "$report" ||
+ data="$(curl -sfm 5 "${WTTRURL:-wttr.in}/$1")" && echo "$data" | less -S ||
+ notify-send 'Failed to get weather forecast!' 'Check your internet connection and the supplied location.'
+fi
diff --git a/.local/bin/wheel b/.local/bin/wheel
new file mode 100755
index 0000000..c904a27
--- /dev/null
+++ b/.local/bin/wheel
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- 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/.local/bin/xdg-terminal-exec b/.local/bin/xdg-terminal-exec
new file mode 100755
index 0000000..12b18ff
--- /dev/null
+++ b/.local/bin/xdg-terminal-exec
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+"$TERMINAL" -e "$@"
diff --git a/.local/bin/xmlschema-json2xml b/.local/bin/xmlschema-json2xml
new file mode 100755
index 0000000..807970e
--- /dev/null
+++ b/.local/bin/xmlschema-json2xml
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from xmlschema.cli import json2xml
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(json2xml())
diff --git a/.local/bin/xmlschema-validate b/.local/bin/xmlschema-validate
new file mode 100755
index 0000000..c6a7dc8
--- /dev/null
+++ b/.local/bin/xmlschema-validate
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from xmlschema.cli import validate
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(validate())
diff --git a/.local/bin/xmlschema-xml2json b/.local/bin/xmlschema-xml2json
new file mode 100755
index 0000000..ff18c43
--- /dev/null
+++ b/.local/bin/xmlschema-xml2json
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from xmlschema.cli import xml2json
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(xml2json())
diff --git a/.local/bin/yappi b/.local/bin/yappi
new file mode 100755
index 0000000..8ff3064
--- /dev/null
+++ b/.local/bin/yappi
@@ -0,0 +1,8 @@
+#!/usr/local/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from yappi import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/.local/bin/ytplay b/.local/bin/ytplay
new file mode 100755
index 0000000..e505a3b
--- /dev/null
+++ b/.local/bin/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)"