commit 142776f70131dbf7ee03d063e214512025198a23 parent e7392bc2aa6078bd41ad1259d420b70bc3590e5b Author: C. Beau Hilton <cbeauhilton@gmail.com> Date: Wed, 13 Jan 2021 14:46:13 -0600 site update Diffstat:
80 files changed, 1665 insertions(+), 0 deletions(-)
diff --git a/home/.Xauthority b/home/.Xauthority Binary files differ. diff --git a/home/.fehbg b/home/.fehbg @@ -0,0 +1,2 @@ +#!/bin/sh +feh --no-fehbg --bg-fill '/home/beau/.config/wall.png' diff --git a/home/.profile b/home/.profile @@ -0,0 +1,68 @@ +#!/usr/bin/env sh + +export EDITOR="nvim" +export TERMINAL="kitty" +export FILE="nnn" +export READER="zathura" +export BROWSER="chromium" + +export NNN_FIFO='/tmp/nnn.fifo' +export NNN_PLUG='p:preview-tui' +export SPLIT='v' + +# Adds ruby to path +PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin" + +# Adds `~/.local/bin/` and all subdirectories to $PATH +export PATH="$PATH:$(du "$HOME/.local/bin/" | cut -f2 | tr '\n' ':' | sed 's/:*$//')" + +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_CACHE_HOME="$HOME/.cache" +export VIMWIKI_HOME="$HOME/repos/vimwiki/index.md" + +export CONDARC="${XDG_CONFIG_HOME:-$HOME/.config}/conda/.condarc" +export IPYTHONDIR="${XDG_CONFIG_HOME:-$HOME/.config}/jupyter" +export JUPYTER_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/jupyter" +export R_ENVIRON_USER="${XDG_CONFIG_HOME:-$HOME/.config}/R/Renviron" + +export CARGO_HOME="$XDG_DATA_HOME"/cargo +export GEM_HOME="$XDG_DATA_HOME"/gem +export GEM_SPEC_CACHE="$XDG_CACHE_HOME"/gem +export NPM_CONFIG_USERCONFIG=$XDG_CONFIG_HOME/npm/npmrc + +export LESSHISTFILE="-" +export SUDO_ASKPASS="$HOME/.local/bin/tools/dmenupass" +export NOTMUCH_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/notmuch-config" +export GTK2_RC_FILES="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-2.0/gtkrc-2.0" +export ZDOTDIR="${XDG_CONFIG_HOME:-$HOME/.config}/zsh" +export WGETRC="${XDG_CONFIG_HOME:-$HOME/.config}/wget/wgetrc" +export INPUTRC="${XDG_CONFIG_HOME:-$HOME/.config}/inputrc" +export PASSWORD_STORE_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/password-store" +export XINITRC="$XDG_CONFIG_HOME"/X11/xinitrc +export MAILCAPS="$XDG_CONFIG_HOME"/tuir/mailcap + +export GPG_TTY=$(tty) +export GPG_AGENT_INFO="" + +# less/man colors +export LESS=-R +export LESS_TERMCAP_mb="$(printf '%b' '[1;31m')"; a="${a%_}" +export LESS_TERMCAP_md="$(printf '%b' '[1;36m')"; a="${a%_}" +export LESS_TERMCAP_me="$(printf '%b' '[0m')"; a="${a%_}" +export LESS_TERMCAP_so="$(printf '%b' '[01;44;33m')"; a="${a%_}" +export LESS_TERMCAP_se="$(printf '%b' '[0m')"; a="${a%_}" +export LESS_TERMCAP_us="$(printf '%b' '[1;32m')"; a="${a%_}" +export LESS_TERMCAP_ue="$(printf '%b' '[0m')"; a="${a%_}" + +mpd >/dev/null 2>&1 & + +[ ! -f ~/.config/shortcutrc ] && shortcuts >/dev/null 2>&1 + +# Start graphical server on tty1 if not already running. +[ "$(tty)" = "/dev/tty1" ] && ! ps -e | grep -qw Xorg && exec startx "$XDG_CONFIG_HOME/X11/xinitrc" -- + +# Switch escape and caps if tty: +sudo -n loadkeys ~/.local/bin/ttymaps.kmap 2>/dev/null + +gpg-connect-agent updatestartuptty /bye >/dev/null diff --git a/home/.zshrc b/home/.zshrc @@ -0,0 +1,16 @@ + +# >>> conda initialize >>> +# !! Contents within this block are managed by 'conda init' !! +__conda_setup="$('/home/beau/.local/bin/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)" +if [ $? -eq 0 ]; then + eval "$__conda_setup" +else + if [ -f "/home/beau/.local/bin/miniconda3/etc/profile.d/conda.sh" ]; then + . "/home/beau/.local/bin/miniconda3/etc/profile.d/conda.sh" + else + export PATH="/home/beau/.local/bin/miniconda3/bin:$PATH" + fi +fi +unset __conda_setup +# <<< conda initialize <<< + diff --git a/scripts/bin/cron/IMPORTANT_NOTE.md b/scripts/bin/cron/IMPORTANT_NOTE.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/1000/bus; export DISPLAY=:0; . $HOME/.profile; then_command_goes_here +``` + +This ensures that notifications will display, xdotool commands will function and environmental varialbes will work as well. diff --git a/scripts/bin/cron/checkup b/scripts/bin/cron/checkup @@ -0,0 +1,15 @@ +#!/usr/bin/env sh +# Syncs repositories and downloads updates, meant to be run as a cronjob. + +ping -q -c 1 1.1.1.1 > /dev/null || exit + +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." + +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/scripts/bin/cron/cronbat b/scripts/bin/cron/cronbat @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +# Notify me with notify-send if my battery is below 25%. +# You can set this to run via cron. + +[ "$(cat /sys/class/power_supply/BAT0/status)" = "Charging" ] && exit +[ "$(cat /sys/class/power_supply/BAT0/capacity)" -lt 25 ] && +export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1001/bus && +notify-send -u critical "Battery critically low." diff --git a/scripts/bin/cron/crontog b/scripts/bin/cron/crontog @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +# Toggles all cronjobs off/on. +# Stores disabled crontabs in ~/.consaved until restored. + +([ -f ~/.config/cronsaved ] && crontab - < ~/.config/cronsaved && rm ~/.config/cronsaved && notify-send "π Cronjobs re-enabled.") || ( crontab -l > ~/.config/cronsaved && crontab -r && notify-send "π Cronjobs saved and disabled.") diff --git a/scripts/bin/cron/newsup b/scripts/bin/cron/newsup @@ -0,0 +1,9 @@ +#!/usr/bin/env 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. + +ping -q -c 1 1.1.1.1 > /dev/null || exit + +pgrep -x newsboat >/dev/null && /usr/bin/xdotool key --window "$(/usr/bin/xdotool search --name newsboat)" R && exit + +/usr/bin/newsboat -x reload diff --git a/scripts/bin/i3cmds/cabl b/scripts/bin/i3cmds/cabl @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Dependencies are xclip and xorg-xprop. +# qrencode required for qrcode generation. +# groff/zathura required for man pages. +prim="$(xclip -o)"; [ -z "$prim" ] && exit + +PID=$(xprop -id "$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')" | grep -m 1 PID | cut -d " " -f 3) +PID=$(echo "$(pstree -lpA "$PID" | tail -n 1)" | awk -F'---' '{print $NF}' | sed -re 's/[^0-9]//g') +cd "$(readlink /proc/"$PID"/cwd)" +[ -f "$prim" ] && xdg-open "$prim" && exit +[ -d "$prim" ] && "$TERMINAL" "$prim" && exit + +websearch() { "$BROWSER" "https://duckduckgo.com/?q=$@" ;} +wikipedia() { "$BROWSER" "https://en.wikipedia.org/wiki/$@" ;} +wiktionary() { "$BROWSER" "https://en.wiktionary.org/wiki/$@" ;} +maps() { "$BROWSER" "https://www.openstreetmap.org/search?query=$@" ;} +ebay() { "$BROWSER" "https://www.ebay.com/sch/$@" ;} + +echo "$prim" | grep "^.*\.[A-Za-z]\+.*" >/dev/null && gotourl() { "$BROWSER" "$@" ;} +echo "$prim" | grep "^.*@.*\.[A-Za-z]\+$" >/dev/null && email() { xdg-email "$@" ;} +command -v qrencode >/dev/null && qrcode() { qrencode "$@" -s 10 -o /tmp/qr.png && xdg-open /tmp/qr.png ;} +man -k "^$prim$" >/dev/null && manual() { man -Tpdf "$prim" | zathura - ;} + +func="$(declare -F | awk '{print $3}' | dmenu -p "Plumb \"$(echo "$prim" | cut -c -30)\" to?" -i -l 15)" + +[ -z "$func" ] || "$func" "$prim" diff --git a/scripts/bin/i3cmds/camtoggle b/scripts/bin/i3cmds/camtoggle @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +pkill -f /dev/video || mpv --no-osc --no-input-default-bindings --input-conf=/dev/null --geometry=-0-0 --autofit=30% --title="mpvfloat" /dev/video0 diff --git a/scripts/bin/i3cmds/ddspawn b/scripts/bin/i3cmds/ddspawn @@ -0,0 +1,19 @@ +#!/usr/bin/env sh + +# Toggle floating dropdown terminal in i3, or start if non-existing. +# $1 is the script run in the terminal. +# All other args are terminal settings. +# Terminal names are in dropdown_* to allow easily setting i3 settings. + +[ -z "$1" ] && exit + +script=$1 +shift +if xwininfo -tree -root | grep "(\"dropdown_$script\" "; +then + echo "Window detected." + i3 "[instance=\"dropdown_$script\"] scratchpad show; [instance=\"dropdown_$script\"] move position center" +else + echo "Window not detected... spawning." + i3 "exec --no-startup-id $TERMINAL -n dropdown_$script $@ -e $script" +fi diff --git a/scripts/bin/i3cmds/displayselect b/scripts/bin/i3cmds/displayselect @@ -0,0 +1,73 @@ +#!/usr/bin/env 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. +# I plan on adding a routine from multi-monitor setups later. + +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 + 1) xrandr $(echo "$allposs" | grep -v "$screens" | awk '{print "--output", $1, "--off"}' | tr '\n' ' ') ;; + 2) twoscreen ;; + *) morescreen ;; + esac ;} + +# Get all possible displays +allposs=$(xrandr -q | grep "connected") + +# Get all connected screens. +screens=$(echo "$allposs" | grep " connected" | awk '{print $1}') + +# 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 ;; + *) xrandr --output "$chosen" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "$chosen" | awk '{print "--output", $1, "--off"}' | tr '\n' ' ') ;; +esac + +setbg # Fix background if screen size/arangement has changed. +remaps # Re-remap keys if keyboard added (for laptop bases) +pgrep -x dunst >/dev/null && killall dunst && setsid dunst & # Restart dunst to ensure proper location on screen diff --git a/scripts/bin/i3cmds/dmenumount b/scripts/bin/i3cmds/dmenumount @@ -0,0 +1,59 @@ +#!/usr/bin/env sh +# Gives a dmenu prompt to mount unmounted drives. +# 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 + mp="$(find $1 2>/dev/null | dmenu -i -p "Type in mount point.")" + [ "$mp" = "" ] && exit 1 + 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 + } + +mountusb() { \ + chosen="$(echo "$usbdrives" | dmenu -i -p "Mount which drive?" | 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 '$2=="part"&&$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not \\( -path *%s -prune \\) \\ \n",$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;; + *) 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?" | cut -d : -f 1) + getmount "$HOME -maxdepth 3 -type d" + simple-mtpfs --device "$chosen" "$mp" + notify-send "π€ Android Mounting" "Android device mounted to $mp." + } + +asktype() { \ + case $(printf "USB\\nAndroid" | dmenu -i -p "Mount a USB drive or Android device?") in + USB) mountusb ;; + Android) mountandroid ;; + esac + } + +anddrives=$(simple-mtpfs -l 2>/dev/null) +usbdrives="$(lsblk -rpo "name,type,size,mountpoint" | awk '$2=="part"&&$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/scripts/bin/i3cmds/dmenurecord b/scripts/bin/i3cmds/dmenurecord @@ -0,0 +1,105 @@ +#!/usr/bin/env sh + +# Usage: +# `record`: Ask for recording type via dmenu +# `record screencast`: Record both audio and screen +# `record video`: Record only screen +# `record audio`: Record only audio +# `record kill`: Kill existing recording +# +# If there is already a running instance, user will be prompted to end it. + +updateicon() { \ + echo "$1" > /tmp/recordingicon + pkill -RTMIN+9 i3blocks + } + +killrecording() { + recpid="$(cat /tmp/recordingpid)" + # kill with SIGTERM, allowing finishing touches. + kill -15 "$recpid" + rm -f /tmp/recordingpid + updateicon "" + pkill -RTMIN+9 i3blocks + # even after SIGTERM, ffmpeg may still run, so SIGKILL it. + sleep 3 + kill -9 "$recpid" + exit + } + +screencast() { \ + ffmpeg -y \ + -f x11grab \ + -framerate 60 \ + -s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ + -i $DISPLAY \ + -f alsa -i default \ + -r 30 \ + -c:v libx264rgb -crf 0 -preset ultrafast -c:a flac \ + "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid + updateicon "βΊοΈποΈ" + } + +video() { ffmpeg \ + -f x11grab \ + -s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ + -i $DISPLAY \ + -c:v libx264 -qp 0 -r 30 \ + "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid + updateicon "βΊοΈ" + } + +webcamhidef() { ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 1920x1080 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid + updateicon "π₯" + } + +webcam() { ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 640x480 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid + updateicon "π₯" + } + + +audio() { \ + ffmpeg \ + -f alsa -i default \ + -c:a flac \ + "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" & + echo $! > /tmp/recordingpid + updateicon "ποΈ" + } + +askrecording() { \ + choice=$(printf "screencast\\nvideo\\naudio\\nwebcam\\nwebcam (hi-def)" | dmenu -i -p "Select recording style:") + case "$choice" in + screencast) screencast;; + audio) audio;; + video) video;; + webcam) webcam;; + "webcam (hi-def)") webcamhidef;; + esac + } + +asktoend() { \ + response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") && + [ "$response" = "Yes" ] && killrecording + } + + +case "$1" in + screencast) screencast;; + audio) audio;; + video) video;; + kill) killrecording;; + *) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording;; +esac diff --git a/scripts/bin/i3cmds/dmenuumount b/scripts/bin/i3cmds/dmenuumount @@ -0,0 +1,41 @@ +#!/usr/bin/env 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?" | 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?") + [ -z "$chosen" ] && exit + sudo -A umount -l "$chosen" && notify-send "π€ Android unmounting" "$chosen unmounted." + } + +asktype() { \ + case "$(printf "USB\\nAndroid" | dmenu -i -p "Unmount a USB drive or Android device?")" in + USB) unmountusb ;; + Android) unmountandroid ;; + esac + } + +drives=$(lsblk -nrpo "name,type,size,mountpoint" | awk '$2=="part"&&$4!~/\/boot|\/home$|SWAP/&&length($4)>1{printf "%s (%s)\n",$4,$3}') + +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/scripts/bin/i3cmds/dmenuunicode b/scripts/bin/i3cmds/dmenuunicode @@ -0,0 +1,22 @@ +#!/usr/bin/env sh +# Give dmenu list of all unicode characters to copy. +# Shows the selected character in dunst if running. + +# Must have xclip installed to even show menu. +xclip -h >/dev/null || exit + +if [ -e ~/.config/fontawesome ]; then + chosen=$(grep -v "#" -h ~/.config/emoji ~/.config/fontawesome | dmenu -i -l 20 -fn Monospace-18) +else + chosen=$(grep -v "#" ~/.config/emoji | dmenu -i -l 20 -fn Monospace-18) +fi + +[ "$chosen" != "" ] || exit + +c=$(echo "$chosen" | sed "s/ .*//") +echo "$c" | tr -d '\n' | xclip -selection clipboard +notify-send "'$c' copied to clipboard." & + +s=$(echo "$chosen" | sed "s/.*; //" | awk '{print $1}') +echo "$s" | tr -d '\n' | xclip +notify-send "'$s' copied to primary." & diff --git a/scripts/bin/i3cmds/dropdowncalc b/scripts/bin/i3cmds/dropdowncalc @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +ifinstalled bc && echo "Welcome to the Calculator." && bc -lq diff --git a/scripts/bin/i3cmds/ducksearch b/scripts/bin/i3cmds/ducksearch @@ -0,0 +1,20 @@ +#!/usr/bin/env sh +# Gives a dmenu prompt to search DuckDuckGo. +# Without input, will open DuckDuckGo.com. +# URLs will be directly handed to the browser. +# Anything else, it search it. +browser=${BROWSER:-firefox} + +pgrep -x dmenu && exit + +choice=$(echo "π¦" | dmenu -i -p "Search DuckDuckGo:") || exit 1 + +if [ "$choice" = "π¦" ]; then + $browser "https://duckduckgo.com" +else + if echo "$choice" | grep "^(http:\/\/|https:\/\/)?[a-zA-Z0-9]+\.[a-zA-Z]+(/)?.*$"; then + $browser "$choice" + else + $browser "https://duckduckgo.com/?q=$choice&t=ffab&atb=v1-1" + fi +fi diff --git a/scripts/bin/i3cmds/hover b/scripts/bin/i3cmds/hover @@ -0,0 +1,14 @@ +#!/usr/bin/env sh +[ -z "$1" ] && exit # If $1 is left, hovers in the bottom left, if right, the bottom right +current=$(xdotool getwindowfocus) +newwidth=$(($(xdotool getdisplaygeometry | awk '{print $2}') / 3)) +newheight=$(($(xdotool getdisplaygeometry | awk '{print $1}') / 3)) +xdotool windowsize "$current" $newheight $newwidth +newsize=$(xdotool getwindowgeometry "$current" | grep Geometry | sed -e 's/x/ /g' | awk '{print $3}') +newwidth=$(xdotool getwindowgeometry "$current" | grep Geometry | grep -o " [0-9]*") + +case "$1" in + left) horizontal=0; vertical=$(($(xdotool getdisplaygeometry | awk '{print $2}') - newsize)) ;; + right) horizontal=$(($(xdotool getdisplaygeometry | awk '{print $1}') - newwidth)) ; vertical=$(($(xdotool getdisplaygeometry | awk '{print $2}') - newsize)) ;; +esac +xdotool windowmove "$current" $horizontal $vertical diff --git a/scripts/bin/i3cmds/i3resize b/scripts/bin/i3cmds/i3resize @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +# This script was made by `goferito` on Github. +# Some cleanup by Luke. + +[ -z "$1" ] && echo "No direction provided" && exit 1 +distanceStr="2 px or 2 ppt" + +moveChoice() { + i3-msg resize "$1" "$2" "$distanceStr" | grep '"success":true' || \ + i3-msg resize "$3" "$4" "$distanceStr" +} + +case $1 in + up) + moveChoice grow up shrink down + ;; + down) + moveChoice shrink up grow down + ;; + left) + moveChoice shrink right grow left + ;; + right) + moveChoice grow right shrink left + ;; +esac + diff --git a/scripts/bin/i3cmds/killrecording b/scripts/bin/i3cmds/killrecording @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +kill -9 "$(cat ~/.recordingpid)" + +# Update i3bar. +echo "" > ~/.recordingicon +pkill -RTMIN+9 i3blocks diff --git a/scripts/bin/i3cmds/maimpick b/scripts/bin/i3cmds/maimpick @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +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/scripts/bin/i3cmds/prompt b/scripts/bin/i3cmds/prompt @@ -0,0 +1,7 @@ +#!/usr/bin/env 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/scripts/bin/i3cmds/samedir b/scripts/bin/i3cmds/samedir @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +PID=$(xprop -id "$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')" | grep -m 1 PID | cut -d " " -f 3) +PID=$(echo "$(pstree -lpA "$PID" | tail -n 1)" | awk -F'---' '{print $NF}' | sed -re 's/[^0-9]//g') +cd "$(readlink /proc/"$PID"/cwd)" +"$TERMINAL" diff --git a/scripts/bin/i3cmds/showclip b/scripts/bin/i3cmds/showclip @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +# Display contents of selection via dunst if running. +# Separate script for i3. + +clip=$(xclip -o -selection clipboard) +prim=$(xclip -o -selection primary) + +[ -n "$clip" ] && notify-send "Clipboard:" "$clip" +[ -n "$prim" ] && notify-send "Primary:" "$prim" diff --git a/scripts/bin/i3cmds/td-toggle b/scripts/bin/i3cmds/td-toggle @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +# If transmission-daemon is running, will ask to kill, else will ask to start. +if pgrep -x transmission-da >/dev/null ; +then + [ "$(printf "No\\nYes" | dmenu -i -p "Kill transmission-daemon?")" = "Yes" ] && killall transmission-da && notify-send "transmission-daemon killed." +else + ifinstalled transmission-cli || exit + [ "$(printf "No\\nYes" | dmenu -i -p "Start transmission daemon?")" = "Yes" ] && transmission-daemon && notify-send "tranmission-daemon started." +fi +sleep 3 && pkill -RTMIN+7 i3blocks diff --git a/scripts/bin/i3cmds/tmuxdd b/scripts/bin/i3cmds/tmuxdd @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +# This is the script that i3 runs to either start tmux in +# the dropdown terminal or log into a previous session. +tmux a || tmux diff --git a/scripts/bin/i3cmds/toggletouchpad b/scripts/bin/i3cmds/toggletouchpad @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +# Toggle touchpad. Requires xf86-input-synaptics. +(synclient | grep "TouchpadOff.*1" && synclient TouchpadOff=0)>/dev/null && echo "TouchPad reactivated." && exit +synclient TouchpadOff=1 && echo "TouchPad deactivated." diff --git a/scripts/bin/i3cmds/torwrap b/scripts/bin/i3cmds/torwrap @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +ifinstalled transmission-remote-cli transmission-cli || exit + +! pgrep -x transmission-da >/dev/null && transmission-daemon && notify-send "Starting torrent daemon..." && sleep 3 && pkill -RTMIN+7 i3blocks + +$TERMINAL -e transmission-remote-cli diff --git a/scripts/bin/i3cmds/tutorialvids b/scripts/bin/i3cmds/tutorialvids @@ -0,0 +1,18 @@ +#!/usr/bin/env sh +vidlist=" +status bar https://www.youtube.com/watch?v=gKumet6b-WY +sxiv (image viewer) https://www.youtube.com/watch?v=GYW9i_u5PYs +st (terminal) https://www.youtube.com/watch?v=9H75enWM22k +i3 (window manager) https://www.youtube.com/watch?v=GKviflL9XeI +pacman (installing/managing programs) https://www.youtube.com/watch?v=-dEuXTMzRKs +mutt (email) https://www.youtube.com/watch?v=2U3vRbF7v5A +ncmpcpp (music player) https://www.youtube.com/watch?v=sZIEdI9TS2U +newsboat (RSS reader) https://www.youtube.com/watch?v=dUFCRqs822w +zathura (pdf viewer) https://www.youtube.com/watch?v=V_Iz4zdyRM4 +gpg keys https://www.youtube.com/watch?v=DMGIlj7u7Eo +calcurse (calendar) https://www.youtube.com/watch?v=hvc-pHjbhdE +urlview https://www.youtube.com/watch?v=IgzpAjFgbCw +colorschemes with pywal https://www.youtube.com/watch?v=Es79N_9BblE +vi mode in shell https://www.youtube.com/watch?v=GqoJQft5R2E +" +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/scripts/bin/i3cmds/winresize b/scripts/bin/i3cmds/winresize @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +echo "π" | dmenu -p "Give width and height:" | xargs xdotool windowsize "$(xdotool getwindowfocus)" diff --git a/scripts/bin/i3cmds/xcqr b/scripts/bin/i3cmds/xcqr @@ -0,0 +1,9 @@ +#!/bin/sh +# Credit to Maddison Hellstrom (@b0o on Github) +qrencode -o - -s 1 \ + "$(xclip -out -selection clipboard)" | + feh --zoom max \ + -F \ + --force-aliasing \ + --image-bg white \ + - diff --git a/scripts/bin/statusbar/battery b/scripts/bin/statusbar/battery @@ -0,0 +1,27 @@ +#!/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!" ;; +esac + +# Loop through all attached batteries. +for battery in /sys/class/power_supply/BAT? +do + # Get its remaining capacity and charge status. + capacity=$(cat "$battery"/capacity) || break + status=$(sed "s/Discharging/π/;s/Not charging/π/;s/Charging/π/;s/Unknown/β»οΈ/;s/Full/β‘/" "$battery"/status) + + # If it is discharging and 25% or less, we will add a β as a warning. + [ "$capacity" -le 25 ] && [ "$status" = "π" ] && warn="β" + + printf "%s%s%s%% " "$status" "$warn" "$capacity" + unset warn +done | sed s/\ $/\\n/ diff --git a/scripts/bin/statusbar/clock b/scripts/bin/statusbar/clock @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +date '+%Y %b %d (%a) %I:%M%p' + +case $BLOCK_BUTTON in + 1) pgrep -x dunst >/dev/null && notify-send "This Month" "$(cal --color=always | sed "s/..7m/<b><span color=\"red\">/;s/..27m/<\/span><\/b>/")" && notify-send "Appointments" "$(calcurse -D ~/.config/calcurse -d3)" ;; + 2) $TERMINAL -e calcurse -D ~/.config/calcurse ;; + 3) pgrep -x dunst >/dev/null && 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" ;; +esac diff --git a/scripts/bin/statusbar/cpu b/scripts/bin/statusbar/cpu @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +case $BLOCK_BUTTON in + 1) notify-send "π₯ CPU hogs" "$(ps axch -o cmd:15,%cpu --sort=-%cpu | head)" ;; + 3) notify-send "π₯ CPU module " "\- Shows CPU temperature. +- Click to show intensive processes. +- % is of single core." ;; +esac + +sensors | awk '/Core 0/ {print $3}' diff --git a/scripts/bin/statusbar/disk b/scripts/bin/statusbar/disk @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +# Status bar module for disk space +# $1 should be drive mountpoint +# $2 is optional icon, otherwise mountpoint will displayed + +[ -z "$1" ] && exit + +icon="$2" +[ -z "$2" ] && icon="$1" + +case $BLOCK_BUTTON in + 1) pgrep -x dunst >/dev/null && notify-send "π½ Disk space" "$(df -h --output=target,used,size)" ;; + 3) pgrep -x dunst >/dev/null && notify-send "π½ Disk module" "\- Shows used hard drive space. +- Click to show all disk info." ;; +esac + +printf "%s: %s\n" "$icon" "$(df -h "$1" | awk ' /[0-9]/ {print $3 "/" $2}')" diff --git a/scripts/bin/statusbar/help b/scripts/bin/statusbar/help @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +case $BLOCK_BUTTON in + 1) groff -mom ~/.local/share/larbs/readme.mom -Tpdf | zathura - ;; + 2) i3 restart ;; + 3) pgrep -x dunst >/dev/null && notify-send "β Help module" "\- Left click to open LARBS guide. +- Middle click to refresh i3.";; +esac; echo "β" diff --git a/scripts/bin/statusbar/internet b/scripts/bin/statusbar/internet @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +case $BLOCK_BUTTON in + 1) $TERMINAL -e nmtui ;; + 3) pgrep -x dunst >/dev/null && notify-send "π Internet module" "\- Click to connect +π‘: no wifi connection +πΆ: wifi connection with quality +β: no ethernet +π: ethernet working +" ;; +esac + +[ "$(cat /sys/class/net/w*/operstate)" = 'down' ] && wifiicon="π‘" + +[ ! -n "${wifiicon+var}" ] && wifiicon=$(grep "^\s*w" /proc/net/wireless | awk '{ print "πΆ", int($3 * 100 / 70) "%" }') + +printf "%s %s\n" "$wifiicon" "$(cat /sys/class/net/e*/operstate | sed "s/down/β/;s/up/π/")" diff --git a/scripts/bin/statusbar/iplocate b/scripts/bin/statusbar/iplocate @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +# Gets your public ip address checks which country you are in and +# displays that information in the statusbar +# +# https://www.maketecheasier.com/ip-address-geolocation-lookups-linux/ +ifinstalled "geoiplookup" || exit +addr="$(curl ifconfig.me 2>/dev/null)" || exit +grep "flag: " ~/.config/emoji | grep "$(geoiplookup $addr | sed 's/.*, //')" | sed "s/flag: //;s/;.*//" diff --git a/scripts/bin/statusbar/mailbox b/scripts/bin/statusbar/mailbox @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +# i3blocks mail module. +# Displays number of unread mail and an loading icon if updating. +# When clicked, brings up `neomutt`. + +case $BLOCK_BUTTON in + 1) "$TERMINAL" -e neomutt ;; + 2) setsid mailsync >/dev/null & ;; + 3) pgrep -x dunst >/dev/null && notify-send "π¬ Mail module" "\- Shows unread mail +- Shows π if syncing mail +- Left click opens neomutt +- Middle click syncs mail" ;; +esac + +echo "$(du -a ~/.local/share/mail/*/INBOX/new/* 2>/dev/null | sed -n '$=')$(cat /tmp/imapsyncicon_$USER 2>/dev/null)" diff --git a/scripts/bin/statusbar/memory b/scripts/bin/statusbar/memory @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +case $BLOCK_BUTTON in + 1) notify-send "π§ Memory hogs" "$(ps axch -o cmd:15,%mem --sort=-%mem | head)" ;; + 3) notify-send "π§ Memory module" "\- Shows Memory Used/Total. +- Click to show memory hogs." ;; +esac + +free -h | awk '/^Mem:/ {print $3 "/" $2}' diff --git a/scripts/bin/statusbar/mpdupdate b/scripts/bin/statusbar/mpdupdate @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +# Whenever the mpd state changes, update the mpd module. + +while : ; do + mpc idle >/dev/null && kill -45 "$(pidof "${STATUSBAR: -dwmblocks}")" }} break +done diff --git a/scripts/bin/statusbar/music b/scripts/bin/statusbar/music @@ -0,0 +1,18 @@ +#!/bin/sh + +filter() { mpc | head -n 1 | paste -sd ' ';} + +pidof -x mpdupdate >/dev/null 2>&1 || mpdupdate >/dev/null 2>&1 & + +case $BLOCK_BUTTON in + 1) mpc status | filter && setsid "$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. +- Italic 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 + *) mpc status | filter ;; +esac; exit diff --git a/scripts/bin/statusbar/news b/scripts/bin/statusbar/news @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +# i3blocks newsboat module. +# 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 newsup >/dev/null & exit ;; + 3) pgrep -x dunst >/dev/null && 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." ;; +esac + + cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ print $1}' | sed s/^0$//g)$(cat ~/.config/newsboat/.update 2>/dev/null)" diff --git a/scripts/bin/statusbar/pacpackages b/scripts/bin/statusbar/pacpackages @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +# module for pacman upgrades. +# 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. + +case $BLOCK_BUTTON in + 1) setsid -f $TERMINAL -e popupgrade ;; + 2) notify-send "$(/usr/bin/pacman -Qu)" ;; + 3) pgrep -x dunst >/dev/null && notify-send "Upgrade module" "π¦: number of upgradable packages +- Left click to upgrade packages +- Middle click to show upgradable packages" ;; +esac + +pacman -Qu | grep -Fcv "[ignored]" | sed "s/^/π¦/;s/^π¦0$//g" diff --git a/scripts/bin/statusbar/popupgrade b/scripts/bin/statusbar/popupgrade @@ -0,0 +1,9 @@ +#!/usr/bin/env 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/scripts/bin/statusbar/torrent b/scripts/bin/statusbar/torrent @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +transmission-remote -l | grep % | + sed " # This first sed command is to ensure a desirable order with sort + s/.*Stopped.*/A/g; + s/.*Seeding.*/Z/g; + s/.*100%.*/N/g; + s/.*Idle.*/B/g; + s/.*Uploading.*/L/g; + s/.*%.*/M/g" | + sort -h | uniq -c | sed " # Now we replace the standin letters with icons. + s/A/π/g; + s/B/βοΈ/g; + s/L/πΌ/g; + s/M/π½/g; + s/N/β /g; + s/Z/π±/g" | awk '{print $2, $1}' | sed -e "s/ $//g" + +case $BLOCK_BUTTON in + 1) $TERMINAL -e transmission-remote-cli ;; + 3) pgrep -x dunst >/dev/null && notify-send "Torrent module" "π: paused +β³: idle (seeds needed) +πΌ: uploading (unfinished) +π½: downloading +β : done +π±: done and seeding" ;; +esac + diff --git a/scripts/bin/statusbar/volume b/scripts/bin/statusbar/volume @@ -0,0 +1,28 @@ +#!/bin/sh + +# Prints the current volume or π if muted. + +case $BLOCK_BUTTON in + 1) setsid -f "$TERMINAL" -e pulsemixer ;; + 2) pamixer -t ;; + 4) pamixer --allow-boost -i 1 ;; + 5) pamixer --allow-boost -d 1 ;; + 3) notify-send "π’ Volume module" "\- Shows volume π, π if muted. +- Middle click to mute. +- Scroll to change." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +[ $(pamixer --get-mute) = true ] && echo π && exit + +vol="$(pamixer --get-volume)" + +if [ "$vol" -gt "70" ]; then + icon="π" +elif [ "$vol" -lt "30" ]; then + icon="π" +else + icon="π" +fi + +echo "$icon$vol%" diff --git a/scripts/bin/statusbar/weather b/scripts/bin/statusbar/weather @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +location="$1"; [ -z "$location" ] || { location="$location+" && rm -f "$HOME/.local/share/weatherreport" ;} + +getforecast() { ping -q -c 1 1.1.1.1 >/dev/null || exit 1 +curl -s "wttr.in/$location" > "$HOME/.local/share/weatherreport" || exit 1 ;} + +showweather() { printf "%s" "$(sed '16q;d' "$HOME/.local/share/weatherreport" | grep -wo "[0-9]*%" | sort -n | sed -e '$!d' | sed -e "s/^/β /g" | tr -d '\n')" +sed '13q;d' "$HOME/.local/share/weatherreport" | grep -o "m\\(-\\)*[0-9]\\+" | sort -n -t 'm' -k 2n | sed -e 1b -e '$!d' | tr '\n|m' ' ' | awk '{print " βοΈ",$1 "Β°","π",$2 "Β°"}' ;} + +case $BLOCK_BUTTON in + 1) $TERMINAL -e less -S "$HOME/.local/share/weatherreport" ;; + 2) getforecast && showweather ;; + 3) pgrep -x dunst >/dev/null && notify-send "π Weather module" "\- Left click for full forecast. +- Middle click to update forecast. +β: Chance of rain/snow +β: Daily low +π: Daily high" ;; +esac + +if [ "$(stat -c %y "$HOME/.local/share/weatherreport" >/dev/null 2>&1 | awk '{print $1}')" != "$(date '+%Y-%m-%d')" ] + then getforecast && showweather + else showweather +fi diff --git a/scripts/bin/tools/blarbs.sh b/scripts/bin/tools/blarbs.sh @@ -0,0 +1,222 @@ +#!/bin/sh +# beau's luke's auto rice boostrapping script (blarbs) +# by beau hilton, forked from bo Smith <luke@lukesmith.xyz> +# License: GNU GPLv3 + +### OPTIONS AND VARIABLES ### + +while getopts ":a:r:b:p:h" o; do case "${o}" in + h) printf "Optional arguments for custom use:\\n -r: Dotfiles repository (local file or url)\\n -b: Dotfiles branch (master is assumed otherwise)\\n -p: Dependencies and programs csv (local file or url)\\n -a: AUR helper (must have pacman-like syntax)\\n -h: Show this message\\n" && exit ;; + r) dotfilesrepo=${OPTARG} && git ls-remote "$dotfilesrepo" || exit ;; + b) repobranch=${OPTARG} ;; + p) progsfile=${OPTARG} ;; + a) aurhelper=${OPTARG} ;; + *) printf "Invalid option: -%s\\n" "$OPTARG" && exit ;; +esac done + +# DEFAULTS: +[ -z "$dotfilesrepo" ] && dotfilesrepo="https://github.com/cbeauhilton/blarbs.git" && repobranch="archi3" +[ -z "$progsfile" ] && progsfile="https://raw.githubusercontent.com/cbeauhilton/blarbs/archi3/.config/progs.csv" +[ -z "$aurhelper" ] && aurhelper="yay" +[ -z "$repobranch" ] && repobranch="master" + +### FUNCTIONS ### + +error() { clear; printf "ERROR:\\n%s\\n" "$1"; exit;} + +welcomemsg() { \ + dialog --title "Welcome!" --msgbox "Welcome to blarbs.\\n\\nThis script will automatically install a fully-featured i3wm Arch Linux desktop, which I use as my main machine.\\n\\n-bo" 10 60 + } + +getuserandpass() { \ + # Prompts user for new username an password. + name=$(dialog --inputbox "First, please enter a name for the user account." 10 60 3>&1 1>&2 2>&3 3>&1) || exit + while ! echo "$name" | grep "^[a-z_][a-z0-9_-]*$" >/dev/null 2>&1; do + name=$(dialog --no-cancel --inputbox "Username not valid. Give a username beginning with a letter, with only lowercase letters, - or _." 10 60 3>&1 1>&2 2>&3 3>&1) + done + pass1=$(dialog --no-cancel --passwordbox "Enter a password for that user." 10 60 3>&1 1>&2 2>&3 3>&1) + pass2=$(dialog --no-cancel --passwordbox "Retype password." 10 60 3>&1 1>&2 2>&3 3>&1) + while ! [ "$pass1" = "$pass2" ]; do + unset pass2 + pass1=$(dialog --no-cancel --passwordbox "Passwords do not match.\\n\\nEnter password again." 10 60 3>&1 1>&2 2>&3 3>&1) + pass2=$(dialog --no-cancel --passwordbox "Retype password." 10 60 3>&1 1>&2 2>&3 3>&1) + done ;} + +usercheck() { \ + ! (id -u "$name" >/dev/null) 2>&1 || + dialog --colors --title "WARNING!" --yes-label "CONTINUE" --no-label "No wait..." --yesno "The user \`$name\` already exists on this system. blarbs can install for a user already existing, but it will \\Zboverwrite\\Zn any conflicting settings/dotfiles on the user account.\\n\\nblarbs will \\Zbnot\\Zn overwrite your user files, documents, videos, etc., so don't worry about that, but only click <CONTINUE> if you don't mind your settings being overwritten.\\n\\nNote also that blarbs will change $name's password to the one you just gave." 14 70 + } + +preinstallmsg() { \ + dialog --title "Let's get this party started!" --yes-label "Let's go!" --no-label "No, nevermind!" --yesno "The rest of the installation will now be totally automated, so you can sit back and relax.\\n\\nIt will take some time, but when done, you can relax even more with your complete system.\\n\\nNow just press <Let's go!> and the system will begin installation!" 13 60 || { clear; exit; } + } + +adduserandpass() { \ + # Adds user `$name` with password $pass1. + dialog --infobox "Adding user \"$name\"..." 4 50 + useradd -m -g wheel -s /bin/bash "$name" >/dev/null 2>&1 || + usermod -a -G wheel "$name" && mkdir -p /home/"$name" && chown "$name":wheel /home/"$name" + echo "$name:$pass1" | chpasswd + unset pass1 pass2 ;} + +refreshkeys() { \ + dialog --infobox "Refreshing Arch Keyring..." 4 40 + pacman --noconfirm -Sy archlinux-keyring >/dev/null 2>&1 + } + +newperms() { # Set special sudoers settings for install (or after). + sed -i "/#blarbs/d" /etc/sudoers + echo "$* #blarbs" >> /etc/sudoers ;} + +manualinstall() { # Installs $1 manually if not installed. Used only for AUR helper here. + [ -f "/usr/bin/$1" ] || ( + dialog --infobox "Installing \"$1\", an AUR helper..." 4 50 + cd /tmp || exit + rm -rf /tmp/"$1"* + curl -sO https://aur.archlinux.org/cgit/aur.git/snapshot/"$1".tar.gz && + sudo -u "$name" tar -xvf "$1".tar.gz >/dev/null 2>&1 && + cd "$1" && + sudo -u "$name" makepkg --noconfirm -si >/dev/null 2>&1 + cd /tmp || return) ;} + +maininstall() { # Installs all needed programs from main repo. + dialog --title "blarbs Installation" --infobox "Installing \`$1\` ($n of $total). $1 $2" 5 70 + pacman --noconfirm --needed -S "$1" >/dev/null 2>&1 + } + +gitmakeinstall() { + dir=$(mktemp -d) + dialog --title "blarbs Installation" --infobox "Installing \`$(basename "$1")\` ($n of $total) via \`git\` and \`make\`. $(basename "$1") $2" 5 70 + git clone --depth 1 "$1" "$dir" >/dev/null 2>&1 + cd "$dir" || exit + make >/dev/null 2>&1 + make install >/dev/null 2>&1 + cd /tmp || return ;} + +aurinstall() { \ + dialog --title "blarbs Installation" --infobox "Installing \`$1\` ($n of $total) from the AUR. $1 $2" 5 70 + echo "$aurinstalled" | grep "^$1$" >/dev/null 2>&1 && return + sudo -u "$name" $aurhelper -S --noconfirm "$1" >/dev/null 2>&1 + } + +pipinstall() { \ + dialog --title "blarbs Installation" --infobox "Installing the Python package \`$1\` ($n of $total). $1 $2" 5 70 + command -v pip || pacman -S --noconfirm --needed python-pip >/dev/null 2>&1 + yes | pip install "$1" + } + +installationloop() { \ + ([ -f "$progsfile" ] && cp "$progsfile" /tmp/progs.csv) || curl -Ls "$progsfile" | sed '/^#/d' > /tmp/progs.csv + total=$(wc -l < /tmp/progs.csv) + aurinstalled=$(pacman -Qm | awk '{print $1}') + while IFS=, read -r tag program comment; do + n=$((n+1)) + echo "$comment" | grep "^\".*\"$" >/dev/null 2>&1 && comment="$(echo "$comment" | sed "s/\(^\"\|\"$\)//g")" + case "$tag" in + "") maininstall "$program" "$comment" ;; + "A") aurinstall "$program" "$comment" ;; + "G") gitmakeinstall "$program" "$comment" ;; + "P") pipinstall "$program" "$comment" ;; + esac + done < /tmp/progs.csv ;} + +putgitrepo() { # Downlods a gitrepo $1 and places the files in $2 only overwriting conflicts + dialog --infobox "Downloading and installing config files..." 4 60 + [ -z "$3" ] && branch="master" || branch="$repobranch" + dir=$(mktemp -d) + [ ! -d "$2" ] && mkdir -p "$2" && chown -R "$name:wheel" "$2" + chown -R "$name:wheel" "$dir" + sudo -u "$name" git clone -b "$branch" --depth 1 "$1" "$dir/gitrepo" >/dev/null 2>&1 && + sudo -u "$name" cp -rfT "$dir/gitrepo" "$2" + } + +serviceinit() { for service in "$@"; do + dialog --infobox "Enabling \"$service\"..." 4 40 + systemctl enable "$service" + systemctl start "$service" + done ;} + +systembeepoff() { dialog --infobox "Getting rid of that retarded error beep sound..." 10 50 + rmmod pcspkr + echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf ;} + +resetpulse() { dialog --infobox "Reseting Pulseaudio..." 4 50 + killall pulseaudio + sudo -n "$name" pulseaudio --start ;} + +finalize(){ \ + dialog --infobox "Preparing welcome message..." 4 50 + echo "exec_always --no-startup-id notify-send -i ~/.local/share/larbs/larbs.png 'Welcome to blarbs:' 'Press Super+F1 for the manual.' -t 10000" >> "/home/$name/.config/i3/config" + dialog --title "All done!" --msgbox "Congrats! Provided there were no hidden errors, the script completed successfully and all the programs and configuration files should be in place.\\n\\nTo run the new graphical environment, log out and log back in as your new user, then run the command \"startx\" to start the graphical environment (it will start automatically in tty1).\\n\\n.t bo" 12 80 + } + +### THE ACTUAL SCRIPT ### + +### This is how everything happens in an intuitive format and order. + +# Check if user is root on Arch distro. Install dialog. +pacman -Syu --noconfirm --needed dialog || error "Are you sure you're running this as the root user? Are you sure you're using an Arch-based distro? ;-) Are you sure you have an internet connection? Are you sure your Arch keyring is updated?" + +# Welcome user. +welcomemsg || error "User exited." + +# Get and verify username and password. +getuserandpass || error "User exited." + +# Give warning if user already exists. +usercheck || error "User exited." + +# Last chance for user to back out before install. +preinstallmsg || error "User exited." + +### The rest of the script requires no user input. + +adduserandpass || error "Error adding username and/or password." + +# Refresh Arch keyrings. +refreshkeys || error "Error automatically refreshing Arch keyring. Consider doing so manually." + +dialog --title "blarbs Installation" --infobox "Installing \`basedevel\` and \`git\` for installing other software." 5 70 +pacman --noconfirm --needed -S base-devel git >/dev/null 2>&1 +[ -f /etc/sudoers.pacnew ] && cp /etc/sudoers.pacnew /etc/sudoers # Just in case + +# Allow user to run sudo without password. Since AUR programs must be installed +# in a fakeroot environment, this is required for all builds with AUR. +newperms "%wheel ALL=(ALL) NOPASSWD: ALL" + +# Make pacman and yay colorful and adds eye candy on the progress bar because why not. +grep "^Color" /etc/pacman.conf >/dev/null || sed -i "s/^#Color/Color/" /etc/pacman.conf +grep "ILoveCandy" /etc/pacman.conf >/dev/null || sed -i "/#VerbosePkgLists/a ILoveCandy" /etc/pacman.conf + +# Use all cores for compilation. +sed -i "s/-j2/-j$(nproc)/;s/^#MAKEFLAGS/MAKEFLAGS/" /etc/makepkg.conf + +manualinstall $aurhelper || error "Failed to install AUR helper." + +# The command that does all the installing. Reads the progs.csv file and +# installs each needed program the way required. Be sure to run this only after +# the user has been created and has priviledges to run sudo without a password +# and all build dependencies are installed. +installationloop + +# Install the dotfiles in the user's home directory +putgitrepo "$dotfilesrepo" "/home/$name" "$repobranch" +rm -f "/home/$name/README.md" "/home/$name/LICENSE" + +# Pulseaudio, if/when initially installed, often needs a restart to work immediately. +[ -f /usr/bin/pulseaudio ] && resetpulse + +# Enable services here. +serviceinit NetworkManager cronie + +# Most important command! Get rid of the beep! +systembeepoff + +# This line, overwriting the `newperms` command above will allow the user to run +# serveral important commands, `shutdown`, `reboot`, updating, etc. without a password. +newperms "%wheel ALL=(ALL) ALL #blarbs +%wheel ALL=(ALL) NOPASSWD: /usr/bin/shutdown,/usr/bin/reboot,/usr/bin/systemctl suspend,/usr/bin/wifi-menu,/usr/bin/mount,/usr/bin/umount,/usr/bin/pacman -Syu,/usr/bin/pacman -Syyu,/usr/bin/packer -Syu,/usr/bin/packer -Syyu,/usr/bin/systemctl restart NetworkManager,/usr/bin/rc-service NetworkManager restart,/usr/bin/pacman -Syyu --noconfirm,/usr/bin/loadkeys,/usr/bin/yay,/usr/bin/pacman -Syyuw --noconfirm" + +# Last message! Install complete! +finalize +clear diff --git a/scripts/bin/tools/compiler b/scripts/bin/tools/compiler @@ -0,0 +1,38 @@ +#!/usr/bin/env 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. Opens .sent files as sent +# presentations. Runs scripts based on extention or shebang + +file=$(readlink -f "$1") +dir=$(dirname "$file") +base="${file%.*}" + +cd "$dir" || exit + +textype() { \ + command="pdflatex" + ( sed 5q "$file" | grep -i -q 'xelatex' ) && command="xelatex" + $command --output-directory="$dir" "$base" && + grep -i addbibresource "$file" >/dev/null && + biber --input-directory "$dir" "$base" && + $command --output-directory="$dir" "$base" && + $command --output-directory="$dir" "$base" + } + +case "$file" in + *\.ms) refer -PS -e "$file" | groff -me -ms -kept -T pdf > "$base".pdf ;; + *\.mom) refer -PS -e "$file" | groff -mom -kept -T pdf > "$base".pdf ;; + *\.[0-9]) refer -PS -e "$file" | groff -mandoc -T pdf > "$base".pdf ;; + *\.rmd) echo "require(rmarkdown); render('$file', output_format = 'all')" | R -q --vanilla ;; + *\.tex) textype "$file" ;; + *\.md) pandoc "$file" --pdf-engine=xelatex -o "$base".pdf ;; + *config.h) sudo make install ;; + *\.c) cc "$file" -o "$base" && "$base" ;; + *\.py) python "$file" ;; + *\.go) go run "$file" ;; + *\.sent) setsid sent "$file" 2>/dev/null & ;; + *) sed 1q "$file" | grep "^#!/" | sed "s/^#!//" | xargs -r -I % "$file" ;; +esac diff --git a/scripts/bin/tools/dmenuhandler b/scripts/bin/tools/dmenuhandler @@ -0,0 +1,15 @@ +#!/usr/bin/env sh +# Feed this script a link and it will give dmenu +# some choice programs to use to open it. + +case "$(printf "copy url\\nmpv\\nmpv (loop)\\nqueue download\\n\\nqueue youtube-dl\\nfeh\\nbrowser\\nw3m\\nmpv (float)" | dmenu -i -p "Open link with what program?")" in + "copy url") echo "$1" | xclip -selection clipboard ;; + mpv) setsid mpv -quiet "$1" >/dev/null 2>&1 & ;; + "mpv (loop)") setsid mpv --input-ipc-server=/tmp/mpvsoc$(date +%s) -quiet --loop "$1" >/dev/null 2>&1 & ;; + "queue download") tsp curl -LO "$1" >/dev/null 2>&1 ;; + "queue youtube-dl") tsp youtube-dl --write-metadata -ic "$1" >/dev/null 2>&1 ;; + browser) setsid "$BROWSER" "$1" >/dev/null 2>&1 & ;; + feh) setsid feh "$1" >/dev/null 2>&1 & ;; + w3m) w3m "$1" >/dev/null 2>&1 ;; + "mpv (float)") setsid mpv --input-ipc-server=/tmp/mpvsoc$(date +%s) --geometry=+0-0 --autofit=30% --title="mpvfloat" "$1" >/dev/null 2>&1 & ;; +esac diff --git a/scripts/bin/tools/dmenupass b/scripts/bin/tools/dmenupass @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +dmenu -fn Monospace-18 -sb "#d79921" -sf "#1d2021" -nf "#000000" -nb "#000000" -p "$1" <&- && echo diff --git a/scripts/bin/tools/dmenushutdown b/scripts/bin/tools/dmenushutdown @@ -0,0 +1,9 @@ +#!/bin/sh + +RET=$(echo -e "shutdown\nreboot\ncancel" | dmenu -l 5 -p "ο") + +case $RET in + shutdown) sudo -A shutdown -h now ;; + reboot) sudo reboot ;; + *) ;; +esac diff --git a/scripts/bin/tools/ext b/scripts/bin/tools/ext @@ -0,0 +1 @@ +extract+ \ No newline at end of file diff --git a/scripts/bin/tools/extract b/scripts/bin/tools/extract @@ -0,0 +1,41 @@ +#!/usr/bin/env sh +# A general, all-purpose extraction script. +# +# 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 ;; +esac done + +if [ -z "$extracthere" ]; then + archive="$(readlink -f "$*")" && + directory="$(echo "$archive" | sed 's/\.[^\/.]*$//')" && + mkdir -p "$directory" && + cd "$directory" || exit +else + archive="$(readlink -f "$(echo "$*" | cut -d' ' -f2)")" +fi + +[ "$archive" = "" ] && printf "Give archive to extract as argument.\\n" && exit + +if [ -f "$archive" ] ; then + case "$archive" in + *.tar.bz2|*.tar.xz|*.tbz2) tar xvjf "$archive" ;; + *.tar.gz|*.tgz) tar xvzf "$archive" ;; + *.lzma) unlzma "$archive" ;; + *.bz2) bunzip2 "$archive" ;; + *.rar) unrar x -ad "$archive" ;; + *.gz) gunzip "$archive" ;; + *.tar) tar xvf "$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/scripts/bin/tools/getbib b/scripts/bin/tools/getbib @@ -0,0 +1,14 @@ +#!/usr/bin/env sh +[ -z "$1" ] && echo "Give either a pdf file or a DOI as an argument." && exit + +if [ -f "$1" ]; then + # Try to get DOI from pdfinfo or pdftotext output. + doi=$(pdfinfo "$1" | grep -io "doi:.*") || + doi=$(pdftotext "$1" 2>/dev/null - | grep -io "doi:.*" -m 1) || + exit 1 +else + doi="$1" +fi + +# Check crossref.org for the bib citation. +curl -s "http://api.crossref.org/works/$doi/transform/application/x-bibtex" -w "\\n" diff --git a/scripts/bin/tools/gitlistobjectbysize b/scripts/bin/tools/gitlistobjectbysize @@ -0,0 +1,16 @@ +#!/bin/bash -e + +# work over each commit and append all files in tree to $tempFile +tempFile=$(mktemp) +IFS=$'\n' +for commitSHA1 in $(git rev-list --all); do + git ls-tree -r --long "$commitSHA1" >>"$tempFile" +done + +# sort files by SHA1, de-dupe list and finally re-sort by filesize +sort --key 3 "$tempFile" | \ + uniq | \ + sort --key 4 --numeric-sort --reverse + +# remove temp file +rm "$tempFile" diff --git a/scripts/bin/tools/ifinstalled b/scripts/bin/tools/ifinstalled @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +# If $1 command is not available, error code and notify. +command -v "$1" >/dev/null || { notify-send "π¦ $1" "must be installed for this function." && exit 1 ;} diff --git a/scripts/bin/tools/linkhandler b/scripts/bin/tools/linkhandler @@ -0,0 +1,22 @@ +#!/usr/bin/env 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*) + setsid mpv --input-ipc-server=/tmp/mpvsoc$(date +%s) -quiet "$1" >/dev/null 2>&1 & ;; + *png|*jpg|*jpe|*jpeg|*gif) + curl -sL "$1" > "/tmp/$(echo "$1" | sed "s/.*\///")" && sxiv -a "/tmp/$(echo "$1" | sed "s/.*\///")" >/dev/null 2>&1 & ;; + *mp3|*flac|*opus|*mp3?source*) + setsid tsp curl -LO "$1" >/dev/null 2>&1 & ;; + *) + if [ -f "$1" ]; then "$TERMINAL" -e "$EDITOR $1" + else setsid "$BROWSER" "$1" >/dev/null 2>&1 & fi ;; +esac diff --git a/scripts/bin/tools/lmc b/scripts/bin/tools/lmc @@ -0,0 +1,42 @@ +#!/usr/bin/env sh +# A general audio interface for LARBS. + +[ -z "$2" ] && num="2" || num="$2" + +case "$1" in + u*) pulsemixer --change-volume +"$num" ;; + d*) pulsemixer --change-volume -"$num" ;; + m*) pulsemixer --toggle-mute ;; + truemute) pulsemixer --mute ;; + play) mpc play ;; + n*) mpc next ;; + prev) mpc prev ;; + t*) mpc toggle ;; + p*) mpc pause ; pauseallmpv ;; + f*) mpc seek +"$num" ;; + b*) mpc seek -"$num" ;; + r*) mpc seek 0% ;; + *) cat << EOF +lmc: cli music interface for mpd and pulse for those with divine intellect too +grand to remember the mpc/pamixer commands. + +Allowed options: + up NUM Increase volume (2 secs default) + down NUM Decrease volume (2 secs default) + mute Toggle mute + truemute Mute + next Next track + prev Previous track + toggle Toggle pause + truepause Pause + foward NUM Seek foward in song (2 secs default) + back NUM Seek back in song (2 secs default) + restart Restart current song + all else Print this message + +All of these commands, except for \`truemute\`, \`prev\` and \`play\` can be truncated, +i.e. \`lmc r\` for \`lmc restart\`. +EOF +esac + +pkill -RTMIN+10 i3blocks diff --git a/scripts/bin/tools/opout b/scripts/bin/tools/opout @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +# opout: "open output": A general handler for opening a file's intended output. +# I find this useful especially running from vim. + +basename="$(echo "$1" | sed 's/\.[^\/.]*$//')" + +case "$1" in + *.tex|*.md|*.rmd|*.ms|*.me|*.mom) setsid "$READER" "$basename".pdf >/dev/null 2>&1 & ;; + *.html) setsid "$BROWSER" --new-window "$basename".html >/dev/null 2>&1 & ;; + *.sent) setsid sent "$1" >/dev/null 2>&1 & ;; +esac diff --git a/scripts/bin/tools/pauseallmpv b/scripts/bin/tools/pauseallmpv @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +for i in $(ls /tmp/mpvsoc*); do + echo '{ "command": ["set_property", "pause", true] }' | socat - $i; +done diff --git a/scripts/bin/tools/podentr b/scripts/bin/tools/podentr @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +# entr command to run `queueandnotify` when newsboat queue is changed + +[ "$(pgrep -x $(basename $0) | wc -l)" -gt 2 ] && exit + +echo ~/.local/share/newsboat/queue | entr -p queueandnotify 2>/dev/null diff --git a/scripts/bin/tools/qndl b/scripts/bin/tools/qndl @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +# $1 is a url; $2 is a command +[ -z "$1" ] && exit +base="$(basename "$1")" +notify-send "β³ Queuing $base..." +cmd="$2" +[ -z "$cmd" ] && cmd="youtube-dl --add-metadata" +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/scripts/bin/tools/queueandnotify b/scripts/bin/tools/queueandnotify @@ -0,0 +1,13 @@ +#!/usr/bin/env sh +# Podboat sucks. This script replaces it. +# It reads the newsboat queue, queuing downloads with taskspooler. +# It also removes the junk from extentions. +queuefile="$HOME/.local/share/newsboat/queue" + +while read -r line; do + [ -z "$line" ] && continue + url="$(echo "$line" | awk '{print $1}')" + qndl "$url" "curl -LO" +done < "$queuefile" + +echo > "$queuefile" diff --git a/scripts/bin/tools/reload_html b/scripts/bin/tools/reload_html @@ -0,0 +1,22 @@ +#!/bin/sh + +# Get the document title because the browser uses it in the window name +WINNAME=`grep '<title>.*</title>' "$1" | sed -e 's/.*<title>\(.*\)<\/title>.*/\1/'` + +# If the title is empty, use the file name +if [ "x$WINNAME" = "x" ] +then + WINNAME=$1 +fi + +# Check if the page is already open +xdotool search --name "$WINNAME" windowactivate --sync + +if [ "$?" = "0" ] +then + # The page is open; emulate the F5 key press to refresh it: + xdotool search --name "$WINNAME" key --clearmodifiers F5 +else + # Start the browser + chromium "$1" & +fi diff --git a/scripts/bin/tools/remaps b/scripts/bin/tools/remaps @@ -0,0 +1,10 @@ +#!/usr/bin/env 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' diff --git a/scripts/bin/tools/rotdir b/scripts/bin/tools/rotdir @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +[ -z "$1" ] && echo "usage: rotdir regex 2>&1" && exit 1 +base="$(basename $1)" + ls "$PWD" | awk "BEGIN { lines = \"\"; m = 0; } /^$base$/ { m = 1; } { if (!m) { if (lines) { lines = lines\"\n\"; } lines = lines\"\"\$0; } else { print \$0; } } END { print lines; }" diff --git a/scripts/bin/tools/rssadd b/scripts/bin/tools/rssadd @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +! echo "$1" | grep "https*://\S\+\.[A-Za-z]\+\S*" >/dev/null && + notify-send "That doesn't look like a full URL." && exit +RSSFILE="$HOME/.config/newsboat/urls" +if awk '{print $1}' "$RSSFILE" | grep "^$1$" >/dev/null; then + notify-send "You already have this RSS feed." +else + echo "$1" >> "$RSSFILE" && notify-send "RSS feed added." +fi diff --git a/scripts/bin/tools/setbg b/scripts/bin/tools/setbg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +# Sets the background. If given an argument, will set file as background. +[ ! -z "$1" ] && cp "$1" ~/.config/wall.png && notify-send -i "$HOME/.config/wall.png" "Wallpaper changed." +feh --bg-fill ~/.config/wall.png diff --git a/scripts/bin/tools/shortcuts b/scripts/bin/tools/shortcuts @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Output locations. Unactivated progs should go to /dev/null. +shell_shortcuts="$HOME/.config/shortcutrc" +ranger_shortcuts="/dev/null" +qute_shortcuts="/dev/null" +fish_shortcuts="/dev/null" +vifm_shortcuts="$HOME/.config/vifm/vifmshortcuts" + +# Remove, prepare files +rm -f "$ranger_shortcuts" "$qute_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 `bmdirs` file in the correct syntax and sent it to all three configs. +sed "s/\s*#.*$//;/^\s*$/d" "$HOME/.config/bmdirs" | tee >(awk '{print $1"=\"cd "$2" && ls -a\" \\"}' >> "$shell_shortcuts") \ + >(awk '{print "abbr", $1, "\"cd " $2 "; and ls -a\""}' >> "$fish_shortcuts") \ + >(awk '{print "map g" $1, ":cd", $2 "<CR>\nmap t" $1, "<tab>:cd", $2 "<CR><tab>\nmap M" $1, "<tab>:cd", $2 "<CR><tab>:mo<CR>\nmap Y" $1, "<tab>:cd", $2 "<CR><tab>:co<CR>" }' >> "$vifm_shortcuts") \ + >(awk '{print "config.bind(\";"$1"\", \"set downloads.location.directory "$2" ;; hint links download\")"}' >> "$qute_shortcuts") \ + | awk '{print "map g"$1" cd "$2"\nmap t"$1" tab_new "$2"\nmap m"$1" shell mv -v %s "$2"\nmap Y"$1" shell cp -rv %s "$2}' >> "$ranger_shortcuts" + +# Format the `configs` file in the correct syntax and sent it to both configs. +sed "s/\s*#.*$//;/^\s*$/d" "$HOME/.config/bmfiles" | tee >(awk '{print $1"=\"$EDITOR "$2"\" \\"}' >> "$shell_shortcuts") \ + >(awk '{print "abbr", $1, "\"$EDITOR "$2"\""}' >> "$fish_shortcuts") \ + >(awk '{print "map", $1, ":e", $2 "<CR>" }' >> "$vifm_shortcuts") \ + | awk '{print "map "$1" shell $EDITOR "$2}' >> "$ranger_shortcuts" diff --git a/scripts/bin/tools/startdwm b/scripts/bin/tools/startdwm @@ -0,0 +1,6 @@ +while true; do + # Log stderror to a file + dwm 2> ~/.dwm.log + # No error logging + #dwm >/dev/null 2>&1 +done diff --git a/scripts/bin/tools/texclear b/scripts/bin/tools/texclear @@ -0,0 +1,14 @@ +#!/usr/bin/env 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|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 "Give .tex file as argument.\\n" ;; +esac + diff --git a/scripts/bin/tools/transadd b/scripts/bin/tools/transadd @@ -0,0 +1,9 @@ +#!/usr/bin/env 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. + +pgrep -x transmission-da || (transmission-daemon && notify-send "Starting transmission daemon..." && sleep 3 && pkill -RTMIN+7 i3blocks) + +transmission-remote -a "$@" && notify-send "π½ Torrent added." diff --git a/scripts/bin/tools/vifmimg b/scripts/bin/tools/vifmimg @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +readonly ID_PREVIEW="preview" + +#PLAY_GIF="yes" +# By enabling this option the GIF will be animated, by leaving it commented like it +# is now will make the gif previews behave the same way as video previews. + +#AUTO_REMOVE="yes" +# By enabling this option the script will remove the preview file after it is drawn +# and by doing so the preview will always be up-to-date with the file. +# This however, requires more CPU and therefore affects the overall performance. + +# The messy code below is for moving pages in pdf files in the vifm file preview by +# utilizing the < and > keys which will be bound to `vifmimg inc` or `vifmimg dec`. +PDF_PAGE_CONFIG="$HOME/.config/vifm/vifmimgpdfpage" +PDF_FILE_CONFIG="$HOME/.config/vifm/vifmimgpdffile" +PDF_PAGE=1 +PDF_FILE="" +# Initialize the variables and required files +[[ -f "$PDF_PAGE_CONFIG" ]] && PDF_PAGE=$(cat $PDF_PAGE_CONFIG) || touch $PDF_PAGE_CONFIG +[[ -f "$PDF_FILE_CONFIG" ]] && PDF_FILE=$(cat $PDF_FILE_CONFIG) || touch $PDF_FILE_CONFIG + + +# Create temporary working directory if the directory structure doesn't exist +if [[ ! -d "/tmp$PWD/" ]]; then + mkdir -p "/tmp$PWD/" +fi + +function inc() { + VAL="$(cat $PDF_PAGE_CONFIG)" + echo "$(expr $VAL + 1)" > $PDF_PAGE_CONFIG +} + +function dec() { + VAL="$(cat $PDF_PAGE_CONFIG)" + echo "$(expr $VAL - 1)" > $PDF_PAGE_CONFIG + if [[ $VAL -le 0 ]]; then + echo 0 > $PDF_PAGE_CONFIG + fi +} + +function previewclear() { + declare -p -A cmd=([action]=remove [identifier]="$ID_PREVIEW") \ + > "$FIFO_UEBERZUG" +} + +function fileclean() { + if [[ -f "/tmp$PWD/$6.png" ]]; then + rm -f "/tmp$PWD/$6.png" + elif [[ -d "/tmp$PWD/$6/" ]]; then + rm -rf "/tmp$PWD/$6/" + fi +} + +function preview() { + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="$PWD/$6") \ + > "$FIFO_UEBERZUG" +} + +function previewvideo() { + if [[ ! -f "/tmp$PWD/$6.png" ]]; then + ffmpegthumbnailer -i "$PWD/$6" -o "/tmp$PWD/$6.png" -s 0 -q 10 + fi + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="/tmp$PWD/$6.png") \ + > "$FIFO_UEBERZUG" +} + +function previewepub() { + if [[ ! -f "/tmp$PWD/$6.png" ]]; then + epub-thumbnailer "$6" "/tmp$PWD/$6.png" 1024 + fi + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="/tmp$PWD/$6.png") \ + > "$FIFO_UEBERZUG" +} + +function previewgif() { + if [[ ! -d "/tmp$PWD/$6/" ]]; then + mkdir -p "/tmp$PWD/$6/" + convert -coalesce "$PWD/$6" "/tmp$PWD/$6/$6.png" + fi + if [[ ! -z "$PLAY_GIF" ]]; then + for frame in $(ls -1 /tmp$PWD/$6/$6*.png | sort -V); do + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="$frame") \ + > "$FIFO_UEBERZUG" + # Sleep between frames to make the animation smooth. + sleep .07 + done + else + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="/tmp$PWD/$6/$6-0.png") \ + > "$FIFO_UEBERZUG" + fi +} + +function previewpdf() { + if [[ ! "$6" == "$PDF_FILE" ]]; then + PDF_PAGE=1 + echo 1 > $PDF_PAGE_CONFIG + rm -f "/tmp$PWD/$6.png" + fi + + if [[ ! "$PDF_PAGE" == "1" ]] && [[ -f "/tmp$PWD/$6.png" ]]; then + rm -f "/tmp$PWD/$6.png" + fi + + if [[ ! -f "/tmp$PWD/$6.png" ]]; then + pdftoppm -png -f $PDF_PAGE -singlefile "$6" "/tmp$PWD/$6" + fi + echo "$6" > $PDF_FILE_CONFIG + + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="/tmp$PWD/$6.png") \ + > "$FIFO_UEBERZUG" +} + + +function previewmagick() { + if [[ ! -f "/tmp$PWD/$6.png" ]]; then + convert -thumbnail $(identify -format "%wx%h" "$6") "$PWD/$6" "/tmp$PWD/$6.png" + fi + declare -p -A cmd=([action]=add [identifier]="$ID_PREVIEW" + [x]="$2" [y]="$3" [width]="$4" [height]="$5" \ + [path]="/tmp$PWD/$6.png") \ + > "$FIFO_UEBERZUG" +} + + + +function main() { + case "$1" in + "inc") inc "$@" ;; + "dec") dec "$@" ;; + "clear") previewclear "$@" ;; + "clean") fileclean "$@" ;; + "draw") preview "$@" ;; + "videopreview") previewvideo "$@" ;; + "epubpreview") previewepub "$@" ;; + "gifpreview") previewgif "$@" ;; + "pdfpreview") previewpdf "$@" ;; + "magickpreview") previewmagick "$@" ;; + "*") echo "Unknown command: '$@'" ;; + esac +} +main "$@" diff --git a/scripts/bin/tools/vifmrun b/scripts/bin/tools/vifmrun @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +export FIFO_UEBERZUG="/tmp/vifm-ueberzug-${PPID}" + +function cleanup { + rm "$FIFO_UEBERZUG" 2>/dev/null + pkill -P $$ 2>/dev/null +} +pkill -P $$ 2>/dev/null +rm "$FIFO_UEBERZUG" 2>/dev/null +mkfifo "$FIFO_UEBERZUG" >/dev/null +trap cleanup EXIT 2>/dev/null +tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser bash 2>&1 >/dev/null & + +vifm +cleanup diff --git a/scripts/bin/tools/vu b/scripts/bin/tools/vu @@ -0,0 +1,15 @@ +#!/usr/bin/env sh +export FIFO_UEBERZUG="/tmp/vifm-ueberzug-${PPID}" + +cleanup() { + rm "$FIFO_UEBERZUG" 2>/dev/null + pkill -P $$ 2>/dev/null +} + +rm "$FIFO_UEBERZUG" 2>/dev/null +mkfifo "$FIFO_UEBERZUG" +trap cleanup EXIT +tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser bash & + +vifm +cleanup diff --git a/scripts/bin/ttymaps.kmap b/scripts/bin/ttymaps.kmap @@ -0,0 +1,2 @@ +keycode 1 = Caps_Lock +keycode 58 = Escape