scripts - scripts - some useful shell scripts

git clone git://git.bcharge.de/scripts.git

About | Log | Files | Refs

commit cd0df10a83f5d07052f2facd19389012e7439a19
parent fc784674af303236c66b8daebb4f78d68779129b
Author: Bakar Chargeishvili <bakar.chargeishvili@gmx.de>
Date:   Fri,  8 Dec 2023 14:34:16 +0100

Add more scripts

Diffstat:
AAdobeReader | 1+
MREADME.md | 2+-
Aaudio | 27+++++++++++++++++++++++++++
Aaudio_alsa.sh | 18++++++++++++++++++
Aaudio_pulse.sh | 18++++++++++++++++++
Abottomleft | 17+++++++++++++++++
Acamtoggle | 2++
Acht.sh | 748+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aclear.sh | 1+
Acolortest | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acompiler | 17+++++++++++++++++
Admenuhandler | 24++++++++++++++++++++++++
Admenumount | 27+++++++++++++++++++++++++++
Admenurecord | 24++++++++++++++++++++++++
Admenuumount | 15+++++++++++++++
Adropdowncalc | 5+++++
Adwm_mutt | 2++
Aextract~ | 30++++++++++++++++++++++++++++++
AflashScreen | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alayout | 4++++
Alinkhandler | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amic_status.sh | 11+++++++++++
Anotmuch-address | 15+++++++++++++++
Aofflineimap-daemon.py | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aofflineimap-daemonctl.sh | 41+++++++++++++++++++++++++++++++++++++++++
Apdfrange | 12++++++++++++
Aprint_desy | 13+++++++++++++
Aprompt | 8++++++++
Aqndl | 12++++++++++++
Arecord | 8++++++++
Asb-doppler | 285+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ascreen.sh | 24++++++++++++++++++++++++
Ascreencast | 36++++++++++++++++++++++++++++++++++++
Ascreencast_alsa.sh | 22++++++++++++++++++++++
Ascreencast_lecture.sh | 25+++++++++++++++++++++++++
Ascreencast_pulse.sh | 27+++++++++++++++++++++++++++
Aspeedvid.sh | 7+++++++
Astart-tmux.sh | 9+++++++++
Astartdwm | 6++++++
Atmuxinit | 4++++
Atransmission.sh | 7+++++++
Avideo | 18++++++++++++++++++
42 files changed, 1956 insertions(+), 1 deletion(-)

diff --git a/AdobeReader b/AdobeReader @@ -0,0 +1 @@ +wine /home/delta/.wine/drive_c/Program\ Files\ \(x86\)/Adobe/Acrobat\ Reader\ DC/Reader/AcroRd32.exe diff --git a/README.md b/README.md @@ -1,3 +1,3 @@ # scripts - some usefult shell scripts -More details will follow... +More details will follow, for now see the comments in the respective files. diff --git a/audio b/audio @@ -0,0 +1,27 @@ +#!/bin/bash + +# This script records audio. +# It runs an appropriate record script for either ALSA and Pulseaudio. +# It also names files smartly to prevent overwrites. + +# Picks a file name for the output file based on availability: +while [[ -f $HOME/screencast$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/screencast$n.mkv" + +# For Pulseaudio with ALSA: +record_pulse() { \ +ffmpeg \ +-f alsa -i default \ +-c:a flac \ +$filename ;} + +# For ALSA: +record_alsa() { \ +ffmpeg -y \ +-f alsa -ar 44100 -i hw:1 \ +$filename ;} + +if [[ $(pgrep -x pulseaudio) ]]; then record_pulse; else record_alsa; fi diff --git a/audio_alsa.sh b/audio_alsa.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +#This is the ffmpeg command that the screencast shortcut in i3 will run. + +#Picks a file name for the output file based on availability: + +while [[ -f $HOME/audio$n.flac ]] +do + n=$((n+1)) +done +filename="$HOME/audio$n.flac" + +#The actual ffmpeg command: + +ffmpeg -y \ + -f alsa -ar 44100 -i hw:1 \ + $filename + diff --git a/audio_pulse.sh b/audio_pulse.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +#This is the ffmpeg command that the audio shortcut in i3 will run. + +#Picks a file name for the output file based on availability: + +while [[ -f $HOME/audio$n.flac ]] +do + n=$((n+1)) +done +filename="$HOME/audio$n.flac" + +#The actual ffmpeg command: + +ffmpeg \ +-f alsa -i default \ +-c:a flac \ +$filename diff --git a/bottomleft b/bottomleft @@ -0,0 +1,17 @@ +#!/bin/bash + +# This script move the selected window to the bottom left of the screen. + +current=$(xdotool getwindowfocus) + +# The window will take up no more than a third of +# the width or height of the screen. +newwidth=$(($(xdotool getdisplaygeometry | awk '{print $2}') / 3)) +newheight=$(($(xdotool getdisplaygeometry | awk '{print $1}') / 3)) + +xdotool windowsize $(xdotool getwindowfocus) $newheight $newwidth + +newsize=$(xdotool getwindowgeometry $(xdotool getwindowfocus) | grep Geometry | sed -e 's/x/ /g' | awk '{print $3}') + +height=$(($(xdotool getdisplaygeometry | awk '{print $2}') - newsize)) +xdotool windowmove $current 0 $height diff --git a/camtoggle b/camtoggle @@ -0,0 +1,2 @@ +#!/bin/bash +pkill -f /dev/video || mpv --no-osc --no-input-default-bindings --input-conf=/dev/null --geometry=-0-0 --autofit=30% --title="mpvfloat" --demuxer-lavf-o=video_size=1280x720:input_format=mjpeg /dev/video0 --profile=low-latency --untimed diff --git a/cht.sh b/cht.sh @@ -0,0 +1,748 @@ +#!/bin/bash +# shellcheck disable=SC1117,SC2001 +# +# [X] open section +# [X] one shot mode +# [X] usage info +# [X] dependencies check +# [X] help +# [X] yank/y/copy/c +# [X] Y/C +# [X] eof problem +# [X] more +# [X] stealth mode +# +# here are several examples for the stealth mode: +# +# zip lists +# list permutation +# random list element +# reverse a list +# read json from file +# append string to a file +# run process in background +# count words in text counter +# group elements list + +__CHTSH_VERSION=6 +__CHTSH_DATETIME="2019-06-05 18:00:46 +0200" + +# cht.sh configuration loading +# +# configuration is stored in ~/.cht.sh/ (can be overridden by CHTSH_HOME) +# +CHTSH_HOME=${CHTSH:-"$HOME"/.cht.sh} +[ -z "$CHTSH_CONF" ] && CHTSH_CONF=$CHTSH_HOME/cht.sh.conf +# shellcheck disable=SC1090,SC2002 +[ -e "$CHTSH_CONF" ] && source "$CHTSH_CONF" +[ -z "$CHTSH_URL" ] && CHTSH_URL=https://cht.sh + +# currently we support only two modes: +# * lite = access the server using curl +# * auto = try standalone usage first +CHTSH_MODE="$(cat "$CHTSH_HOME"/mode 2> /dev/null)" +[ "$CHTSH_MODE" != lite ] && CHTSH_MODE=auto +CHEATSH_INSTALLATION="$(cat "$CHTSH_HOME/standalone" 2> /dev/null)" + + +export LESSSECURE=1 +STEALTH_MAX_SELECTION_LENGTH=5 + +case "$(uname -s)" in + Darwin) is_macos=yes ;; + *) is_macos=no ;; +esac + +# for KSH93 +# shellcheck disable=SC2034,SC2039,SC2168 +if echo "$KSH_VERSION" | grep -q ' 93' && ! local foo 2>/dev/null; then + alias local=typeset +fi + +fatal() +{ + echo "ERROR: $*" >&2 + exit 1 +} + +_say_what_i_do() +{ + [ -n "$LOG" ] && echo "$(date '+[%Y-%m-%d %H:%M%S]') $*" >> "$LOG" + + local this_prompt="\033[0;1;4;32m>>\033[0m" + printf "\n${this_prompt}%s\033[0m\n" " $* " +} + +cheatsh_standalone_install() +{ + # the function installs cheat.sh with the upstream repositories + # in the standalone mode + local installdir; installdir="$1" + local default_installdir="$HOME/.cheat.sh" + + if [ "$installdir" = help ]; then + cat <<EOF +Install cheat.sh in the standalone mode. + +After the installation, cheat.sh can be used locally, without accessing +the public cheat.sh service, or it can be used in the server mode, +where the newly installed server could be accessed by external clients +in the same fashion as the public cheat.sh server. + +During the installation, cheat.sh code as well as the cheat.sh upstream +cheat sheets repositories will be fetched. + +It takes approximately 1G of the disk space. + +Default installation location: ~/.cheat.sh/ +It can be overriden by a command line parameter to this script: + + ${0##*/} --standalone-install DIR + +See cheat.sh/:standalone or https://github.com/chubin/cheat.sh/README.md +for more information: + + cht.sh :standalone + curl cheat.sh/:standalone + +After the installation is finished, the cht.sh shell client is switched +to the auto mode, where it uses the local cheat.sh installation if possible. +You can switch the mode with the --mode switch: + + cht.sh --mode lite # use https://cheat.sh/ only + cht.sh --mode auto # use local installation + +For intallation and standalone usage, you need \`git\`, \`python\`, +and \`virtualenv\` to be installed locally. +EOF + return + fi + + local _exit_code=0 + + local dependencies=(python git virtualenv) + for dep in "${dependencies[@]}"; do + command -v "$dep" >/dev/null || \ + { echo "DEPENDENCY: \"$dep\" is needed to install cheat.sh in the standalone mode" >&2; _exit_code=1; } + done + [ "$_exit_code" -ne 0 ] && return "$_exit_code" + + while true; do + echo -n "Where should cheat.sh be installed [$default_installdir]? "; read -r installdir + [ -n "$installdir" ] || installdir="$default_installdir" + + if [ "$installdir" = y ] \ + || [ "$installdir" = Y ] \ + || [ "$(echo "$installdir" | tr "[:upper:]" "[:lower:]")" = yes ] + then + echo Please enter the directory name + echo If it was the directory name already, please prepend it with \"./\": "./$installdir" + else + break + fi + done + + if [ -e "$installdir" ]; then + echo "ERROR: Installation directory [$installdir] exists already" + echo "Please remove it first before continuing" + return 1 + fi + + if ! mkdir -p "$installdir"; then + echo "ERROR: Could not create the installation directory \"$installdir\"" + echo "ERROR: Please check the permissions and start the script again" + return 1 + fi + + local space_needed=700 + local space_available; space_available=$(($(df -k "$installdir" | awk '{print $4}' | tail -1)/1024)) + + if [ "$space_available" -lt "$space_needed" ]; then + echo "ERROR: Installation directory has no enough space (needed: ${space_needed}M, available: ${space_available}M" + echo "ERROR: Please clean up and start the script again" + rmdir "$installdir" + return 1 + fi + + _say_what_i_do Cloning cheat.sh locally + local url=https://github.com/chubin/cheat.sh + rmdir "$installdir" + git clone "$url" "$installdir" || fatal Could not clone "$url" with git into "$installdir" + cd "$installdir" || fatal "Cannot cd into $installdir" + git checkout offline_usage + + # after the repository cloned, we may have the log directory + # and we can write our installation log into it + mkdir -p "$installdir/log/" + LOG="$installdir/log/install.log" + + # we use tee everywhere so we should set -o pipefail + set -o pipefail + + _say_what_i_do Creating virtual environment + python2 "$(command -v virtualenv)" ve \ + || fatal Could not create virtual environment with "python2 $(command -v virtualenv) ve" + + _say_what_i_do Installing python requirements into the virtual environment + ve/bin/pip install -r requirements.txt > "$LOG" \ + || { + + echo "ERROR:" + echo "---" + tail -n 10 "$LOG" + echo "---" + echo "See $LOG for more" + fatal Could not install python dependecies into the virtual environment + } + echo "$(ve/bin/pip freeze | wc -l) dependencies were successfully installed" + + _say_what_i_do Fetching the upstream cheat sheets repositories + ve/bin/python lib/fetch.py fetch-all | tee -a "$LOG" + + _say_what_i_do Running self-tests + ( + cd tests || exit + + if CHEATSH_TEST_STANDALONE=YES \ + CHEATSH_TEST_SKIP_ONLINE=NO \ + CHEATSH_TEST_SHOW_DETAILS=NO \ + PYTHON=../ve/bin/python bash run-tests.sh | tee -a "$LOG" + then + printf "\033[0;32m%s\033[0m\n" "SUCCESS" + else + printf "\033[0;31m%s\033[0m\n" "FAILED" + echo "Some tests were failed. Run the tests manually for further investigation:" + echo " cd $PWD; bash run-tests.sh)" + fi + ) + + mkdir -p "$CHTSH_HOME" + echo "$installdir" > "$CHTSH_HOME/standalone" + echo auto > "$CHTSH_HOME/mode" + + _say_what_i_do Done + + local v1; v1=$(printf "\033[0;1;32m") + local v2; v2=$(printf "\033[0m") + + cat <<EOF | sed "s/{/$v1/; s/}/$v2/" + +{ _ } +{ \\ \\ } The installation is successfully finished. +{ \\ \\ } +{ / / } Now you can use cheat.sh in the standalone mode, +{ /_/ } or you can start your own cheat.sh server. + + +Now the cht.sh shell client is switched to the auto mode, where it uses +the local cheat.sh installation if possible. +You can switch the mode with the --mode switch: + + cht.sh --mode lite # use https://cheat.sh/ only + cht.sh --mode auto # use local installation + +You can add your own cheat sheets repository (config is in \`etc/config.yaml\`), +or create new cheat sheets adapters (in \`lib/adapters\`). + +To update local copies of cheat sheets repositores on a regular basis, +add the following line to your user crontab (crontab -e): + + 10 * * * * $installdir/ve/bin/python $installdir/lib/fetch.py update-all + +All cheat sheets will be automatically actualized each hour. + +If you are running a server reachable from the Internet, it can be instantly +notified via a HTTP request about any cheat sheets changes. For that, please +open an issue on the cheat.sh project repository [github.com/chubin/cheat.sh] +with the ENTRY-POINT from the URL https://ENTRY-POINT/:actualize specified +EOF +} + +chtsh_mode() +{ + local mode="$1" + + local text; text=$( + echo " auto use the standalone installation first" + echo " lite use the cheat sheets server directly" + ) + + if [ -z "$mode" ]; then + echo "current mode: $CHTSH_MODE ($(printf "%s" "$text" | grep "$CHTSH_MODE" | sed "s/$CHTSH_MODE//; s/^ *//; s/ \+/ /"))" + if [ -d "$CHEATSH_INSTALLATION" ]; then + echo "cheat.sh standalone installation: $CHEATSH_INSTALLATION" + else + echo 'cheat.sh standalone installation not found; falling back to the "lite" mode' + fi + elif [ "$mode" = auto ] || [ "$mode" = lite ]; then + if [ "$mode" = "$CHTSH_MODE" ]; then + echo "The configured mode was \"$CHTSH_MODE\"; nothing changed" + else + mkdir -p "$CHTSH_HOME" + echo "$mode" > "$CHTSH_HOME/mode" + echo "Configured mode: $mode" + fi + else + echo "Uknown mode: $mode" + echo Suported modes: + echo " auto use the standalone installation first" + echo " lite use the cheat sheets server directly" + fi +} + +get_query_options() +{ + local query="$*" + if [ -n "$CHTSH_QUERY_OPTIONS" ]; then + case $query in + *\?*) query="$query&${CHTSH_QUERY_OPTIONS}";; + *) query="$query?${CHTSH_QUERY_OPTIONS}";; + esac + fi + printf "%s" "$query" +} + +do_query() +{ + local query="$*" + local b_opts= + local uri="${CHTSH_URL}/\"\$(get_query_options $query)\"" + + if [ -e "$HOME/.cht.sh/id" ]; then + b_opts="-b \"\$HOME/.cht.sh/id\"" + fi + + eval curl "$b_opts" -s "$uri" > "$TMP1" + + if [ -z "$lines" ] || [ "$(wc -l "$TMP1" | awk '{print $1}')" -lt "$lines" ]; then + cat "$TMP1" + else + ${PAGER:-$defpager} "$TMP1" + fi +} + +prepare_query() +{ + local section="$1"; shift + local input="$1"; shift + local arguments="$1" + + local query + if [ -z "$section" ] || [ x"${input}" != x"${input#/}" ]; then + query=$(printf %s "$input" | sed 's@ @/@; s@ @+@g') + else + query=$(printf %s "$section/$input" | sed 's@ @+@g') + fi + + [ -n "$arguments" ] && arguments="?$arguments" + printf %s "$query$arguments" +} + +get_list_of_sections() +{ + curl -s "${CHTSH_URL}"/:list | grep -v '/.*/' | grep '/$' | xargs +} + +gen_random_str() +( + len=$1 + if command -v openssl >/dev/null; then + openssl rand -base64 $((len*3/4)) | awk -v ORS='' // + else + rdev=/dev/urandom + for d in /dev/{srandom,random,arandom}; do + test -r "$d" && rdev=$d + done + if command -v hexdump >/dev/null; then + hexdump -vn $((len/2)) -e '1/1 "%02X" 1 ""' "$rdev" + elif command -v xxd >/dev/null; then + xxd -l $((len/2)) -ps "$rdev" | awk -v ORS='' // + else + cd /tmp || { echo Cannot cd into /tmp >&2; exit 1; } + s= + # shellcheck disable=SC2000 + while [ "$(echo "$s" | wc -c)" -lt "$len" ]; do + s="$s$(mktemp -u XXXXXXXXXX)" + done + printf "%.${len}s" "$s" + fi + fi +) + +if [ "$CHTSH_MODE" = auto ] && [ -d "$CHEATSH_INSTALLATION" ]; then + curl() { + # ignoring all options + # currently the standalone.py does not support them anyway + local opt + while getopts "b:s" opt; do + : + done + shift $((OPTIND - 1)) + + local url; url="$1"; shift + PYTHONIOENCODING=UTF-8 "$CHEATSH_INSTALLATION/ve/bin/python" "$CHEATSH_INSTALLATION/lib/standalone.py" "${url#"$CHTSH_URL"}" "$@" + } +elif [ "$(uname -s)" = OpenBSD ] && [ -x /usr/bin/ftp ]; then + # any better test not involving either OS matching or actual query? + curl() { + local opt args="-o -" + while getopts "b:s" opt; do + case $opt in + b) args="$args -c $OPTARG";; + s) args="$args -M -V";; + *) echo "internal error: unsupported cURL option '$opt'" >&2; exit 1;; + esac + done + shift $((OPTIND - 1)) + /usr/bin/ftp "$args" "$@" + } +else + command -v curl >/dev/null || { echo 'DEPENDENCY: install "curl" to use cht.sh' >&2; exit 1; } + _CURL=$(command -v curl) + if [ x"$CHTSH_CURL_OPTIONS" != x ]; then + curl() { + $_CURL "${CHTSH_CURL_OPTIONS}" "$@" + } + fi +fi + +if [ "$1" = --read ]; then + read -r a || a="exit" + printf "%s\n" "$a" + exit 0 +elif [ x"$1" = x--help ] || [ -z "$1" ]; then + + n=${0##*/} + s=$(echo "$n" | sed "s/./ /"g) + + cat <<EOF +Usage: + + $n [OPTIONS|QUERY] + +Options: + + QUERY process QUERY and exit + + --help show this help + --shell [LANG] shell mode (open LANG if specified) + + --standalone-install [DIR|help] + install cheat.sh in the standalone mode + (by default, into ~/.cheat.sh/) + + --mode [auto|lite] set (or display) mode of operation + * auto - prefer the local installation + * lite - use the cheat sheet server + +EOF + exit 0 +elif [ x"$1" = x--shell ]; then + shell_mode=yes + shift +elif [ x"$1" = x--standalone-install ]; then + shift + cheatsh_standalone_install "$@" + exit "$?" +elif [ x"$1" = x--mode ]; then + shift + chtsh_mode "$@" + exit "$?" +fi + +prompt="cht.sh" +opts="" +input="" +for o; do + if [ x"$o" != x"${o#-}" ]; then + opts="${opts}${o#-}" + else + input="$input $o" + fi +done +query=$(echo "$input" | sed 's@ *$@@; s@^ *@@; s@ @/@; s@ @+@g') + +if [ "$shell_mode" != yes ]; then + curl -s "${CHTSH_URL}"/"$(get_query_options "$query")" + exit 0 +else + new_section="$1" + valid_sections=$(get_list_of_sections) + valid=no; for q in $valid_sections; do [ "$q" = "$new_section/" ] && { valid=yes; break; }; done + + if [ "$valid" = yes ]; then + section="$new_section" + # shellcheck disable=SC2001 + this_query="$(echo "$input" | sed 's@ *[^ ]* *@@')" + this_prompt="\033[0;32mcht.sh/$section>\033[0m " + else + this_query="$input" + this_prompt="\033[0;32mcht.sh>\033[0m " + fi + if [ -n "$this_query" ] && [ -z "$CHEATSH_RESTART" ]; then + printf "$this_prompt$this_query\n" + curl -s "${CHTSH_URL}"/"$(get_query_options "$query")" + fi +fi + +if [ "$is_macos" != yes ]; then + command -v xsel >/dev/null || echo 'DEPENDENCY: please install "xsel" for "copy"' >&2 +fi +command -v rlwrap >/dev/null || { echo 'DEPENDENCY: install "rlwrap" to use cht.sh in the shell mode' >&2; exit 1; } + +mkdir -p "$HOME/.cht.sh/" +lines=$(tput lines) + +if command -v less >/dev/null; then + defpager="less -R" +elif command -v more >/dev/null; then + defpager="more" +else + defpager="cat" +fi + +cmd_cd() { + if [ $# -eq 0 ]; then + section="" + else + new_section=$(echo "$input" | sed 's/cd *//; s@/*$@@; s@^/*@@') + if [ -z "$new_section" ] || [ ".." = "$new_section" ]; then + section="" + else + valid_sections=$(get_list_of_sections) + valid=no; for q in $valid_sections; do [ "$q" = "$new_section/" ] && { valid=yes; break; }; done + if [ "$valid" = no ]; then + echo "Invalid section: $new_section" + echo "Valid sections:" + echo "$valid_sections" \ + | xargs printf "%-10s\n" \ + | tr ' ' . \ + | xargs -n 10 \ + | sed 's/\./ /g; s/^/ /' + else + section="$new_section" + fi + fi + fi +} + +cmd_copy() { + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + elif [ -z "$input" ]; then + echo copy: Make at least one query first. + else + curl -s "${CHTSH_URL}"/"$(get_query_options "$query"?T)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -bi < "$TMP1" + else + pbcopy < "$TMP1" + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + fi +} + +cmd_ccopy() { + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + elif [ -z "$input" ]; then + echo copy: Make at least one query first. + else + curl -s "${CHTSH_URL}"/"$(get_query_options "$query"?TQ)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -bi < "$TMP1" + else + pbcopy < "$TMP1" + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + fi +} + +cmd_exit() { + exit 0 +} + +cmd_help() { + cat <<EOF +help - show this help +hush - do not show the 'help' string at start anymore +cd LANG - change the language context +copy - copy the last answer in the clipboard (aliases: yank, y, c) +ccopy - copy the last answer w/o comments (cut comments; aliases: cc, Y, C) +exit - exit the cheat shell (aliases: quit, ^D) +id [ID] - set/show an unique session id ("reset" to reset, "remove" to remove) +stealth - stealth mode (automatic queries for selected text) +update - self update (only if the scriptfile is writeable) +version - show current cht.sh version +/:help - service help +QUERY - space ceparated query staring (examples are below) + cht.sh> python zip list + cht.sh/python> zip list + cht.sh/go> /python zip list +EOF +} + +cmd_hush() { + mkdir -p "$HOME/.cht.sh/" && touch "$HOME/.cht.sh/.hushlogin" && echo "Initial 'use help' message was disabled" +} + +cmd_id() { + id_file="$HOME/.cht.sh/id" + + if [ id = "$input" ]; then + new_id="" + else + new_id=$(echo "$input" | sed 's/id *//; s/ *$//; s/ /+/g') + fi + if [ "$new_id" = remove ]; then + if [ -e "$id_file" ]; then + rm -f -- "$id_file" && echo "id is removed" + else + echo "id was not set, so you can't remove it" + fi + return + fi + if [ -n "$new_id" ] && [ reset != "$new_id" ] && [ "$(/bin/echo -n "$new_id" | wc -c)" -lt 16 ]; then + echo "ERROR: $new_id: Too short id. Minimal id length is 16. Use 'id reset' for a random id" + return + fi + if [ -z "$new_id" ]; then + # if new_id is not specified check if we have some id already + # if yes, just show it + # if not, generate a new id + if [ -e "$id_file" ]; then + awk '$6 == "id" {print $NF}' <"$id_file" | tail -n 1 + return + else + new_id=reset + fi + fi + if [ "$new_id" = reset ]; then + new_id=$(gen_random_str 12) + else + echo WARNING: if someone gueses your id, he can read your cht.sh search history + fi + if [ -e "$id_file" ] && grep -q '\tid\t[^\t][^\t]*$' "$id_file" 2> /dev/null; then + sed -i 's/\tid\t[^\t][^\t]*$/ id '"$new_id"'/' "$id_file" + else + if ! [ -e "$id_file" ]; then + printf '#\n\n' > "$id_file" + fi + printf ".cht.sh\tTRUE\t/\tTRUE\t0\tid\t$new_id\n" >> "$id_file" + fi + echo "$new_id" +} + +cmd_query() { + query=$(prepare_query "$section" "$input") + do_query "$query" +} + +cmd_stealth() { + if [ "$input" != stealth ]; then + arguments=$(echo "$input" | sed 's/stealth //; s/ /\&/') + fi + trap break INT + if [ "$is_macos" = yes ]; then + past=$(pbpaste) + else + past=$(xsel -o) + fi + printf "\033[0;31mstealth:\033[0m you are in the stealth mode; select any text in any window for a query\n" + printf "\033[0;31mstealth:\033[0m selections longer than $STEALTH_MAX_SELECTION_LENGTH words are ignored\n" + if [ -n "$arguments" ]; then + printf "\033[0;31mstealth:\033[0m query arguments: ?$arguments\n" + fi + printf "\033[0;31mstealth:\033[0m use ^C to leave this mode\n" + while true; do + if [ "$is_macos" = yes ]; then + current=$(pbpaste) + else + current=$(xsel -o) + fi + if [ "$past" != "$current" ]; then + past=$current + current_text="$(echo $current | tr -c '[a-zA-Z0-9]' ' ')" + if [ "$(echo "$current_text" | wc -w)" -gt "$STEALTH_MAX_SELECTION_LENGTH" ]; then + echo "\033[0;31mstealth:\033[0m selection length is longer than $STEALTH_MAX_SELECTION_LENGTH words; ignoring" + continue + else + printf "\n\033[0;31mstealth: \033[7m $current_text\033[0m\n" + query=$(prepare_query "$section" "$current_text" "$arguments") + do_query "$query" + fi + fi + sleep 1; + done + trap - INT +} + +cmd_update() { + [ -w "$0" ] || { echo "The script is readonly; please update manually: curl -s ${CHTSH_URL}/:cht.sh | sudo tee $0"; return; } + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + curl -s "${CHTSH_URL}"/:cht.sh > "$TMP2" + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + if grep -q ^__CHTSH_VERSION= "$TMP2"; then + # section was vaildated by us already + args=(--shell "$section") + cp "$TMP2" "$0" && echo "Updated. Restarting..." && rm "$TMP2" && CHEATSH_RESTART=1 exec "$0" "${args[@]}" + else + echo "Something went wrong. Please update manually" + fi + else + echo "cht.sh is up to date. No update needed" + fi + rm -f "$TMP2" > /dev/null 2>&1 +} + +cmd_version() { + insttime=$(ls -l -- "$0" | sed 's/ */ /g' | cut -d ' ' -f 6-8) + echo "cht.sh version $__CHTSH_VERSION of $__CHTSH_DATETIME; installed at: $insttime" + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + if curl -s "${CHTSH_URL}"/:cht.sh > "$TMP2"; then + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + echo "Update needed (type 'update' for that)". + else + echo "Up to date. No update needed" + fi + fi + rm -f "$TMP2" > /dev/null 2>&1 +} + +TMP1=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) +trap 'rm -f $TMP1 $TMP2' EXIT +trap 'true' INT + +if ! [ -e "$HOME/.cht.sh/.hushlogin" ] && [ -z "$this_query" ]; then + echo "type 'help' for the cht.sh shell help" +fi + +while true; do + if [ "$section" != "" ]; then + full_prompt="$prompt/$section> " + else + full_prompt="$prompt> " + fi + + input=$( + rlwrap -H "$HOME/.cht.sh/history" -pgreen -C cht.sh -S "$full_prompt" bash "$0" --read | sed 's/ *#.*//' + ) + + cmd_name=${input%% *} + cmd_args=${input#* } + case $cmd_name in + "") continue;; # skip empty input lines + '?'|h|help) cmd_name=help;; + hush) cmd_name=hush;; + cd) cmd_name="cd";; + exit|quit) cmd_name="exit";; + copy|yank|c|y) cmd_name=copy;; + ccopy|cc|C|Y) cmd_name=ccopy;; + id) cmd_name=id;; + stealth) cmd_name=stealth;; + update) cmd_name=update;; + version) cmd_name=version;; + *) cmd_name="query"; cmd_args="$input";; + esac + "cmd_$cmd_name" $cmd_args +done diff --git a/clear.sh b/clear.sh @@ -0,0 +1 @@ +find . -maxdepth 1 -regextype gnu-awk -regex "^.*\.(pyc|p yo|bak|swp|aux|log|lof|nav|out|snm|toc|bcf|run\.xml|synctex\.gz|blg|bbl|fls|fdb_latexmk)" -delete diff --git a/colortest b/colortest @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +theme=$(dirname $0)/scripts/${1:-base16-default-dark.sh} +theme=/home/bakar/.config/base16-shell/scripts/base16-3024.sh +if [ -f $theme ]; then + # get the color declarations in said theme, assumes there is a block of text that starts with color00= and ends with new line + eval $(awk '/^color00=/,/^$/ {print}' $theme | sed 's/#.*//') +else + printf "No theme file %s found\n" $theme +fi; +ansi_mappings=( + Black + Red + Green + Yellow + Blue + Magenta + Cyan + White + Bright_Black + Bright_Red + Bright_Green + Bright_Yellow + Bright_Blue + Bright_Magenta + Bright_Cyan + Bright_White +) +colors=( + base00 + base08 + base0B + base0A + base0D + base0E + base0C + base05 + base03 + base08 + base0B + base0A + base0D + base0E + base0C + base07 + base09 + base0F + base01 + base02 + base04 + base06 +) +for padded_value in `seq -w 0 21`; do + color_variable="color${padded_value}" + eval current_color=\$${color_variable} + current_color=$(echo ${current_color//\//} | tr '[:lower:]' '[:upper:]') # get rid of slashes, and uppercase + non_padded_value=$((10#$padded_value)) + base16_color_name=${colors[$non_padded_value]} + current_color_label=${current_color:-unknown} + ansi_label=${ansi_mappings[$non_padded_value]} + block=$(printf "\x1b[48;5;${non_padded_value}m___________________________") + foreground=$(printf "\x1b[38;5;${non_padded_value}m$color_variable") + printf "%s %s %s %-30s %s\x1b[0m\n" $foreground $base16_color_name $current_color_label ${ansi_label:-""} $block +done; diff --git a/compiler b/compiler @@ -0,0 +1,17 @@ +#!/bin/bash + +# This is a compilation handler, so to speak, which I have vim run. +# +# It compiles a document to pdf + +file=$(basename "$1") +ext="${file##*.}" +base="${file%.*}" + +echo $ext + +case "$ext" in + rmd) echo "require(rmarkdown); render('$file')" | R --vanilla ;; + tex) xelatex "$file" ;; + md) pandoc "$file" --pdf-engine=xelatex -o "$base".pdf ;; +esac diff --git a/dmenuhandler b/dmenuhandler @@ -0,0 +1,24 @@ +#!/bin/bash +# Feed this script a link and it will give dmenu +# some choice programs to use to open it. + +# The URL will be shown visually in 30 characters or less. +if [[ "${#1}" -gt 30 ]]; +then +visual="${1:0:20}"..."${1: -7}" +else +visual="$1" +fi +echo $visual + +x=$(echo -e "mpv\nmpv (loop)\nwget\nfeh\nbrowser\nw3m\nmpv (float)\nqndl" | dmenu -i -p "How should I open '$visual'?") +case "$x" in + mpv) mpv -quiet "$1" 2&>/dev/null & disown ;; + "mpv (loop)") mpv -quiet --loop "$1" 2&>/dev/null & disown ;; + wget) wget "$1" 2&>/dev/null & disown ;; + browser) $BROWSER "$1" 2&>/dev/null & disown ;; + feh) feh "$1" 2&>/dev/null & disown ;; + w3m) w3m "$1" 2&>/dev/null & disown ;; + "mpv (float)") mpv --geometry=+0-0 --autofit=30% --title="mpvfloat" /dev/video0 "$1" 2&>/dev/null & disown ;; + qndl) qndl "$1" 'youtube-dl --add-metadata -ic' 2&>/dev/null & disown ;; +esac diff --git a/dmenumount b/dmenumount @@ -0,0 +1,27 @@ +#!/bin/sh + +# Should be run with sudo. + +# 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. + +pgrep -x dmenu && exit + +mountable=$(lsblk -lp | grep part | grep -v "t /" | awk '{print $1, "(" $4 ")"}') +[[ "$mountable" = "" ]] && exit 1 +chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}') +[[ "$chosen" = "" ]] && exit 1 +mount "$chosen" && exit 0 +# You may want to change the line below for more suggestions for mounting. +# I.e. you can increase the depth of the search, or add directories. +# This will increase the load time briefly though. +dirs=$(find /mnt /media /mount /home -type d -maxdepth 5 2>/dev/null) +mountpoint=$(echo "$dirs" | dmenu -i -p "Type in mount point.") +[[ "$mountpoint" = "" ]] && exit 1 +if [[ ! -d "$mountpoint" ]]; then + mkdiryn=$(echo -e "No\nYes" | dmenu -i -p "$mountpoint does not exist. Create it?") + [[ "$mkdiryn" = Yes ]] && sudo mkdir -p "$mountpoint" +fi +sudo mount "$chosen" "$mountpoint" -o uid=$UID,gid=$GROUPS diff --git a/dmenurecord b/dmenurecord @@ -0,0 +1,24 @@ +#!/bin/bash + +# A dmenu recording prompt for my different recording scripts. + +# Asks for type of recording and uses one of my three different scripts. +asktype() { \ +case $(echo -e "Screencast\nVideo only\nAudio only" | dmenu -i -p "Select recording style:") in + Screencast) screencast ;; + "Audio only") audio ;; + "Video only") video ;; +esac ;} + +# If already running, will ask to end previous recording. + +asktoend() { \ +response=$(echo -e "No\nYes" | dmenu -i -p "Recording still active. End recording?") && +if [[ "$response" = "Yes" ]]; then killall ffmpeg; fi ;} + +if (( $(pgrep dmenurecord | wc -l) > 2 )); then +asktoend; +else +asktype; +fi +echo $response diff --git a/dmenuumount b/dmenuumount @@ -0,0 +1,15 @@ +#!/bin/sh + +# A dmenu prompt to unmount drives. +# Provides you with mounted partitions, select one to unmount. + +# Drives mounted at /, /boot and /home will not be options to unmount. +# This can be changed by modifying $exclusionregex. + +exclusionregex="\(/boot\|/home\|/\)$" +drives=$(lsblk -lp | grep "t /" | grep -v "$exclusionregex" | awk '{print $1, "(" $4 ")", "on", $7}') +[[ "$drives" = "" ]] && test=$(echo "" | dmenu -i -p "Nothing is mounted...") +[[ "$drives" = "" ]] && exit +chosen=$(echo "$drives" | dmenu -i -p "Unmount which drive?" | awk '{print $1}') +[[ "$chosen" = "" ]] && exit +sudo umount $chosen diff --git a/dropdowncalc b/dropdowncalc @@ -0,0 +1,5 @@ +#!/bin/sh +# This script ensures that i3 will spawn a calculator. +# If R is installed, it will run R, otherwise it will run +# Python. +([[ -e /usr/bin/R ]] && R -q) || python -q diff --git a/dwm_mutt b/dwm_mutt @@ -0,0 +1,2 @@ +#!/bin/sh +st sh -c "tty>/tmp/tty; export GPG_TTY=$(</tmp/tty); neomutt" diff --git a/extract~ b/extract~ @@ -0,0 +1,30 @@ +#!/bin/bash +# there are two different ways this script can work. +# for the first way, uncomment the two lines after the if and place two '.' in front of the /$1 +# this creates a new directory in the directory where the compressed file is and dumps the content in it +# for the second way, comment the two lines under the if and place just one '.' in front of the /$1 +# this just dumps the content of the compressed file in the same directory of the compressed file +if [ -f "$1" ] ; then + NAME="${1%.*}" + mkdir "$NAME" && cd "$NAME" + case "$1" in + *.tar.bz2) tar xvjf ../"$1" ;; + *.tar.gz) tar xvzf ../"$1" ;; + *.tar.xz) tar xvJf ../"$1" ;; + *.lzma) unlzma ../"$1" ;; + *.bz2) bunzip2 ../"$1" ;; + *.rar) unrar x -ad ../"$1" ;; + *.gz) gunzip ../"$1" ;; + *.tar) tar xvf ../"$1" ;; + *.tbz2) tar xvjf ../"$1" ;; + *.tgz) tar xvzf ../"$1" ;; + *.zip) unzip ../"$1" ;; + *.Z) uncompress ../"$1" ;; + *.7z) 7z x ../"$1" ;; + *.xz) unxz ../"$1" ;; + *.exe) cabextract ../"$1" ;; + *) echo "extract: '$1' - unknown archive method" ;; + esac +else +echo "$1 - file does not exist" + fi diff --git a/flashScreen b/flashScreen @@ -0,0 +1,171 @@ +#!/bin/bash + +# NAME: flash-primary-screen.sh +# PATH: ~/bin +# DESC: Flashes primary screen colours to alert timer has ended. +# DATE: November 15, 2018 + +# NOTE: Written for: https://askubuntu.com/a/1092835/307523 +# I'm looking for a command to flash screens (if possible in colors) + +# Change 6 variables below to control screen flashing levels +MaxBright="1.5" +MinBright=".5" +MaxRed="2.0" +MaxGreen="2.0" +MaxBlue="2.0" +MinGamma=".5" + +declare aXrandr=() + +# Next two functions lifted from: eyesome internet sunrise/sunset time screen +# brightness and gamma controller: https://github.com/WinEunuuchs2Unix/eyesome + +InitXrandrArray () { + + # Array is used for each monitor and searched by name. + # Save time to search on connected/disconnected, primary monitor, + # brightness level, gamma level. + + mapfile -t aXrandr < <(xrandr --verbose --current) + +} # InitXrandrArray + +SearchXrandrArray () { + + # Parms: $MonXrandrName = xrandr monitor name to search for. + + # NOTE: Entries in array follow predicatble order from xrandr --verbose: + + # <MONITOR-NAME> connected / disconnected (line 1 of monitor entry) + # Gamma: 0.99:0.99:0.99 (line 5 of entry) + # Brightness: 0.99 (line 6 of entry) + # CRTC: 9 (line 8 of entry) + + fNameFnd=false + fBrightnessFnd=false + fGammaFnd=false + fCrtcFnd=false + XrandrConnection=disconnected + XrandrPrimary=false + XrandrGamma="" + XrandrBrightness="" + XrandrCRTC="" # Laptop lid open value=0, lid closed=blank + + for (( i=0; i<"${#aXrandr[*]}"; i++ )) ; do + + line="${aXrandr[$i]}" + # Have we looped to next monitor and not found search string? + if [[ "$line" =~ " connected " ]] && [[ $fNameFnd == true ]] ; then + break + fi + + if [[ "$line" =~ ^"$MonXrandrName connected" ]]; then + fNameFnd=true + XrandrConnection=connected + [[ "$line" =~ "primary" ]] && XrandrPrimary=true + fi + + if [[ $fNameFnd == true ]] && [[ $fGammaFnd == false ]] ; then + if [[ "$line" =~ "Gamma: " ]]; then + fGammaFnd=true + XrandrGamma="${line##* }" + # TODO: Use `xgamma` for accuracy + fi + fi + + if [[ $fGammaFnd == true ]] && [[ $fBrightnessFnd == false ]] ; then + if [[ "$line" =~ "Brightness: " ]]; then + fBrightnessFnd=true + XrandrBrightness="${line##* }" + fi + fi + + if [[ $fBrightnessFnd == true ]] && [[ $fCrtcFnd == false ]] ; then + if [[ "$line" =~ "CRTC: " ]]; then + fCrtcFnd=true + XrandrCRTC="${line##* }" + break + fi + fi + + done + +} # SearchXrandrArray + +FlipBright () { + + if [[ $NewBrightness == "$MaxBright" ]] ; then + NewBrightness="$MinBright" + else + NewBrightness="$MaxBright" + fi + +} # FlipBright + +CleanUp() { + + xrandr --output "$MonXrandrName" --gamma "$SaveGamma" \ + --brightness "$SaveBrightness" + + # Compensate for bug in Xrandr as of Nov 15, 2018 with second call + InitXrandrArray + SearchXrandrArray + xrandr --output "$MonXrandrName" --gamma "$XrandrGamma" + exit 0 + +} # CleanUp + +Main () { + + trap CleanUp INT TERM + + # Get primary monitor current settings + XrandrName=$(xrandr --current | grep primary) + MonXrandrName="${XrandrName%% *}" + InitXrandrArray + SearchXrandrArray + + # Did we find primary monitor ok? + if [[ $fBrightnessFnd == false ]] || [[ $fGammaFnd == false ]] ; then + echo "Internal Error: Could not find Primary Screen brightness or gamma" + echo XrandrPrimary: "$XrandrPrimary" + echo aXrandr[0]: "${aXrandr[0]}" + echo Brightness: "$XrandrBrightness" + echo Gamma: "$XrandrGamma" + exit 2 + fi + + # Restore these values when CleanUping program + SaveBrightness="$XrandrBrightness" + SaveGamma="$XrandrGamma" + + #Blink for 10 seconds + end=$((SECONDS+10)) + while [ $SECONDS -lt $end ]; do + if [[ $Red == true ]] ; then + Red=false + Green=true + NewGamma="$MaxRed:$MinGamma:$MinGamma" + FlipBright + elif [[ $Green == true ]] ; then + Green=false + NewGamma="$MinGamma:$MaxGreen:$MinGamma" + FlipBright + else + Red=true + NewGamma="$MinGamma:$MinGamma:$MaxBlue" + FlipBright + fi + + xrandr --output "$MonXrandrName" --gamma "$NewGamma" \ + --brightness "$NewBrightness" + + sleep .2 + + done +CleanUp + +} # Main + +Main "$@" diff --git a/layout b/layout @@ -0,0 +1,4 @@ +#!/bin/bash + +#Language layout switch +setxkbmap -layout us,ge -option grp:alt_space_toggle diff --git a/linkhandler b/linkhandler @@ -0,0 +1,58 @@ +#!/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. +BROWSER="qutebrowser" +[ -z "$1" ] && { "$BROWSER"; exit; } + +case "$1" in + *youtube.com/watch*|*youtube.com/playlist*|*youtu.be*|*youtube.com/embed/*) + dmenuhandler "$1" >/dev/null 2>&1 ;; + *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtu.be*|*youtube.com/embed/*|*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|*ogg|*flac|*opus|*mp3?*|*ogg?*) + qndl "$1" 'curl -LO' >/dev/null 2>&1 ;; + #setsid -f mpv -quiet "$1" >/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 + +#!/bin/bash + +# Feed script a url. +# If an image, it will view in feh, +# 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. + +# List of sites that will be opened in mpv. +#vidsites="youtube.com + #\|hooktube.com + #\|bitchute.com + #" +#ext="${1##*.}" +#mpvFiles="mkv mp4 gif webm" +#fehFiles="png jpg jpeg jpe" +#wgetFiles="mp3 flac opus mp3?source=feed pdf" +#BROWSER="qutebrowser" + +#if echo $fehFiles | grep -w $ext > /dev/null; then + #feh "$1" >/dev/null & disown +#elif echo $mpvFiles | grep -w $ext > /dev/null; then + #mpv -quiet "$1" > /dev/null & disown +#elif echo $wgetFiles | grep -w $ext > /dev/null; then + #wget "$1" >/dev/null & disown +#elif echo "$@" | grep "$vidsites">/dev/null; then + #mpv -quiet "$1" > /dev/null & disown +#else + #$BROWSER "$1" 2>/dev/null & disown +#fi diff --git a/mic_status.sh b/mic_status.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +micstatus=$(amixer sget Capture | awk '{if(/\[on\]/) {print "ON"; exit}}') + +if [ "$micstatus" = ON ]; then + echo "🗣️🎙" + #echo -e "\033[32m🎙\033[0m" +else + #echo -e "\033[31;9;5m🎙\033[0m" + echo "⛔🎙" +fi diff --git a/notmuch-address b/notmuch-address @@ -0,0 +1,15 @@ +#!/bin/sh +(parallel notmuch address {} "\*'$1'\*" ::: \ + '--output=sender' '--output=recipients') | \ + grep -Pi "$1" | \ + awk ' +/@/ { + s=$NF; + sub(/^</, "", s); + sub(/>$/, "", s); + printf("%s\t", s); + for (i = 1; i < NF; i++) + printf("%s ", $i); + printf("\n") +} +' | sort -u -k 1,1 | uniq -c | sort -nr | cut -c9- | awk 'BEGIN{print}{print $0}' diff --git a/offlineimap-daemon.py b/offlineimap-daemon.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +import subprocess +import signal +import threading +import sys + +import dbus +from dbus.mainloop.glib import DBusGMainLoop +from gi.repository import GLib + + +class OfflineimapCtl(object): + def __init__(self): + self.daemon_proc = None + self.run_ev = threading.Event() + self.run_daemon = False + + def run(self): + t = threading.Thread(target=self._watch_daemon, daemon=True) + t.start() + + def _watch_daemon(self): + while True: + self.run_ev.wait() + self.run_ev.clear() + if self.run_daemon: + self.is_running = True + print('offlineimap is being started') + self._spawn_daemon() + print('offlineimap has stopped') + self.run_ev.set() # check state and restart if needed + + def _spawn_daemon(self): + self.daemon_proc = subprocess.Popen(['offlineimap', '-u', 'basic'], shell=False) + self.daemon_proc.wait() + self.daemon_proc = None + + def start(self): + print('starting offlineimap') + self.run_daemon = True + self.run_ev.set() + + def stop(self): + print('stopping offlineimap') + self.run_daemon = False + if self.daemon_proc: + try: + self.daemon_proc.send_signal(signal.SIGUSR2) + except OSError: + print('Unable to stop offlineimap') + + def restart(self): + print('restarting offlineimap') + if self.run_daemon: + self.stop() + self.start() + + def onConnectivityChanged(self, state): + # 70 means fully connected + if state == 70: + self.start() + else: + self.stop() + +def main(): + oi_ctl = OfflineimapCtl() + oi_ctl.run() + + try: + bus = dbus.SystemBus(mainloop=DBusGMainLoop()) + network_manager = bus.get_object( + 'org.freedesktop.NetworkManager', + '/org/freedesktop/NetworkManager') + network = dbus.Interface(network_manager, + dbus_interface='org.freedesktop.NetworkManager') + + network.connect_to_signal('StateChanged', oi_ctl.onConnectivityChanged) + + # send current state as first event + state = network.state() + oi_ctl.onConnectivityChanged(state) + + except dbus.exceptions.DBusException: + print('Unable to connect to dbus') + sys.exit(3) + + # start receiving events from dbus + loop = GLib.MainLoop() + loop.run() + +if __name__ == '__main__': + main() diff --git a/offlineimap-daemonctl.sh b/offlineimap-daemonctl.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# this script runs offline imap as daemon (configured to check periodically) + +LOG=~/.offlineimap/sync.log +PIDFILE=~/.offlineimap/pid + +# if not present on PATH, those vars must point to proper locations +THIS_SCRIPT=offlineimap-daemonctl.sh +PYTHON_DAEMON=offlineimap-daemon.py + +daemon(){ + $PYTHON_DAEMON 2>&1 | + # add timestamps to logs + (while read line; do + echo `date` "$line" >> $LOG + done) +} + +stop(){ + kill -USR2 `cat $PIDFILE` +} + +refresh(){ + kill -USR1 `cat $PIDFILE` +} + +case "$1" in + '--daemon' | '-d' ) + nohup $THIS_SCRIPT < /dev/null > /dev/null 2>&1 & + ;; + '--kill' | '-k' ) + stop + ;; + '--refresh' | '-r' ) + refresh + ;; + * ) + daemon + ;; +esac +\ No newline at end of file diff --git a/pdfrange b/pdfrange @@ -0,0 +1,12 @@ +#!/bin/sh +# this function uses 3 arguments: +# $1 is the first page of the range to extract +# $2 is the last page of the range to extract +# $3 is the input file +# output file will be named "inputfile_pXX-pYY.pdf" +gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER \ + -dFirstPage="${1}" \ + -dLastPage="${2}" \ + -sOutputFile="print.pdf" \ + "${3}" +#-sOutputFile="${3%.pdf}_p${1}-p${2}.pdf" \ diff --git a/print_desy b/print_desy @@ -0,0 +1,13 @@ +#!/bin/sh +echo "$0"; +echo "$1"; +echo "$2"; +echo "$3"; + +sshpass -p $(pass bchargei@bastion.desy.de) rsync -avP "$1" bchargei@bastion.desy.de:/afs/desy.de/user/b/bchargei/Print/ + +sshpass -p $(pass bchargei@bastion.desy.de) ssh bchargei@bastion.desy.de -XYC \ + ssh pal<<EOF +cd /afs/desy.de/user/b/bchargei/Print/ +lpr -H cups-hep -P t00ps$2 -o sides=two-sided-long-edge "$(basename "$1")" +EOF diff --git a/prompt b/prompt @@ -0,0 +1,8 @@ +#!/bin/sh +# A dmenu binary prompt script. +# Gives a dmenu prompt labeled with $1 to perform command $2. +# For example: +# `./prompt "Do you want to shutdown?" "shutdown -h now"` + +[ $(echo -e "No\nYes" | dmenu -i -p "$1" -nb darkred -sb red -sf white -nf gray -fn mono) \ +== "Yes" ] && $2 diff --git a/qndl b/qndl @@ -0,0 +1,12 @@ +#!/bin/sh + +# $1 is a url; $2 is a command +[ -z "$1" ] && exit +base="$(basename "$1")" +notify-send "⏳ Queuing $base..." +cmd="$2" +[ -z "$cmd" ] && cmd="youtube-dl --add-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/record b/record @@ -0,0 +1,8 @@ +#!/bin/bash +# A dmenu recording prompt for my different + +case $(echo -e "Screencast\nVideo only\nAudio only" | dmenu -i -p "Select recording style:") in + Screencast) (pgrep -x pulseaudio && screencast_pulse.sh) || screencast_alsa.sh ;; + "Audio only") (pgrep -x pulseaudio && audio_pulse.sh) || audio_alsa.sh ;; + "Video only") video.sh ;; +esac diff --git a/sb-doppler b/sb-doppler @@ -0,0 +1,285 @@ +#!/bin/sh + +# Show a Doppler RADAR of a user's preferred location. + +secs=600 # Download a new doppler radar if one hasn't been downloaded in $secs seconds. +radarloc="${XDG_CACHE_HOME:-$HOME/.cache}/radar" +doppler="${XDG_CACHE_HOME:-$HOME/.cache}/doppler.gif" + +pickloc() { chosen="$(echo "US: CONUS: Continental United States +US: Northeast +US: Southeast +US: PacNorthWest +US: PacSouthWest +US: UpperMissVly +US: SouthMissVly +US: SouthPlains +US: NorthRockies +US: SouthRockies +US: Alaska +US: Carib +US: Hawaii +US: CentGrLakes +US: Conus-Large +US: KABR: Aberdeen, SD +US: KBIS: Bismarck, ND +US: KFTG: Denver/Boulder, CO +US: KDMX: Des Moines, IA +US: KDTX: Detroit, MI +US: KDDC: Dodge City, KS +US: KDLH: Duluth, MN +US: KCYS: Cheyenne, WY +US: KLOT: Chicago, IL +US: KGLD: Goodland, KS +US: KUEX: Hastings, NE +US: KGJX: Grand Junction, CO +US: KGRR: Grand Rapids, MI +US: KMVX: Fargo/Grand Forks, ND +US: KGRB: Green Bay, WI +US: KIND: Indianapolis, IN +US: KJKL: Jackson, KY +US: KARX: La Crosse, WI +US: KILX: Lincoln/Central Illinois, IL +US: KLVX: Louisville, KY +US: KMQT: Marquette +US: KMKX: Milwaukee, WI +US: KMPX: Minneapolis, MN +US: KAPX: Gaylord/Alpena, MI +US: KLNX: North Platte, NE +US: KIWX: N. Webster/Northern, IN +US: KOAX: Omaha, NE +US: KPAH: Paducah, KY +US: KEAX: Pleasant Hill, MO +US: KPUX: Pueblo, CO +US: KDVN: Quad Cities, IA +US: KUDX: Rapid City, SD +US: KRIW: Riverton, WY +US: KSGF: Springfield, MO +US: KLSX: St. LOUIS, MO +US: KFSD: Sioux Falls, SD +US: KTWX: Topeka, KS +US: KICT: Wichita, KS +US: KVWX: Paducah, KY +US: ICAO: Responsible Wfo +US: KLTX: WILMINGTON, NC +US: KCCX: State College/Central, PA +US: KLWX: Sterling, VA +US: KFCX: Blacksburg/Roanoke, VA +US: KRAX: Raleigh/Durham, NC +US: KGYX: Portland, ME +US: KDIX: Mt Holly/Philadelphia, PA +US: KPBZ: Pittsburgh, PA +US: KAKQ: Wakefield, VA +US: KMHX: Morehead City, NC +US: KGSP: Greer/Greenville/Sprtbg, SC +US: KILN: Wilmington/Cincinnati, OH +US: KCLE: Cleveland, OH +US: KCAE: Columbia, SC +US: KBGM: Binghamton, NY +US: KENX: Albany, NY +US: KBUF: Buffalo, NY +US: KCXX: Burlington, VT +US: KCBW: Caribou, ME +US: KBOX: Boston /Taunton, MA +US: KOKX: New York City, NY +US: KCLX: Charleston, SC +US: KRLX: Charleston, WV +US: ICAO: Responsible WFO +US: KBRO: Brownsville, TX +US: KABX: Albuquerque, NM +US: KAMA: Amarillo, TX +US: KFFC: Peachtree City/Atlanta, GA +US: KEWX: Austin/Sanantonio, TX +US: KBMX: Birmingham, AL +US: KCRP: Corpus Christi, TX +US: KFWS: Dallas / Ft. Worth, TX +US: KEPZ: El Paso, TX +US: KHGX: Houston/ Galveston, TX +US: KJAX: Jacksonville, FL +US: KBYX: Key West, FL +US: KMRX: Morristown/knoxville, TN +US: KLBB: Lubbock, TX +US: KLZK: Little Rock, AR +US: KLCH: Lake Charles, LA +US: KOHX: Nashville, TN +US: KMLB: Melbourne, FL +US: KNQA: Memphis, TN +US: KAMX: Miami, FL +US: KMAF: Midland/odessa, TX +US: KTLX: Norman, OK +US: KHTX: Huntsville, AL +US: KMOB: Mobile, AL +US: KTLH: Tallahassee, FL +US: KTBW: Tampa Bay Area, FL +US: KSJT: San Angelo, TX +US: KINX: Tulsa, OK +US: KSRX: Tulsa, OK +US: KLIX: New Orleans/slidell, LA +US: KDGX: Jackson, MS +US: KSHV: Shreveport, LA +US: ICAO: Responsible WFO +US: KLGX: Seattle / Tacoma, WA +US: KOTX: Spokane, WA +US: KEMX: Tucson, AZ +US: KYUX: Phoenix, AZ +US: KNKX: San Diego, CA +US: KMUX: Monterey/san Francisco, CA +US: KHNX: San Joaquin/hanford, CA +US: KSOX: San Diego, CA +US: KATX: Seattle / Tacoma, WA +US: KIWA: Phoenix, AZ +US: KRTX: Portland, OR +US: KSFX: Pocatello, ID +US: KRGX: Reno, NV +US: KDAX: Sacramento, CA +US: KMTX: Salt Lake City, UT +US: KPDT: Pendleton, OR +US: KMSX: Missoula, MT +US: KESX: Las Vegas, NV +US: KVTX: Los Angeles, CA +US: KMAX: Medford, OR +US: KFSX: Flagstaff, AZ +US: KGGW: Glasgow, MT +US: KLRX: Elko, NV +US: KBHX: Eureka, CA +US: KTFX: Great Falls, MT +US: KCBX: Boise, ID +US: KBLX: Billings, MT +US: KICX: Salt Lake City, UT +US: ICAO: Responsible Wfo W/ MSCF +US: PABC: Anchorage, AK +US: PAPD: Fairbanks, AK +US: PHKM: Honolulu, HI +US: PAHG: Anchorage, AK +US: PAKC: Anchorage, AK +US: PAIH: Anchorage, AK +US: PHMO: Honolulu, HI +US: PAEC: Fairbanks, AK +US: TJUA: San Juan, PR +US: PACG: Juneau, AK +US: PHKI: Honolulu, HI +US: PHWA: Honolulu, HI +US: ICAO: Responsible Wfo W/ MSCF +US: KFDR: Norman, OK +US: PGUA: Guam +US: KBBX: Sacramento, CA +US: KFDX: Albuquerque, NM +US: KGWX: Jackson, MS +US: KDOX: Wakefield, VA +US: KDYX: San Angelo, TX +US: KEYX: Las Vegas, NV +US: KEVX: Mobile, AL +US: KHPX: Paducah, KY +US: KTYX: Burlington, VT +US: KGRK: Dallas / Ft. Worth, TX +US: KPOE: Lake Charles, LA +US: KEOX: Tallahassee, FL +US: KHDX: El Paso, TX +US: KDFX: San Antonio, TX +US: KMXX: Birmingham, AL +US: KMBX: Bismarck, ND +US: KVAX: Jacksonville, FL +US: KJGX: Peachtree City/atlanta, GA +US: KVNX: Norman, OK +US: KVBX: Vandenberg Afb: Orcutt, CA +EU: Europe +EU: GB: Great Brittain +EU: SCAN: Scandinavia. Norway, Sweden And Denmark +EU: ALPS: The Alps +EU: NL: The Netherlands +EU: DE: Germany +EU: SP: Spain +EU: FR: France +EU: IT: Italy +EU: PL: Poland +EU: GR: Greece +EU: TU: Turkey +EU: RU: Russia +EU: BA: Bahrain +EU: BC: Botswana +EU: SE: Republic of Seychelles +EU: HU: Hungary +EU: UK: Ukraine +AF: AF: Africa +AF: WA: West Africa +AF: ZA: South Africa +AF: DZ: Algeria +AF: CE: Canary Islands +AF: NG: Nigeria +AF: TD: Chad +AF: CG: Democratic Republic of Congo +AF: EG: Egypt +AF: ET: Ethiopia +AF: CM: Cameroon +AF: IS: Israel +AF: LY: Libya +AF: MG: Madagascar +AF: MO: Morocco +AF: BW: Namibia +AF: SA: Saudi Arabia +AF: SO: Somalia +AF: SD: Sudan +AF: TZ: Tanzania +AF: TN: Tunisia +AF: ZM: Zambia +AF: KE: Kenya +AF: AO: Angola +DE: BAW: Baden-Württemberg +DE: BAY: Bavaria +DE: BBB: Berlin +DE: BBB: Brandenburg +DE: HES: Hesse +DE: MVP: Mecklenburg-Western Pomerania +DE: NIB: Lower Saxony +DE: NIB: Bremen +DE: NRW: North Rhine-Westphalia +DE: RPS: Rhineland-Palatinate +DE: RPS: Saarland +DE: SAC: Saxony +DE: SAA: Saxony-Anhalt +DE: SHH: Schleswig-Holstein +DE: SHH: Hamburg +DE: THU: Thuringia" | dmenu -i -l 50 -p "Select a radar to use as default:" | tr "[:lower:]" "[:upper:]")" + +# Ensure user did not escape. +[ -z "$chosen" ] && exit 1 + +# Set continent code and radar code. +continentcode=${chosen%%:*} +radarcode=${chosen#* } radarcode=${radarcode%:*} + +# Print codes to $radarloc file. + printf "%s,%s\\n" "$continentcode" "$radarcode" > "$radarloc" ;} + +getdoppler() { + cont=$(cut -c -2 "$radarloc") + loc=$(cut -c 4- "$radarloc") + notify-send "🌦️ Doppler RADAR" "Pulling most recent Doppler RADAR for $loc." + case "$cont" in + "US") curl -sL "https://radar.weather.gov/ridge/standard/${loc}_loop.gif" > "$doppler" ;; + "EU") curl -sL "https://api.sat24.com/animated/${loc}/rainTMC/2/" > "$doppler" ;; + "AF") curl -sL "https://api.sat24.com/animated/${loc}/rain/2/" > "$doppler" ;; + "DE") loc="$(echo "$loc" | tr "[:upper:]" "[:lower:]")" + curl -sL "https://www.dwd.de/DWD/wetter/radar/radfilm_${loc}_akt.gif" > "$doppler" ;; + esac +} + +showdoppler() { setsid -f mpv --no-osc --loop=inf --no-terminal "$doppler" ;} + +case $BLOCK_BUTTON in + 1) [ ! -f "$radarloc" ] && pickloc && getdoppler + [ $(($(date '+%s') - $(stat -c %Y "$doppler"))) -gt "$secs" ] && getdoppler + showdoppler ;; + 2) pickloc && getdoppler && showdoppler ;; + 3) notify-send "🗺️ Doppler RADAR module" "\- Left click for local Doppler RADAR. +- Middle click to update RADAR location. +After $secs seconds, new clicks will also automatically update the doppler RADAR." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac +#[ ! -f "$radarloc" ] && pickloc && getdoppler +#[ ! -f "$radarloc" ] && pickloc && getdoppler +getdoppler +[ $(($(date '+%s') - $(stat -c %Y "$doppler"))) -gt "$secs" ] && getdoppler +showdoppler + +echo 🌅 diff --git a/screen.sh b/screen.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +#Feed this script either: +# "l" for laptop screen only, +# "v" for vga screen only, +# or "d" for dual vga/laptop. + +d() { if [[ $(xrandr -q | grep VGA1\ con) ]] + then param $1 + else echo "No VGA input detected." + fi ;} +dual() { xrandr --output LVDS1 --auto --output VGA1 --auto --right-of LVDS1 ;} +laptop() { xrandr --output LVDS1 --auto --output VGA1 --off ;} +vga() { xrandr --output VGA1 --auto --output LVDS1 --off ;} +#mirror() { xrandr --addmode VGA1 $lapres && xrandr --output LVDS1 --mode $lapres --output VGA1 --mode $lapres ;} + +param() { +case $1 in + d) dual ;; + v) vga ;; + l) laptop ;; + *) echo -e "Invalid parameter. Add one of the following:\n\"d\" for dualscreen laptop and VGA.\n\"l\" for laptop only\n\"v\" for VGA only." ;; +esac ;} +d $1 diff --git a/screencast b/screencast @@ -0,0 +1,36 @@ +#!/bin/bash + +# This script records a screencast with audio and video. +# It runs an appropriate record script for either ALSA and Pulseaudio. +# It also names files smartly to prevent overwrites. + +# Picks a file name for the output file based on availability: +while [[ -f $HOME/screencast$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/screencast$n.mkv" + +# For Pulseaudio with ALSA: +record_pulse() { \ +ffmpeg -y \ +-f x11grab \ +-framerate 60 \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ +-f alsa -i default \ +-r 30 \ + -c:v libx264rgb -crf 0 -preset ultrafast -c:a flac $filename ;} + +# For ALSA: +record_alsa() { \ +ffmpeg -y \ +-f x11grab \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ +-thread_queue_size 1024 \ + -f alsa -ar 44100 -i hw:1 \ + -c:v libx264 -r 30 -c:a flac $filename ;} + + +if [[ $(pgrep -x pulseaudio) ]]; then record_pulse; else record_alsa; fi diff --git a/screencast_alsa.sh b/screencast_alsa.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +#This is the ffmpeg command that the screencast shortcut in i3 will run. + +#Picks a file name for the output file based on availability: + +while [[ -f $HOME/screencast$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/screencast$n.mkv" + +#The actual ffmpeg command: + +ffmpeg -y \ +-f x11grab \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ +-thread_queue_size 1024 \ + -f alsa -ar 44100 -i hw:1 \ + -c:v libx264 -r 30 -c:a flac $filename + #-c:v ffvhuff -r 30 -c:a flac $filename diff --git a/screencast_lecture.sh b/screencast_lecture.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +#This is the ffmpeg command that the screencast shortcut in i3 will run. + +#Picks a file name for the output file based on availability: + +while [[ -f $HOME/screencast$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/screencast$n.mkv" + +#The actual ffmpeg command: + +ffmpeg -y \ +-f x11grab \ +-framerate 60 \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ +-thread_queue_size 2048 \ +-f pulse -i alsa_output.pci-0000_00_1f.3.analog-stereo.monitor \ +-r 30 \ + -c:v libx264 -crf 20 -c:a flac $filename + #-c:v ffvhuff -r 30 -c:a flac $filename + #-f pulse -ac 1 -ar 44100 -i default \ diff --git a/screencast_pulse.sh b/screencast_pulse.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +#This is the ffmpeg command that the screencast shortcut in i3 will run. + +#Picks a file name for the output file based on availability: + +while [[ -f $HOME/screencast$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/screencast$n.mkv" + +#The actual ffmpeg command: + +ffmpeg -y \ +-f x11grab \ +-framerate 60 \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ +-thread_queue_size 2048 \ +-f pulse -i logitechsource \ +-f pulse -i alsa_output.pci-0000_00_1f.3.analog-stereo.monitor \ +-filter_complex "[2:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume=0.8[l];[1:a][l]amerge=inputs=2[a]" -map 0 -map "[a]" \ +-r 30 \ + -c:v libx264 -r 30 -c:a flac $filename + #-c:v ffvhuff -r 30 -c:a flac $filename + #-f pulse -ac 1 -ar 44100 -i default \ diff --git a/speedvid.sh b/speedvid.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +base=$(basename $1) +ext="${base##*.}" +base="${base%.*}" + +ffmpeg -i $1 -vf "setpts=$2*PTS" -an $base'_sped.'$ext diff --git a/start-tmux.sh b/start-tmux.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# if not inside tmux, then start it. + +tmux -2 +#if [ -z "$TMUX" ]; then + #tmux attach || exec tmux new-session +#else + #echo "already in tmux!" +#fi diff --git a/startdwm b/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/tmuxinit b/tmuxinit @@ -0,0 +1,4 @@ +#!/bin/bash +# This is the script that i3 runs to either start tmux in +# the dropdown terminal or log into a previous session. +tmux a -t scratch || tmux new -s scratch diff --git a/transmission.sh b/transmission.sh @@ -0,0 +1,7 @@ +#!/bin/bash +if [ -f $(pgrep transmission) ]; + then + st -e transmission-remote-cli + else + transmission-daemon && st -e transmission-remote-cli +fi diff --git a/video b/video @@ -0,0 +1,18 @@ +#!/bin/bash + +# This script records video. +# It also names files smartly to prevent overwrites. + +# Picks a file name for the output file based on availability: +while [[ -f $HOME/video$n.mkv ]] +do + n=$((n+1)) +done +filename="$HOME/video$n.mkv" + +# The actual ffmpeg command: +ffmpeg \ +-f x11grab \ +-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \ +-i :0.0 \ + -c:v libx264 -qp 0 -r 30 $filename