From 83f04de8f13263a680865cc6e60c004b84da52fe Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Thu, 11 Sep 2025 10:33:31 +0200 Subject: [PATCH] feat: Add LARBS scripts --- .gitignore | 34 ++++++++++++ bin/getkeys | 5 ++ bin/ifinstalled | 12 +++++ bin/lfub | 24 +++++++++ bin/linkhandler | 23 ++++++++ bin/maimpick | 14 +++++ bin/noisereduce | 81 ++++++++++++++++++++++++++++ bin/normalizer | 8 +++ bin/opout | 13 +++++ bin/otp | 53 +++++++++++++++++++ bin/pauseallmpv | 10 ++++ bin/peertubetorrent | 7 +++ bin/podentr | 7 +++ bin/prompt | 8 +++ bin/pygmentize | 8 +++ bin/qndl | 12 +++++ bin/queueandnotify | 14 +++++ bin/remaps | 13 +++++ bin/rotdir | 12 +++++ bin/rssadd | 18 +++++++ bin/samedir | 10 ++++ bin/setbg | 33 ++++++++++++ bin/shortcuts | 43 +++++++++++++++ bin/slider | 126 ++++++++++++++++++++++++++++++++++++++++++++ bin/sysact | 28 ++++++++++ bin/tag | 67 +++++++++++++++++++++++ bin/td-toggle | 12 +++++ bin/texclear | 16 ++++++ bin/torwrap | 7 +++ bin/transadd | 9 ++++ bin/tutorialvids | 26 +++++++++ bin/vpn | 3 ++ 32 files changed, 756 insertions(+) create mode 100755 bin/getkeys create mode 100755 bin/ifinstalled create mode 100755 bin/lfub create mode 100755 bin/linkhandler create mode 100755 bin/maimpick create mode 100755 bin/noisereduce create mode 100755 bin/normalizer create mode 100755 bin/opout create mode 100755 bin/otp create mode 100755 bin/pauseallmpv create mode 100755 bin/peertubetorrent create mode 100755 bin/podentr create mode 100755 bin/prompt create mode 100755 bin/pygmentize create mode 100755 bin/qndl create mode 100755 bin/queueandnotify create mode 100755 bin/remaps create mode 100755 bin/rotdir create mode 100755 bin/rssadd create mode 100755 bin/samedir create mode 100755 bin/setbg create mode 100755 bin/shortcuts create mode 100755 bin/slider create mode 100755 bin/sysact create mode 100755 bin/tag create mode 100755 bin/td-toggle create mode 100755 bin/texclear create mode 100755 bin/torwrap create mode 100755 bin/transadd create mode 100755 bin/tutorialvids create mode 100755 bin/vpn diff --git a/.gitignore b/.gitignore index e7d64c1..31df7bd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,40 @@ !bin/statusbar !bin/statusbar/* +!bin/cron +!bin/cron/* +!bin/dmenu* +!bin/getkeys +!bin/ifinstalled +!bin/lfub +!bin/linkhandler +!bin/maimpick +!bin/noisereduce +!bin/normalizer +!bin/opout +!bin/otp +!bin/pauseallmpv +!bin/peertubetorrent +!bin/podentr +!bin/prompt +!bin/pygmentize +!bin/qndl +!bin/queueandnotify +!bin/remaps +!bin/rotdir +!bin/rssadd +!bin/samedir +!bin/setbg +!bin/shortcuts +!bin/slider +!bin/sysact +!bin/tag +!bin/td-toggle +!bin/texclear +!bin/torwrap +!bin/transadd +!bin/tutorialvids +!bin/vpn !share !share/larbs diff --git a/bin/getkeys b/bin/getkeys new file mode 100755 index 0000000..266f29a --- /dev/null +++ b/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/bin/ifinstalled b/bin/ifinstalled new file mode 100755 index 0000000..c192eba --- /dev/null +++ b/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/bin/lfub b/bin/lfub new file mode 100755 index 0000000..9012f50 --- /dev/null +++ b/bin/lfub @@ -0,0 +1,24 @@ +#!/bin/sh + +# This is a wrapper script for lb that allows it to create image previews with +# ueberzug. This works in concert with the lf configuration file and the +# lf-cleaner script. + +set -e + +cleanup() { + exec 3>&- + rm "$FIFO_UEBERZUG" +} + +if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then + lf "$@" +else + [ ! -d "$HOME/.cache/lf" ] && mkdir -p "$HOME/.cache/lf" + export FIFO_UEBERZUG="$HOME/.cache/lf/ueberzug-$$" + mkfifo "$FIFO_UEBERZUG" + ueberzug layer -s <"$FIFO_UEBERZUG" -p json & + exec 3>"$FIFO_UEBERZUG" + trap cleanup HUP INT QUIT TERM PWR EXIT + lf "$@" 3>&- +fi diff --git a/bin/linkhandler b/bin/linkhandler new file mode 100755 index 0000000..fa74caf --- /dev/null +++ b/bin/linkhandler @@ -0,0 +1,23 @@ +#!/bin/sh + +# Feed script a url or file location. +# If an image, it will view in sxiv, +# if a video or gif, it will view in mpv +# if a music file or pdf, it will download, +# otherwise it opens link in browser. + +# If no url given. Opens browser. For using script as $BROWSER. +[ -z "$1" ] && { "$BROWSER"; exit; } + +case "$1" in + *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtu.be*|*hooktube.com*|*bitchute.com*|*videos.lukesmith.xyz*|*odysee.com*) + setsid -f mpv -quiet "$1" >/dev/null 2>&1 ;; + *png|*jpg|*jpe|*jpeg|*gif) + curl -sL "$1" > "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;; + *pdf|*cbz|*cbr) + curl -sL "$1" > "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$1" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;; + *mp3|*flac|*opus|*mp3?source*) + qndl "$1" 'curl -LO' >/dev/null 2>&1 ;; + *) + [ -f "$1" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$1" >/dev/null 2>&1 || setsid -f "$BROWSER" "$1" >/dev/null 2>&1 +esac diff --git a/bin/maimpick b/bin/maimpick new file mode 100755 index 0000000..7125e61 --- /dev/null +++ b/bin/maimpick @@ -0,0 +1,14 @@ +#!/bin/sh + +# This is bound to Shift+PrintScreen by default, requires maim. It lets you +# choose the kind of screenshot to take, including copying the image or even +# highlighting an area to copy. scrotcucks on suicidewatch right now. + +case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -l 6 -i -p "Screenshot which area?")" in + "a selected area") maim -s pic-selected-"$(date '+%y%m%d-%H%M-%S').png" ;; + "current window") maim -i "$(xdotool getactivewindow)" pic-window-"$(date '+%y%m%d-%H%M-%S').png" ;; + "full screen") maim pic-full-"$(date '+%y%m%d-%H%M-%S').png" ;; + "a selected area (copy)") maim -s | xclip -selection clipboard -t image/png ;; + "current window (copy)") maim -i "$(xdotool getactivewindow)" | xclip -selection clipboard -t image/png ;; + "full screen (copy)") maim | xclip -selection clipboard -t image/png ;; +esac diff --git a/bin/noisereduce b/bin/noisereduce new file mode 100755 index 0000000..c344760 --- /dev/null +++ b/bin/noisereduce @@ -0,0 +1,81 @@ +#!/usr/bin/sh + +usage () +{ + printf "Usage : noisereduce \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/bin/normalizer b/bin/normalizer new file mode 100755 index 0000000..2479e13 --- /dev/null +++ b/bin/normalizer @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli.normalizer import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/bin/opout b/bin/opout new file mode 100755 index 0000000..faf6575 --- /dev/null +++ b/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|*.m[dse]|*.[rR]md|*.mom|*.[0-9]) setsid -f xdg-open "$basename".pdf >/dev/null 2>&1 ;; + *.html) setsid -f "$BROWSER" "$basename".html >/dev/null 2>&1 ;; + *.sent) setsid -f sent "$1" >/dev/null 2>&1 ;; +esac diff --git a/bin/otp b/bin/otp new file mode 100755 index 0000000..1726b1a --- /dev/null +++ b/bin/otp @@ -0,0 +1,53 @@ +#!/bin/sh + +# Get a one-time password, or add a OTP secret to your pass-otp store. + +# The assumption of this script is that all otp passwords are stored with the +# suffix `-otp`. This script automatically appends newly added otps as such. + +# For OTP passwords to be generated properly, it is important for the local +# computer to have its time properly synced. This can be done with the command +# below which requires the package `ntp`. + +ifinstalled pass pass-otp + +dir="${PASSWORD_STORE_DIR}" + +choice="$({ echo "🆕add" ; echo "🕙sync-time" ; ls ${dir}/*-otp.gpg ;} | sed "s/.*\///;s/-otp.gpg//" | dmenu -p "Pick a 2FA:")" + +case $choice in + 🆕add ) + ifinstalled maim zbar xclip || exit 1 + + temp="$dir/temp.png" + otp="otp-test-script" + trap 'shred -fu $temp; pass rm $otp' HUP INT QUIT TERM PWR EXIT + + notify-send "Scan the image." "Scan the OTP QR code." + + maim -s "$temp" || exit 1 + info="$(zbarimg -q "$temp")" + info="${info#QR-Code:}" + issuer="$(echo "$info" | grep -o "issuer=[A-z0-9]\+")" + name="${issuer#issuer=}" + + if echo "$info" | pass otp insert "$otp"; then + while true ; do + export name="$(dmenu -p "Give this One Time Password a one-word name:")" + echo "$name" | grep -q -- "^[A-z0-9-]\+$" && break + done + pass mv "$otp" "$name-otp" + notify-send "Successfully added." "$name-otp has been created." + else + notify-send "No OTP data found." "Try to scan the image again more precisely." + fi + + ;; + 🕙sync-time ) + ifinstalled ntp || exit 1 + notify-send -u low "🕙 Synchronizing Time..." "Synching time with remote NTP servers..." + updatedata="$(sudo ntpdate pool.ntp.org)" && + notify-send -u low "🕙 Synchronizing Time..." "Done. Time changed by ${updatedata#*offset }" + ;; + *) pass otp -c ${choice}-otp ;; +esac diff --git a/bin/pauseallmpv b/bin/pauseallmpv new file mode 100755 index 0000000..d69a414 --- /dev/null +++ b/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/bin/peertubetorrent b/bin/peertubetorrent new file mode 100755 index 0000000..7a7a483 --- /dev/null +++ b/bin/peertubetorrent @@ -0,0 +1,7 @@ +#!/bin/sh +# torrent peertube videos, requires the transadd script +# first argument is the video link, second is the quality (480 or 1080) +# 13/07/20 - Arthur Bais + +link="$(echo "$1" | sed "s/w/download\/torrents/")""-$2.torrent" +transadd "$link" diff --git a/bin/podentr b/bin/podentr new file mode 100755 index 0000000..9454b07 --- /dev/null +++ b/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/bin/prompt b/bin/prompt new file mode 100755 index 0000000..666434f --- /dev/null +++ b/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/bin/pygmentize b/bin/pygmentize new file mode 100755 index 0000000..3b60d99 --- /dev/null +++ b/bin/pygmentize @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pygments.cmdline import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/qndl b/bin/qndl new file mode 100755 index 0000000..48bc61e --- /dev/null +++ b/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/bin/queueandnotify b/bin/queueandnotify new file mode 100755 index 0000000..1c3025c --- /dev/null +++ b/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/bin/remaps b/bin/remaps new file mode 100755 index 0000000..3cb41e4 --- /dev/null +++ b/bin/remaps @@ -0,0 +1,13 @@ +#!/bin/sh + +# This script is called on startup to remap keys. +# Increase key speed via a rate change +xset r rate 300 50 +# Map the caps lock key to super... +setxkbmap -option caps:super +# But when it is pressed only once, treat it as escape. +killall xcape 2>/dev/null ; xcape -e 'Super_L=Escape' +# Map the menu button to right super as well. +xmodmap -e 'keycode 135 = Super_R' +# Turn off the caps lock if on since there is no longer a key for it. +xset -q | grep "Caps Lock:\s*on" && xdotool key Caps_Lock diff --git a/bin/rotdir b/bin/rotdir new file mode 100755 index 0000000..86da6db --- /dev/null +++ b/bin/rotdir @@ -0,0 +1,12 @@ +#!/bin/sh + +# When I open an image from the file manager in sxiv (the image viewer), I want +# to be able to press the next/previous keys to key through the rest of the +# images in the same directory. This script "rotates" the content of a +# directory based on the first chosen file, so that if I open the 15th image, +# if I press next, it will go to the 16th etc. Autistic, I know, but this is +# one of the reasons that sxiv is great for being able to read standard input. + +[ -z "$1" ] && echo "usage: rotdir regex 2>&1" && exit 1 +base="$(basename "$1")" +ls "$PWD" | awk -v BASE="$base" 'BEGIN { lines = ""; m = 0; } { if ($0 == BASE) { m = 1; } } { if (!m) { if (lines) { lines = lines"\n"; } lines = lines""$0; } else { print $0; } } END { print lines; }' diff --git a/bin/rssadd b/bin/rssadd new file mode 100755 index 0000000..910fca3 --- /dev/null +++ b/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/bin/samedir b/bin/samedir new file mode 100755 index 0000000..0a19707 --- /dev/null +++ b/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/bin/setbg b/bin/setbg new file mode 100755 index 0000000..2829896 --- /dev/null +++ b/bin/setbg @@ -0,0 +1,33 @@ +#!/bin/sh + +# This script does the following: +# Run by itself, set the wallpaper (at X start). +# If given a file, set that as the new wallpaper. +# If given a directory, choose random file in it. +# If wal is installed, also generates a colorscheme. + +# Location of link to wallpaper link. +bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/bg" + +# Configuration files of applications that have their themes changed by pywal. +dunstconf="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc" +zathuraconf="${XDG_CONFIG_HOME:-$HOME/.config}/zathura/zathurarc" + +trueloc="$(readlink -f "$1")" && +case "$(file --mime-type -b "$trueloc")" in + image/* ) ln -sf "$(readlink -f "$1")" "$bgloc" && notify-send -i "$bgloc" "Changing wallpaper..." ;; + inode/directory ) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && notify-send -i "$bgloc" "Random Wallpaper chosen." ;; + *) notify-send "Error" "Not a valid image." ; exit 1;; +esac + +# If pywal is installed, use it. +if command -v wal >/dev/null 2>&1 ; then + wal -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1 && + pidof dwm >/dev/null && xdotool key super+F12 +# If pywal is removed, return config files to normal. +else + [ -f "$dunstconf.bak" ] && unlink "$dunstconf" && mv "$dunstconf.bak" "$dunstconf" + [ -f "$zathuraconf.bak" ] && unlink "$zathuraconf" && mv "$zathuraconf.bak" "$zathuraconf" +fi + +xwallpaper --zoom "$bgloc" diff --git a/bin/shortcuts b/bin/shortcuts new file mode 100755 index 0000000..8fecea2 --- /dev/null +++ b/bin/shortcuts @@ -0,0 +1,43 @@ +#!/bin/sh + +bmdirs="${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" +bmfiles="${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-files" + +# Output locations. Unactivated progs should go to /dev/null. +shell_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/shell/shortcutrc" +zsh_named_dirs="${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshnameddirrc" +lf_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/lf/shortcutrc" +vim_shortcuts="${XDG_CONFIG_HOME:-$HOME/.config}/nvim/shortcuts.vim" +ranger_shortcuts="/dev/null" +qute_shortcuts="/dev/null" +fish_shortcuts="/dev/null" +vifm_shortcuts="/dev/null" + +# Remove, prepare files +rm -f "$lf_shortcuts" "$ranger_shortcuts" "$qute_shortcuts" "$zsh_named_dirs" "$vim_shortcuts" 2>/dev/null +printf "# vim: filetype=sh\\n" > "$fish_shortcuts" +printf "# vim: filetype=sh\\nalias " > "$shell_shortcuts" +printf "\" vim: filetype=vim\\n" > "$vifm_shortcuts" + +# Format the `directories` file in the correct syntax and sent it to all three configs. +eval "echo \"$(cat "$bmdirs")\"" | \ +awk "!/^\s*#/ && !/^\s*\$/ {gsub(\"\\\s*#.*$\",\"\"); + printf(\"%s=\42cd %s && ls -a\42 \\\\\n\",\$1,\$2) >> \"$shell_shortcuts\" ; + printf(\"hash -d %s=%s \n\",\$1,\$2) >> \"$zsh_named_dirs\" ; + printf(\"abbr %s \42cd %s; and ls -a\42\n\",\$1,\$2) >> \"$fish_shortcuts\" ; + printf(\"map g%s :cd %s\nmap t%s :cd %s\nmap M%s :cd %s:mo\nmap Y%s :cd %s:co \n\",\$1,\$2, \$1, \$2, \$1, \$2, \$1, \$2) >> \"$vifm_shortcuts\" ; + printf(\"config.bind(';%s', \42set downloads.location.directory %s ;; hint links download\42) \n\",\$1,\$2) >> \"$qute_shortcuts\" ; + printf(\"map g%s cd %s\nmap t%s tab_new %s\nmap m%s shell mv -v %%s %s\nmap Y%s shell cp -rv %%s %s \n\",\$1,\$2,\$1,\$2, \$1, \$2, \$1, \$2) >> \"$ranger_shortcuts\" ; + printf(\"map C%s cd \42%s\42 \n\",\$1,\$2) >> \"$lf_shortcuts\" ; + printf(\"cmap ;%s %s\n\",\$1,\$2) >> \"$vim_shortcuts\" }" + +# Format the `files` file in the correct syntax and sent it to both configs. +eval "echo \"$(cat "$bmfiles")\"" | \ +awk "!/^\s*#/ && !/^\s*\$/ {gsub(\"\\\s*#.*$\",\"\"); + printf(\"%s=\42\$EDITOR %s\42 \\\\\n\",\$1,\$2) >> \"$shell_shortcuts\" ; + printf(\"hash -d %s=%s \n\",\$1,\$2) >> \"$zsh_named_dirs\" ; + printf(\"abbr %s \42\$EDITOR %s\42 \n\",\$1,\$2) >> \"$fish_shortcuts\" ; + printf(\"map %s :e %s \n\",\$1,\$2) >> \"$vifm_shortcuts\" ; + printf(\"map %s shell \$EDITOR %s \n\",\$1,\$2) >> \"$ranger_shortcuts\" ; + printf(\"map E%s \$\$EDITOR \42%s\42 \n\",\$1,\$2) >> \"$lf_shortcuts\" ; + printf(\"cmap ;%s %s\n\",\$1,\$2) >> \"$vim_shortcuts\" }" diff --git a/bin/slider b/bin/slider new file mode 100755 index 0000000..674781a --- /dev/null +++ b/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:" o; do case "${o}" in + c) bgc="$OPTARG" ;; + t) fgc="$OPTARG" ;; + f) font="$OPTARG" ;; + i) file="$OPTARG" ;; + a) audio="$OPTARG" ;; + o) outfile="$OPTARG" ;; + d) prepdir="$OPTARG" ;; + r) redo="$OPTARG" ;; + s) ppt="$OPTARG" ;; + e) endtime="$OPTARG" ;; + x) res="$OPTARG" + echo "$res" | grep -qv "^[0-9]\+x[0-9]\+$" && + echo "Resolution must be dimensions separated by a 'x': 1280x720, etc." && + exit 1 ;; + p) echo "Purge old build files in $cache? [y/N]" + read -r confirm + echo "$confirm" | grep -iq "^y$" && rm -rf "$cache" && echo "Done." + exit ;; + v) verbose=True ;; + *) echo "$(basename "$0") usage: + -i input timecode list (required) + -a audio file + -c color of background (use html names, black is default) + -t text color for text slides (white is default) + -s text font size for text slides (150 is default) + -f text font for text slides (sans serif is default) + -o output video file + -e if no audio given, the time in seconds that the last slide will be shown (5 is default) + -x resolution (1920x1080 is default) + -d tmp directory + -r rerun imagemagick commands even if done previously (in case files or background has changed) + -p purge old build files instead of running + -v be verbose" && exit 1 + +esac done + +# Check that the input file looks like it should. +{ head -n 1 "$file" 2>/dev/null | grep -q "^00:00:00 " ;} || { + echo "Give an input file with -i." && + echo "The file should look as this example: + +00:00:00 first_image.jpg +00:00:03 otherdirectory/next_image.jpg +00:00:09 this_image_starts_at_9_seconds.jpg +etc... + +Timecodes and filenames must be separated by Tabs." && + exit 1 + } + +if [ -n "${audio+x}" ]; then + # Check that the audio file looks like an actual audio file. + case "$(file --dereference --brief --mime-type -- "$audio")" in + audio/*) ;; + *) echo "That doesn't look like an audio file."; exit 1 ;; + esac + totseconds="$(date '+%s' -d $(ffmpeg -i "$audio" 2>&1 | awk '/Duration/ {print $2}' | sed s/,//))" + endtime="$((totseconds-seconds))" +fi + +prepdir="${prepdir:-$cache/$file}" +outfile="${outfile:-$file.mp4}" +prepfile="$prepdir/$file.prep" + +[ -n "${verbose+x}" ] && echo "Preparing images... May take a while depending on the number of files." +mkdir -p "$prepdir" + +{ +while read -r x; +do + # Get the time from the first column. + time="${x%% *}" + seconds="$(date '+%s' -d "$time")" + # Duration is not used on the first looped item. + duration="$((seconds - prevseconds))" + + # Get the filename/text content from the rest. + content="${x#* }" + base="$(basename "$content")" + base="${base%.*}.jpg" + + if [ -f "$content" ]; then + # If images have already been made in a previous run, do not recreate + # them unless -r was given. + { [ ! -f "$prepdir/$base" ] || [ -n "${redo+x}" ] ;} && + convert -size "${res:-1920x1080}" canvas:"${bgc:-black}" -gravity center "$content" -resize 1920x1080 -composite "$prepdir/$base" + else + { [ ! -f "$prepdir/$base" ] || [ -n "${redo+x}" ] ;} && + convert -size "${res:-1920x1080}" -background "${bgc:-black}" -fill "${fgc:-white}" -font "${font:-Sans}" -pointsize "${ppt:-150}" -gravity center label:"$content" "$prepdir/$base" + fi + + # If the first line, do not write yet. + [ "$time" = "00:00:00" ] || echo "file '$prevbase' +duration $duration" + + # Keep the information required for the next file. + prevbase="$base" + prevtime="$time" + prevseconds="$(date '+%s' -d "$prevtime")" +done < "$file" +# Do last file which must be given twice as follows +echo "file '$base' +duration ${endtime:-5} +file '$base'" +} > "$prepfile" +if [ -n "${audio+x}" ]; then + ffmpeg -hide_banner -y -f concat -safe 0 -i "$prepfile" -i "$audio" -c:a aac -vsync vfr -c:v libx264 -pix_fmt yuv420p "$outfile" +else + ffmpeg -hide_banner -y -f concat -safe 0 -i "$prepfile" -vsync vfr -c:v libx264 -pix_fmt yuv420p "$outfile" +fi + +# Might also try: +# -vf "fps=${fps:-24},format=yuv420p" "$outfile" +# but has given some problems. diff --git a/bin/sysact b/bin/sysact new file mode 100755 index 0000000..948b44b --- /dev/null +++ b/bin/sysact @@ -0,0 +1,28 @@ +#!/bin/sh +# A dmenu wrapper script for system functions. +case "$(readlink -f /sbin/init)" in + *systemd*) ctl='systemctl' ;; + *) ctl='loginctl' ;; +esac + +lock=" lock" +leave="󰗼 leave dwm" +renew="󱎝 renew dwm" +hibernate="󱣻 hibernate" +reboot="󱄋 reboot" +shutdown="󰈅 shutdown" +sleep="󰒲 sleep" +display="󰍹 display off" + +case "$(printf "$lock\n$leave\n$renew\n$hibernate\n$reboot\n$shutdown\n$sleep\n$display" \ + | dmenu -i -p 'Action: ')" in + $lock) slock ;; + $leave) kill -TERM "$(pgrep -u "$USER" "\bdwm$")" ;; + $renew) kill -HUP "$(pgrep -u "$USER" "\bdwm$")" ;; + $hibernate) slock $ctl hibernate ;; + $sleep) slock $ctl suspend -i ;; + $reboot) $ctl reboot -i ;; + $shutdown) $ctl poweroff -i ;; + $display) xset dpms force off ;; + *) exit 1 ;; +esac diff --git a/bin/tag b/bin/tag new file mode 100755 index 0000000..8462b99 --- /dev/null +++ b/bin/tag @@ -0,0 +1,67 @@ +#!/bin/sh + +err() { echo "Usage: + tag [OPTIONS] file +Options: + -a: artist/author + -t: song/chapter title + -A: album/book title + -n: track/chapter number + -N: total number of tracks/chapters + -d: year of publication + -g: genre + -c: comment +You will be prompted for title, artist, album and track if not given." && exit 1 ;} + +while getopts "a:t:A:n:N:d:g:c:f:" o; do case "${o}" in + a) artist="${OPTARG}" ;; + t) title="${OPTARG}" ;; + A) album="${OPTARG}" ;; + n) track="${OPTARG}" ;; + N) total="${OPTARG}" ;; + d) date="${OPTARG}" ;; + g) genre="${OPTARG}" ;; + c) comment="${OPTARG}" ;; + f) file="${OPTARG}" ;; + *) printf "Invalid option: -%s\\n" "$OPTARG" && err ;; +esac done + +shift $((OPTIND - 1)) + +file="$1" + +[ ! -f "$file" ] && echo "Provide file to tag." && err + +[ -z "$title" ] && echo "Enter a title." && read -r title +[ -z "$artist" ] && echo "Enter an artist." && read -r artist +[ -z "$album" ] && echo "Enter an album." && read -r album +[ -z "$track" ] && echo "Enter a track number." && read -r track + +case "$file" in + *.ogg) echo "Title=$title +Artist=$artist +Album=$album +Track=$track +Total=$total +Date=$date +Genre=$genre +Comment=$comment" | vorbiscomment -w "$file" ;; + *.opus) echo "Title=$title +Artist=$artist +Album=$album +Track=$track +Total=$total +Date=$date +Genre=$genre +Comment=$comment" | opustags -i -S "$file" ;; + *.mp3) eyeD3 -Q --remove-all -a "$artist" -A "$album" -t "$title" -n "$track" -N "$total" -Y "$date" "$file" ;; + *.flac) echo "TITLE=$title +ARTIST=$artist +ALBUM=$album +TRACKNUMBER=$track +TOTALTRACKS=$total +DATE=$date +GENRE=$genre +DESCRIPTION=$comment" | metaflac --remove-all-tags --import-tags-from=- "$file" ;; + *) echo "File type not implemented yet." ;; +esac diff --git a/bin/td-toggle b/bin/td-toggle new file mode 100755 index 0000000..3c20ea1 --- /dev/null +++ b/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-da && notify-send "transmission-daemon disabled." +else + ifinstalled transmission-cli || exit + [ "$(printf "No\\nYes" | dmenu -i -p "Turn on transmission daemon?")" = "Yes" ] && transmission-daemon && notify-send "transmission-daemon enabled." +fi +sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}" diff --git a/bin/texclear b/bin/texclear new file mode 100755 index 0000000..f38f7be --- /dev/null +++ b/bin/texclear @@ -0,0 +1,16 @@ +#!/bin/sh + +# Clears the build files of a LaTeX/XeLaTeX build. +# I have vim run this file whenever I exit a .tex file. + +case "$1" in + *.tex) + file=$(readlink -f "$1") + dir=$(dirname "$file") + base="${file%.*}" + find "$dir" -maxdepth 1 -type f -regextype gnu-awk -regex "^$base\\.(4tc|xref|tmp|pyc|pyg|pyo|fls|vrb|fdb_latexmk|bak|swp|aux|log|synctex\\(busy\\)|lof|lot|maf|idx|mtc|mtc0|nav|out|snm|toc|bcf|run\\.xml|synctex\\.gz|blg|bbl)" -delete + rm -rdf "$dir/_minted-$(basename -- $base)" + ;; + *) printf "Give .tex file as argument.\\n" ;; +esac + diff --git a/bin/torwrap b/bin/torwrap new file mode 100755 index 0000000..8b20ad4 --- /dev/null +++ b/bin/torwrap @@ -0,0 +1,7 @@ +#!/bin/sh + +ifinstalled tremc transmission-cli || exit + +! pidof transmission-daemon >/dev/null && transmission-daemon && notify-send "Starting torrent daemon..." + +$TERMINAL -e tremc; pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}" diff --git a/bin/transadd b/bin/transadd new file mode 100755 index 0000000..a598fad --- /dev/null +++ b/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/bin/tutorialvids b/bin/tutorialvids new file mode 100755 index 0000000..6d4914b --- /dev/null +++ b/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 +pacman (installing/managing programs) https://videos.lukesmith.xyz/videos/watch/8e7cadb9-0fed-47ce-a2a8-6635fa48614b +status bar https://videos.lukesmith.xyz/videos/watch/a4d5326b-0aac-496e-bfc3-5acd5cee89f0 +sxiv (image viewer) https://videos.lukesmith.xyz/videos/watch/ad4c8d85-90c3-4f3d-a1f3-89129e64a3c2 +st (terminal) https://videos.lukesmith.xyz/videos/watch/efddd39d-bac5-4599-b572-177beb4ce6e8 +i3 (old window manager) https://videos.lukesmith.xyz/videos/watch/b861525c-7ada-40ee-a2bb-b5e1ffe0f48b +neomutt (email) https://videos.lukesmith.xyz/videos/watch/83122e83-52d9-4278-ae1a-7d1beeb50c8e +ncmpcpp (music player) https://videos.lukesmith.xyz/videos/watch/b5ac6f0d-a220-4433-88e3-e98fc791dc0a +newsboat (RSS reader) https://videos.lukesmith.xyz/videos/watch/bd2c3fff-40fa-47ea-aa98-5b1ec0c903b6 +lf (file manager) https://videos.lukesmith.xyz/w/rKeHsF5ZHDNDbR1buUKB1c +zathura (pdf viewer) https://videos.lukesmith.xyz/videos/watch/c780f75a-11f6-48a9-a191-d079ebc36ea4 +gpg keys https://videos.lukesmith.xyz/videos/watch/040f5530-4830-4583-9ddc-2080b421531b +calcurse (calendar) https://videos.lukesmith.xyz/videos/watch/4b937e8b-7654-46e3-8d01-79392ec5b3d1 +urlview https://videos.lukesmith.xyz/videos/watch/31a4918f-633b-4bd6-b08e-956ac75d0324 +colorschemes with pywal https://videos.lukesmith.xyz/videos/watch/1b476003-61b2-4609-ac4b-820c3d128643 +vi mode in shell https://videos.lukesmith.xyz/videos/watch/228aa50c-836f-456f-9f0d-a45157fe4313 +pass (password manager) https://videos.lukesmith.xyz/videos/watch/432fc942-5e28-4682-9beb-f5cb237a1dd6 +" +echo "$vidlist" | grep -P "^$(echo "$vidlist" | grep "https:" | sed 's/\t.*//g' | dmenu -i -p "Learn about what? (ESC to cancel)" -l 20 | awk '{print $1}')\s" | sed 's/.*\t//' | xargs -r mpv diff --git a/bin/vpn b/bin/vpn new file mode 100755 index 0000000..ee0da07 --- /dev/null +++ b/bin/vpn @@ -0,0 +1,3 @@ +#!/bin/bash +cloudflared access tcp --hostname openvpn.wessel.gg --url 127.0.0.1:9393 & +sudo openvpn /mnt/Users/wesse/Documents/laptop-helix.ovpn &