diff options
Diffstat (limited to 'bin/menuscripts')
| -rwxr-xr-x | bin/menuscripts/aumount | 97 | ||||
| -rwxr-xr-x | bin/menuscripts/commander | 261 | ||||
| -rwxr-xr-x | bin/menuscripts/ddl | 88 | ||||
| -rwxr-xr-x | bin/menuscripts/keyadd | 62 | ||||
| -rwxr-xr-x | bin/menuscripts/mmedia | 59 | ||||
| -rwxr-xr-x | bin/menuscripts/mpass | 27 | ||||
| -rwxr-xr-x | bin/menuscripts/mplay | 76 | ||||
| -rwxr-xr-x | bin/menuscripts/muzrname | 22 | ||||
| -rwxr-xr-x | bin/menuscripts/pomo | 78 | ||||
| -rwxr-xr-x | bin/menuscripts/shdul.sh | 157 | ||||
| -rwxr-xr-x | bin/menuscripts/td | 65 | ||||
| -rwxr-xr-x | bin/menuscripts/treetag.sh | 128 | ||||
| -rwxr-xr-x | bin/menuscripts/tsh | 208 | 
13 files changed, 1328 insertions, 0 deletions
diff --git a/bin/menuscripts/aumount b/bin/menuscripts/aumount new file mode 100755 index 0000000..8a2b785 --- /dev/null +++ b/bin/menuscripts/aumount @@ -0,0 +1,97 @@ +#!/bin/sh + +tmp="$(mktemp)" +test "$(id -u)" != "0" && sudo="sudo" + +logn () { >&2 printf "%s\n" "$@"; } +log () { >&2 printf '%s' "$@"; } + +# Read one character +read_char () +{ +	log ">" +	old_stty_cfg=$(stty -g) +	stty raw +	dd ibs=1 count=1 2> /dev/null +	stty "$old_stty_cfg" +	logn "" +} + +get_dev () { grep "^$1\." "$tmp" | cut -f 2- -d ' '; } + +# mount the device with $1 as the choice +mount () +{ +	dev="$(get_dev "$1")" +	test -z "$dev" && exit 1 + +	logn "Mounting /dev/$dev on /media/$dev" +	mkdir -p /media/"$dev" +	$sudo mount /dev/"$dev" /media/"$dev" > /dev/null 2>&1 || +		return 1 +} + +# umount the device with $1 as the choice +umount () +{ +	mountpoint="$(sed -n "${1}p" "$tmp" | awk '{print $3}')" +	test -z "$mountpoint" && exit 1 + +	logn "Unmounting $mountpoint" +	$sudo umount "$mountpoint" || +		return 1 +} + +ejekt () +{ +	dev="$(get_dev "$1" | sed 's/.$//')" +	test -z "$dev" && exit 1 + +	logn "Ejecting /dev/$dev" +	$sudo eject /dev/"$dev" > /dev/null 2>&1 || +		return 1 +} + +# print lsblk, use $1 to print only devices with mountpoints or without +pr_lsblk () +{ +	clear +	lsblk -o name,size,type,mountpoint +	logn "───────────────────────────────────" +	lsblk --ascii -o name,mountpoint | +		grep '^.-' | +		while read -r line +	do +		words="$(printf "%s" "$line" | wc -w)" +		test "$words" -eq "${1:-1}" && continue  +		printf "%s\n" "$line" +	done | +		cut -f 2- -d "-" | +		awk '{print NR ". " $0}' | +		tee "$tmp" >&2 +} + +cleanup () { rm -f "$tmp"; } + +trap cleanup EXIT INT + +logn "m(ount) u(mount) (e)ject ?" +choice="$(read_char)" + +case $choice in +	"m") i=2; cmd=mount ;; +	"u") i=1; cmd=umount ;; +	"e") i=2; cmd=ejekt ;; +	*) exit 1 ;; +esac + +pr_lsblk "$i" +choice="$(read_char)" +printf "%s" "$choice" | grep -q "[0-9]" || exit 1 + +if $cmd "$choice" +then +	logn "Successful." +else +	logn "Failed." +fi diff --git a/bin/menuscripts/commander b/bin/menuscripts/commander new file mode 100755 index 0000000..3f26429 --- /dev/null +++ b/bin/menuscripts/commander @@ -0,0 +1,261 @@ +#!/bin/sh + +# An attempt to unify usage of multiple launchers. +# MENUCMD must be set to the name of the lancher +# +# look at the last line to understand how it works + +### TODO +# instead of dynamic, provide a command to set width and height manually + +tmp="$(mktemp -u)" +export menuopts="" +TOFIRC="$HOME/.config/tofi/config" + +options=' +horizontal +height +center +input +instant +long +prompt +numbered +prefix +width' + +cleanup() { rm -f "$tmp"; } + +logn() { >&2 printf '%s\n' "$@"; } +die() { logn "$@"; exit 1; } + +help() { +	>&2 cat <<-EOF +	Usage: commander OPTIONS... + +	An attempt to regroup multiple launchers into one, +	it detects the value of the MENUCMD variable + +	try: +	MENUCMD=tofi commander < /etc/passwd + +	Options: +	  -h              Display items horizontally +	  -c              Display centered +	  -i              Take an input and return it to stdout +	  -p ARG          Prompt user with the specified argument +	  -l              Display in long list format +	  -n              Output the number of matches +	  -r              Select an executable from PATH +	  -1              Invert instant select on single match +	  -y ARG          Use specified height +	  -w ARG          Use specified width +	  -x              Invert prefix matching +	EOF +} + +add_option() { menuopts="$menuopts $*"; } +get_prop() { awk -F '=' "/$1 *=*/ {print \$2}" "$TOFIRC"; } + + +trap cleanup EXIT + +# Helper functions +case "$MENUCMD" in +	tofi) +		### Get a height based on a number of items +		# $1: max items count +		get_height() +		{ +			font_size="$(get_prop "font-size")" +			padding_top="$(get_prop "padding-top")" +			padding_bottom="$(get_prop "padding-bottom")" + +			printf "%s" "$(( +			font_size*2 + padding_top + padding_bottom + 2 + +			($1)*(font_size*2 - 2) +			))" + +		} +		### Get a width based on a maximum character length +		# $1: max character length +		get_width() +		{ +			font_size="$(get_prop "font-size")" +			padding_left="$(get_prop "padding-left")" +			padding_right="$(get_prop "padding-right")" +			printf "%s" "$(($1*(font_size-2) + 3 + padding_left + padding_right))" +		} ;; +	*) ;; +esac + + +main() +{ +	# shellcheck disable=SC2317 +	case "$MENUCMD" in +		tofi) +			center() { add_option "--anchor=center --width=252"; } + +			horizontal() { +				add_option "--horizontal=true --height=32" +				add_option "--result-spacing=12" +				add_option "--selection-background=#88c0d0" +				add_option "--selection-background-padding=6,4" +				add_option "--padding-top=0 --padding-bottom=0" +				add_option "--margin-top=4" +			} + +			long() { add_option "--width=100% --height=$(get_height 20)"; } + +			input() { +				add_option "--height=$(get_height 0) --width=$(get_width 24)" +				pre_filter() { cat /dev/null; } +			} + +			prefix() { add_option '--matching-algorithm=normal'; } + +			instant() { add_option "--auto-accept-single=false"; } + +			prompt() { add_option '--prompt-text' "$prompt_arg"; } + +			numbered() {  +				pre_filter() { awk '{print NR, $0}'; } +				post_filter() { awk '{print $1}'; } +			} + +			height() { add_option "--height=$(get_height "$height_arg")"; } +			width() { add_option "--width=$(get_width "$width_arg")"; } + +			run() { tofi-run $*; } + +			menucmd() { tofi "$@"; } ;; + +		dmenu) +			horizontal() { add_option "-l 0"; } + +			center() { add_option "-c"; } + +			long() { add_option "-l 20 -g 1"; } + +			input() { +				pre_filter() { cat /dev/null; } +			} + +			instant() { add_option "-n"; } + +			prefix() { add_option '-x -i'; } + +			prompt() { add_option '-p' "$prompt_arg"; } + +			numbered() { add_option "-px"; } + + +			height() { add_option "-l $height_arg"; } +			width() { add_option "-g $width_arg"; } + +			run() { dmenu_path | dmenu $*; } + +			menucmd() { dmenu $*; } ;; + +		fzf) +			center() { :; } +			horizontal() { :; } +			long() { :; } +			height() { :; } +			width() { :; } +			instant() { :; } +			prefix() { :; } + +			input() { +				pre_filter() { cat /dev/null; } +				add_option '--print-query' +			} + +			prompt() { add_option "--prompt" "$prompt_arg"; } + +			numbered() {  +				pre_filter() { awk '{print NR, $0}'; } +				add_option '--with-nth' '2..' +				post_filter() { awk '{print $1}'; } +			} + +			run() { +				IFS=: +				set -f +				find -L $PATH -type f -printf "%f\n" 2> /dev/null | sort -u | fzf $* +			} + +			menucmd() { fzf -0 -1 "$@"; } ;; + +		*) ;; +	esac + +	for option in $options +	do eval "$option=0" +	done + +	while getopts ":cdhilop:nr1w:xy:v" opt +	do +		# shellcheck disable=SC2034 +		case $opt in +			 +			# display horizontal +			h) horizontal=1 ;; +			# display centered +			c) center=1 ;; +			# take an input and return it on stdout +			i) input=1 ;; +			# adjust size and style dynamically +			p) prompt=1; prompt_arg="$OPTARG";; +			# long list format +			l) long=1 ;; +			# output number of match +			n) numbered=1 ;; +			# select an executable from PATH +			r) run=1 ;; +			# invert instant select on single match +			1) instant=1 ;; +			w) width=1; width_arg="$OPTARG" ;; +			# invert prefix matching +			x) prefix=1 ;; +			y) height=1; height_arg="$OPTARG" ;; + +			:) die "Option '-$OPTARG' requires an argument" ;; +			?) die "Invalid option: -$OPTARG" ;; +		esac +	done + +	# quit if stdin is empty +	[ -t 0 ] && [ "${run:-0}" -eq 0 ] && [ "$input" -eq 0 ] && help && exit 1 + +	# call options +	for option in $options +	do eval "test \"\$$option\" -eq 1" && $option +	done + +	if [ "$run" ]  +	then +		run "$menuopts"  +		exit +	fi + +	command -v pre_filter > /dev/null || pre_filter() { cat; } +	command -v post_filter > /dev/null || post_filter() { cat; } + +	! which "${MENUCMD:-fzf}" > /dev/null && die "MENUCMD '$MENUCMD' was not found." + +	if command -v pre_cmd > /dev/null +	then +		pre_cmd > "$tmp" +		logn "menuopts: $menuopts" +		# shellcheck disable=SC2086 +		pre_filter < "$tmp" | menucmd $menuopts | post_filter +	else +		logn "menuopts: $menuopts" +		# shellcheck disable=SC2086 +		pre_filter | menucmd $menuopts | post_filter +	fi +} + +main "$@" diff --git a/bin/menuscripts/ddl b/bin/menuscripts/ddl new file mode 100755 index 0000000..dd10af5 --- /dev/null +++ b/bin/menuscripts/ddl @@ -0,0 +1,88 @@ +#!/bin/sh + +# colors +red="$(printf '\033[31m')" +blue="$(printf '\033[34m')" +cyan_light="$(printf '\033[36m')" +yellow="$(printf '\033[33m')" +green="$(printf '\033[32m')" +italic="$(printf '\033[3m')" +reset="$(printf '\033[0m')" + +deadlines="$HOME/docs/filios"/deadlines + +die() { >&2 printf '%s\n' "$*"; exit 1; } +usage() +{ +    cat <<EOF +usage: ddl [COMMAND] [ARGUMENT] +        ddl                 lists deadlines +COMMANDS +        new TEXT...         add a new deadline +        coming [NUM]        show the nearest coming deadline(s) +        delete NUM          delete deadline by number +        grep REGEX          show deadlines matching regex +        help                show usage +        edit                edit file in \$EDITOR +EOF +    exit 1 +} +wrong_usage() { >&2 printf 'Wrong usage!\n'; usage; } + +colorize() +{ +    sed \ +        -e "s/^#.*/${red}&${reset}/" \ +        -e "s/^\s*[-?!*].*/${cyan_light}&${reset}/" \ +        -e "s/([^()]\+)/${yellow}${italic}&${reset}/" \ +        -e "s/^\s*#.*/${blue}${italic}&${reset}/" +} +list_deadlines() { cat "$deadlines"; } +# list dates in chronological order +list_dates() +{ +    grep '^#' "$deadlines" | +        sort -t '/' -k 3 -k 2 -k 1 -n |  +        uniq | +        sed 's@/@.@g' +} + + +# shellcheck disable=SC2142 + +### MAIN + +# Arguments without an option +case "$1" in +    h*) usage ;; + +    e*) $EDITOR "$deadlines" ;; + +    c*)  +        i=1 +        list_dates | head -n "${2:-1}" | +            while read -r date +                do +                    sed -n "/$date/,/^#\|^$/p" "$deadlines" |  +                        colorize | +                        sed "1s/.*/& ($green$i$reset)/" +                    i=$((i+1)) +                done ;; + +    "") list_deadlines | colorize ;; + +    *) false ;; + +esac && exit + +arg="$1" +shift +[ "$1" ] || wrong_usage + +case "$arg" in + +    d*) sed -i "/$(list_dates | sed -n "${1}p")/,/^$/d" "$deadlines" ;; + +    *) wrong_usage ;; + +esac diff --git a/bin/menuscripts/keyadd b/bin/menuscripts/keyadd new file mode 100755 index 0000000..4e7949f --- /dev/null +++ b/bin/menuscripts/keyadd @@ -0,0 +1,62 @@ +#!/bin/sh + +log() +{ +	notify-send -t 1000 "keyadd" "$1" & +	>&2 printf '%s\n' "$1" +} + +SSHFOLDER="$HOME/.ssh" + +# Test if can connect to ssh-agent +ssh-add -l > /dev/null 2>&1 +if [ $? -gt 1 ] # ignore if there are no identities +then +	log "Could not connect to agent." +	exit 1 +fi + +delete=0 +if [ "$1" = "-d" ]  +then +    delete=1 +    shift +fi + +if [ "$1" ] +then +    key_pretty="$1" +else +	key_pretty="$(find "$SSHFOLDER" -iname "*.pub" | +        sed "s@$SSHFOLDER/\(.*\)\.pub\$@\1@" | +        commander -xc)" +fi +[ "$key_pretty" ] || exit 1 +key="$SSHFOLDER/$key_pretty" + +if [ ! -f "$key" ]  +then +    log "No key found at: $key" +    exit 1 +fi + +if [ "$delete" -eq 1 ] +then +	ssh-add -q -d - < "$key".pub 2> /dev/null && +		log "Deleted $key_pretty." || +		log "Could not delete." +    exit +fi + +# check if key is already added +if ssh-add -l | grep -q "$(ssh-keygen -lf "$key")" +then +	log "Key already added." +    exit 1 +fi + +HOST=$(hostnamectl hostname) +export PASSWORD="keys/$HOST/ssh/$key_pretty" +export SSH_ASKPASS="sshpass" +ssh-add -q - < "$key" && +    log "Added $key_pretty." diff --git a/bin/menuscripts/mmedia b/bin/menuscripts/mmedia new file mode 100755 index 0000000..3141c3b --- /dev/null +++ b/bin/menuscripts/mmedia @@ -0,0 +1,59 @@ +#!/usr/bin/env sh + +tmp="/tmp/mmedia" + +dirs="$HOME/dl" + +concat_path() { sed "s#^$HOME#\~#;s#\([^/]\)[^/]*/#\1/#g"; } + +case "$1" in  +	"video")  +		regex='^.\+\.\(webm\|mp4\|mpeg\|mkv\)$'  +		dirs="$dirs $HOME/vids" +		viewer() { $PLAYER "$1"; } ;; +	"pdf")  +		regex='^.\+\.\(pdf\)$'  +		dirs="$dirs $HOME/docs" +		viewer() { $VIEWER "$1"; } ;; +	"image") +		regex='^.\+\.\(png\|avif\|jpg\)$'  +		dirs="$dirs $HOME/pics" +		viewer() { $IMAGE "$1"; } ;; +	"cursus") +		regex='^.*/[cC]ursus/index.html$' +		dirs="$HOME/docs/school/Vakken" +		concat_path() { sed "s#$dirs/##;s#/[cC]ursus/index.html##"; } +		viewer() { $BROWSER "$1"; } ;; +	"schoolpdf") +		regex='^.\+\.\(pdf\)$'  +		dirs="$HOME/docs/school/Vakken" +		concat_path() { sed "s#$dirs/##;s#/[cC]ursus/index.html##;s#/Cursus/viewer/files/#: #"; } +		viewer() { $VIEWER "$1"; } ;; +	*)  +		choice="$(cat <<-EOF | dmenu -g 5 -l 1 -c +		video +		pdf +		image +		cursus +		schoolpdf +		EOF +		)" +		[ "$choice" ] || exit 1 +		"$0" "$choice" +		exit ;; +esac + +shift +[ "$1" ] && dirs="$1" + +choice="$( +	find -L $dirs 2> /dev/null | +	grep "$regex" | +	sort | tee "$tmp" | +	concat_path | +	dmenu -px -c -i -l 10 -g 1 -x)" + +file="$(sed -n "${choice}p" "$tmp")" +[ -r "$file" ] || exit 1 + +viewer "$file" diff --git a/bin/menuscripts/mpass b/bin/menuscripts/mpass new file mode 100755 index 0000000..7348321 --- /dev/null +++ b/bin/menuscripts/mpass @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +store="${PASSWORD_STORE_DIR:-$HOME/.password-store}" + +# list passwords, group directories first +list_pswds() +{ +	find "$1" \ +		-maxdepth 1 -mindepth 1 \ +		-not -name '.*' -type d -printf "%y\t%f\n" -o \ +		-not -name '.*' -not -type d -printf "%y\t%f\n" | +		sort -k1 -k2 | +		cut -f 2 | sed 's/\.gpg$//' +} + +while [ -d "$store/$file" ] +do +	choice="$(list_pswds "$store/$file" | dmenu -c -g 4 -l 4)" +	[ "$choice" ] || exit 1 +	[ -z "$file" ] && file="$choice" || file="$file/$choice" +done +[ "$file" ] || exit 1 + +pass show -c "$file" || exit 1 +notify-send -t 1000 "mpass" "copied: $file" + +[ "$WAYLAND_DISPLAY" ] && cliphist list >/dev/null && # on wayland and cliphist is running +	cliphist list | head -n 1 | cliphist delete diff --git a/bin/menuscripts/mplay b/bin/menuscripts/mplay new file mode 100755 index 0000000..57af631 --- /dev/null +++ b/bin/menuscripts/mplay @@ -0,0 +1,76 @@ +#!/bin/sh + +MUSIC="$HOME/music" + + +list_dirs() +{ +	find -L "$1" \ +		-mindepth 1 -maxdepth 1 \ +		-not -name "*.cue" | +		sed "s@^$1/@@" | sort; +} + +find_song() +{ +	file="$MUSIC" +	while [ -d "$file" ] +	do  +		choice="$(list_dirs "$file" | commander -clx)" +		[ "$choice" ] || return +		file="$file/$choice" +	done +	printf '%s' "${file##"$MUSIC/"}" +} + +play_song() +{ +	printf '%s\n' "$1" | tr '\n' '\0' | +		xargs -0I{} mpc insert "{}" || return +	mpc next 2> /dev/null +	mpc play 2> /dev/null +} + +main() +{ +	choice="$(printf 'volume\nsearch\ncommand\nall_search\nquit' | commander -c -w 5 -y 1)" +	case "$choice" in +		volume)  +			# Change volume while no error +			while true  +			do +				volume="$(mpc volume | awk -F '[ %]' '{print $2}')" +				nb="$(printf 'p\nm' | commander -c -y 2 -p "$volume" | tr 'pm' '+-')" +				[ "$nb" ] || break +				change="$(commander -ci -p "$volume$nb")" +				mpc volume "$nb$change" || break +			done ;; + +		search)  +			song="$(find_song)" +			[ "$song" ] || return + +			choice="$(printf 'insert\nadd\nplay' | commander -c -w 3 -y 1)" +			case "$choice" in +				insert|add) mpc "$choice" "$song" ;; +				play) play_song "$song" ;; +			esac ;; + +		command)  +			mpc "$(printf 'next\nprevious\nclear\nstop\ntoggle' | +				commander -c -w 8 -y 5)" ;; + +		all_search)  +			song="$(mpc listall | commander -cxh)" +			[ "$song" ] || return +			play_song "$song";; +		quit) return 1 ;; + +		*) return 1 ;;  +	esac +	return 0 +} + +while main +do :; +done diff --git a/bin/menuscripts/muzrname b/bin/menuscripts/muzrname new file mode 100755 index 0000000..3f63aff --- /dev/null +++ b/bin/menuscripts/muzrname @@ -0,0 +1,22 @@ +#!/bin/sh + +rename() +{ +	## Expression 1: +	# For CDs or volumes 1-01 -> 1_01 +	## Expression 2: +	# * don't match the start (^) +	# match the first part with a number and replace following [ -.] by '. ' +	sed -e 's/^\s*\([0-9]\+\)[ -_.]\([0-9]\+\)/\1_\2. /' \ +		-e 's#\s*\([0-9]\+\)[ -.]\+#\1. #' +} + +if [ ! -t 0 ] +then  +	rename +elif [ "$1" ] +then  +	printf '%s' "$1" | rename +else +	exit 1 +fi diff --git a/bin/menuscripts/pomo b/bin/menuscripts/pomo new file mode 100755 index 0000000..e8795e7 --- /dev/null +++ b/bin/menuscripts/pomo @@ -0,0 +1,78 @@ +#!/bin/sh + +### FUNCTIONS +notif() {  +    herbe "pomo" "$1" & +    sleep 1 +    pkill -SIGUSR1 herbe +} +logn () { >&2 printf '%s\n' "$@"; } +log () { >&2 printf '%s' "$@"; } + +# Plays ringing sound +# Then wait for user input to start/end the break +player_command() +{ +	>&2 printf ' > ' +	[ -r "$ringSound" ] || PLAYER="" +	case "$PLAYER" in +	    mpv) mpv --loop --msg-level=all=no "$ringSound" ;; +	    "") head -n 1;; +	    *) $PLAYER "$ringSound" ;; +	esac +} + +# $1: time in minutes +# $2: msg for notification +ring_ring() +{ +	logn "$(date '+%R') B $round" +	player_command +    herbe "pomo" "$2" & +    sleep "${1}m" +	player_command +	>&2 printf '\n' +} + +### PROGRAM +main() +{ +	round="${1-0}" +	case "$round" in +		0|1|2|3) ;; +		ring) ;; +		*) logn "Invalid \$round value." && exit 1 ;; +	esac + +	ringSound="${XDG_DATA_HOME:-$HOME/.local/share}"/pomo/ring.aac +	[ -r "$ringSound" ] && logn "ring: $ringSound" + +	if [ "$1" = "ring" ] +	then +	    player_command +	    exit +	fi + +	# Countdown +	for msg in "three" "two" "one" +	do notif "$msg" +	done + +	while true +	do +		notif "START" +		logn "$(date '+%R') S $round" +		sleep 25m +		if [ "$round" -eq 3 ] +		then +			ring_ring 20 "GIGA BREAK TIME" +			round=0 +		else +			ring_ring 5 "BREAK TIME" +			round=$((round+1)) +		fi +	done +} + +trap 'exit 1' INT +main "$@" diff --git a/bin/menuscripts/shdul.sh b/bin/menuscripts/shdul.sh new file mode 100755 index 0000000..4e1d744 --- /dev/null +++ b/bin/menuscripts/shdul.sh @@ -0,0 +1,157 @@ +#!/bin/sh + +tmp="$(mktemp)" + +red="$(printf '\033[35m')" +blue="$(printf '\033[34m')" +reset="$(printf '\033[0m')" +underline="$(printf '\033[4m')" +bold="$(printf '\033[1m')" + +THISDIR="$(dirname "$(readlink -f "$0")")" +# schedule file +SCHEDULE="$THISDIR/schedule" +# blocks directory +BLOCKS="$THISDIR/blocks" + +die () { >&2 printf "%s" "$@"; exit 1; } +log () { >&2 printf '%s' "$@"; } +logn () { >&2 printf '%s\n' "$@"; } + +cleanup () { rm -f "$tmp"; } + +trap cleanup EXIT + +read_char () +{ +	old_stty_cfg=$(stty -g) +	stty raw -echo  +	dd ibs=1 count=1 2> /dev/null +	stty "$old_stty_cfg" +} + +edit_schedule () +{ +	while true +	do +		char="$(read_char)" +		case "$char" in +			q) exit ;; +			a) add_block ;; +			# new or from save +			d) delete_block ;; +			'') ;; +			*) printf "%s" "$char" +		esac +	done + +} + +# adds NOW to the schedule and gets its line number +# $1: schedule file +get_now () +{ +	fake="$(date +%R)\tZZZZZZZZZZZZZZZZ - NOW" +	sed "\$a $fake" "$1" | +		sort -g | +		awk "/^$fake/ {print NR}" +} + +# prints schedule in a nice format +# $1: schedule file +# $2: blocks dir +print_schedule () +{ +	now="$(get_now "$1")" + +	clear + +	i=1 +	while read -r line +	do +		[ "$i" -lt "$((now-1))" ] && i=$((i+1)) && continue +		i=$((i+1)) + +		# Colors +		if [ "$i" -lt "$now" ] +		then +			printf "%s" "${reset}${red}" +		elif [ "$i" -eq "$now" ] +		then +			printf "%s" "${reset}${bold}" +		else +			printf "%s" "${reset}${blue}" +		fi + +		block_file="$2/$(printf "%s" "$line" | cut -f2)" +		block_time="$(printf "%s" "$line" | cut -f1)" + +		# markup +		printf "%s\n" "$block_time" +		sed 's/.*/│&/' "$block_file" +		# printf '\n' +		 +	done < "$1" + +	printf '%s' "${reset}" +} + +# $1: schedule file +# $2: blocks dir +view_schedule() +{ +	trap "break" INT + +	prev_now="$(get_now "$1")" +	print_schedule "$1" "$2" +	while true +	do +		now="$(get_now "$1")" + +		# Refresh when new block +		if [ "$prev_now" -ne "$now" ] +		then +			print_schedule "$1" "$2" +			prev_now="$now" +			notify-send -u critical -t 5000 "shdul" "$(awk "NR==$((now-1)) {print \$2}" "$1")" + +			# Align with clock +			sleep "$((60-$(date +%-S)))s" +		else +			sleep 1m +		fi +	done + +	clear +} + +main () +{ +	echo $$ > "$THISDIR/.scheduler.pid" + +	view_schedule "$SCHEDULE" "$BLOCKS" +	while true +	do +		printf ':' +		char="$(read_char)" +		case "$char" in +			h) cat <<-EOF + +				 h	help +				 v	view schedule +				 s	edit schedule mode +				 q	exit + +				EOF +				;; +			l) clear ;; +			v) view_schedule "$SCHEDULE" "$BLOCKS" ;; +			s) edit_schedule ;; +			q) exit ;; +			'') ;; +			*) printf "%s" "$char" +		esac +	done +} + +main diff --git a/bin/menuscripts/td b/bin/menuscripts/td new file mode 100755 index 0000000..e905d9b --- /dev/null +++ b/bin/menuscripts/td @@ -0,0 +1,65 @@ +#!/bin/sh + +todo="$HOME/docs/filios"/todo + +die() { >&2 printf '%s\n' "$*"; exit 1; } +usage() +{ +    cat <<EOF +usage: td [COMMAND] [ARGUMENT] +        td                  lists to-do's +COMMANDS +        new TEXT...         add a new to-do +        clear               remove all to-do's +        delete NUMBER       delete a to-do by number +        grep REGEX          show to-do's matching regex +        help                show usage +        move NUMBER NUMBER  change priority of a to-do +        edit                edit file in \$EDITOR +EOF +    exit 1 +} +wrong_usage() { >&2 printf 'Wrong usage!\n'; usage; } + +list_todos() {  +    [ ! -r "$todo" ] && die "No to-do's." +    [ "$(wc -l < "$todo")"  -eq 0 ] && die "No to-do's." +    awk '{print NR ": " $0}' "$todo" +} + +# shellcheck disable=SC2142 + +### MAIN + +# Arguments without an option +case "$1" in +    c*) rm -f "$todo"; >&2 printf 'Cleared.\n' ;; +    h*) usage ;; +    e*) $EDITOR "$todo" ;; +    "") list_todos ;; +    *) false ;; +esac && exit + + +arg="$1" +shift +[ "$1" ] || wrong_usage + +case "$arg" in +    n*) +        printf '%s\n' "$*" >> "$todo" +        list_todos ;; + +    d*) +        sed -i -n "$1!p" "$todo" +        list_todos ;; +    g*) list_todos | grep "$*" ;; + +    m*) +        [ "$2" ] || wrong_usage +        line="$(list_todos | sed "/^$1:/!d;s/^$1: //")" +        sed -i "${1}d;${2}i${line}" "$todo" +        list_todos ;; + +    *) wrong_usage ;; +esac diff --git a/bin/menuscripts/treetag.sh b/bin/menuscripts/treetag.sh new file mode 100755 index 0000000..3ded637 --- /dev/null +++ b/bin/menuscripts/treetag.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +VERSION="0.3" + +batch=0 +rename=0 + +help () +{ +	cat <<-EOF >&2 +	Usage: treetag.sh [options] +	Options: +	-b              Enable batch mode +	-d <directory>  Specify the music directory +	-h              Show this help message and exit +	-r              also rename file +	-v              Print version information and exit +	EOF +} + +log () { >&2 printf '%s\n' "$@"; } +die () { log "$@"; exit 1; } +require () { command -v "$1" > /dev/null || die "E: This script needs '$1' to be installed."; } +ls_dirs() { find . -mindepth 1 -maxdepth 1 -type d -printf "%f\n"; } + +### Tag files in the current directory +# $1: artist name +# $2: album name +treetag () +{ +	[ -z "$1" ] || [ -z "$2" ] && return 1 +	artist="$1" +	album="$2" + +	>&2 printf "artist: %s\n" "$artist" +	>&2 printf "album: %s\n" "$album" +	find . -maxdepth 1 -type f -printf '%f\n' | sort -g | +		while read -r file +		do +			>&2 printf "file: %s\n" "$file" +			! soxi "$file" > /dev/null 2>&1 && continue + +			# Remove number prefix and extension +			name="$(printf '%s' "${file%.*}" | sed 's/^[0-9]*\s*[. -]\s*//')" +			i=$((i+1)) + +			log "I: [$artist] ($album) #$i $name" + +			id3v2 \ +				-a "$artist" \ +				-A "$album" \ +				-t "$name" \ +				-T "$i" \ +				-- "$file" +			printf '%s\n' "$i" > .count + +			[ $rename -eq 1 ] && mv -- "$file" "$i. $name.${file##*.}" + +		done +		if [ -f .count ] +		then +			log "I: $(cat .count) file(s) tagged." +			rm .count +		else +			log "I: No files tagged." +		fi +} + +batch_tag () +{ +	artist="${PWD##*/}" # basename of current dir +	ls_dirs | +		while read -r album +		do (cd "$album" && treetag "$artist" "$album") +		done +} + +# Tag interactively with fzf +interactive () +{ +	require "fzf" + +	artist="$(ls_dirs | fzf)" +	[ "$artist" ] && cd "$artist" || exit 1 + +	choice="$artist" +	while true +	do +		choice="$(ls_dirs | fzf --prompt "$choice:")" +		if [ "$choice" ] +		then  +			album="$choice" +			cd "$album" || exit 1 + +			printf 'stop? ' +			head -n 1 | grep -q "[yY]" && break +		else  +			break +		fi +	done + +	treetag "$artist" "$album" +} + +while getopts ":d:bhrv" opt +do +	case $opt in +		b) batch=1 ;; +		d) musdir="$OPTARG" ;; +		h) help; exit ;; +		r) rename=1 ;; +		v) log "treetag.sh $VERSION"; exit ;; +		:) die "E: Option -$OPTARG requires an argument" ;; +		?) die "E: Invalid option: -$OPTARG" ;; +	esac +done + +require "id3v2" +require "sox" + +cd "${musdir:=.}" || exit 1 + +if [ $batch -eq 1 ]  +then +	batch_tag +else +	interactive +fi diff --git a/bin/menuscripts/tsh b/bin/menuscripts/tsh new file mode 100755 index 0000000..0c57ee0 --- /dev/null +++ b/bin/menuscripts/tsh @@ -0,0 +1,208 @@ +#!/bin/sh + +PROG="$(basename "$0")" +## VARIABLES +# copy command and deps variable +deps="pup curl $MENUCMD" + +MODULES_PATH=$HOME/.local/share/tsh +module='nyaa.sh' # default module + +# Files +export tmp="/tmp/$PROG" +files="seeds sizes names html tmp_types" +# Use export so that these variables can be used inside of modules +for file in $files +do eval "export $file=$tmp/$file" +done +# Files not in $files won't be deleted +export results="$tmp/results" +export links="$tmp/links" + +categories="music anime movies shows other software games isos books" + +if [ "$WAYLAND_DISPLAY" ] +then +	clipp() { wl-copy -n; } +	deps="$deps wl-copy" +else +	clipp() { xclip -selection clipboard -r; } +	deps="$deps xclip" +fi +## FUNCTIONS + +help () +{ +	>&2 cat <<-EOF +	Usage: $PROG [options] query +	Options: +	    -h           Show this help message and exit +	    -r           Skip getting pages and use last results +	    -s OPTION    Sort results based on the specified OPTION +	                 Available options: seeds, size, name +	    -m MODULE    Select a module, if MODULE is 'list', +	                 lists out available modules +            -c CATEGORY  Select category +            -f           Do not list files +            -d		 Download without confirming +	EOF +} + +log () { >&2 printf '%s' "$*"; } +logn () { >&2 printf '%s\n' "$*"; } +die () { logn "$@"; exit 1; } + +confirm() +{ +	log "$1" +	head -n 1 | grep -q "[yY]" +} + +dependencies () +{ +	for p in $deps +	do +		if ! command -v "$p" > /dev/null +		then +			logn "E: Program '$p' not found." +			error=1 +		fi +	done +	[ "${error:-0}" -eq 1 ] && exit 1 +} + +# shellcheck disable=SC2046 +# (we use word splitting on purpose) +isOnline () { grep -q '1' $(echo /sys/class/net/*/carrier | sed 's#/sys/class/net/lo/carrier ##'); } + +# Remove temp files and quit +cleanup () +{ +	for file in $files +	do eval "rm -f \$$file" +	done +} + +list_modules () { find -L "$MODULES_PATH" -type f -printf "%f\n"; } + +# get a query from user based on MENUCMD +get_query () +{ +	isOnline || exit 1 +	if [ "${query:="$*"}" ] +	then +		printf "%s" "$query" +	else +		log ' > ' +		head -n 1 +	fi | tr ' ' '+' +} + +# Select a result from the result file sorterd with sort_results +# and select with fzf +select_result () +{ +	command -v sort_results > /dev/null || sort_results() { sort -k3 -n -r; } +	awk '{print NR, $0}' "$results" | +		sort_results | +		column -t -l 3 | +		fzf -m --with-nth 2.. | +		awk '{print $1}' +} + +show_files() +{ +	hash="${1##*btih:}" +	hash="${hash%%&*}" + +	# Download the torrent file from a torrent website +	curl -s "https://itorrents.org/torrent/${hash}.torrent" > "$tmp"/.torrent +	transmission-show "$tmp"/.torrent | sed -n '/^FILES/,$p' | head -n -1 | tail -n +3 >&2 +	rm -f "$tmp"/.torrent +} + +trap "exit 1" INT +trap "cleanup" EXIT + +## OPTIONS +skip=0 +while getopts ":hm:rs:c:fd" opt +do +	case $opt in +		h) help && exit ;; +		c) +			[ "$OPTARG" = "list" ] && >&2 printf '%s\n' "$categories" && exit +			category="$(printf '%s\n' "$categories" | tr ' ' '\n' | grep -m 1 "^$OPTARG")" +			[ -z "$category" ] && die "No valid category for '$OPTARG'" +			logn "category: $category" ;; +		f) noaskfiles="1" ;; +		d) noaskdownload="1" ;; +		m) +			[ "$OPTARG" = "list" ] && list_modules && exit +			module="$(list_modules | grep -m 1 "^$OPTARG")" +			[ -z "$module" ] && die "No valid module for '$OPTARG'" +			logn "module: $module" ;; +		r)  +			[ ! -r "$results" ] && die "No previous results found." +			skip=1 ;; +		s) +			case $OPTARG in +				"seeds")	sort_results() { sort -k3 -n -r; } ;; +				"size") 	sort_results() { sort -k2 -h -r; } ;; +				"name") 	sort_results() { sort -k4; } ;; +				*) die "argument '$OPTARG' not seeds,size,name" ;; +			esac ;; +		:) die "Option -$OPTARG requires an argument" ;; +		?) die "Invalid option: -$OPTARG" ;; +	esac +done +shift $((OPTIND - 1)) + +dependencies + +# Get the torrents with module +if [ $skip -ne 1 ] +then +	mkdir -p "$tmp" + +	query="$(get_query "$*")" +	[ "$query" ] || exit 1 + +	# Get results +	rm -f "$results" "$links" +	# shellcheck source=/usr/local/lib/$PROG/nyaa.sh disable=SC1091 +	. "$MODULES_PATH/$module" +	[ -f "$results" ] || die "No results." + +	# Save which module was used +	printf "%s\n" "$module" >> "$links" +else +	module="$(tail -n 1 "$links")" +fi + +# acquire get_magnet function +# shellcheck source=/usr/local/lib/$PROG/nyaa.sh disable=SC1091 +getfunctions=1 . "$MODULES_PATH/$module" + +# select result from "$results" +for choice in $(select_result | xargs) +do +    printf 'choice: %s\n' "$(sed -n "${choice}p" "$results" | cut -f 3-)" +    magnet="$(get_magnet "$choice")" +    [ "$magnet" ] || exit 1 + +    if [ -z "$noaskfiles" ] && confirm 'files?'; then +	    show_files "$magnet" +    fi + +    if [ "$noaskdownload" ] || confirm 'download?' +    then +    	    [ "$category" ] || category="$(printf '%s' "$categories" | tr ' ' '\n' | fzf)" +    	    [ "$category" ] || exit 2 +	    transmission-remote debuc.com -a "$magnet" -w "/downloads/$category" +    elif confirm "copy?" +    then +	    echo "$magnet" | clipp +    fi + +done  | 
