diff options
62 files changed, 2180 insertions, 174 deletions
diff --git a/bin/common/ytlink b/bin/common/ytlink index 48be9cf..215c164 100755 --- a/bin/common/ytlink +++ b/bin/common/ytlink @@ -2,15 +2,21 @@  # convert to youtube.com/path url  # works for: -# - 'youtu.be/watch?v=xxxxxx' +# - 'youtu.be/xxxxxx'  # - 'https://piped.video/watch?v=xxxxx' +# - https://youtube.com/watch?v=xxxx -inp="$1" -[ "${inp:=$(clipo)}" ] || inp="$(cat /dev/stdin)" +# get from $1 or clipboard if empty +vid="${1:-$(clipo)}" +# The following subsitutions will try to grab the video id  # if link is http://127.0.0.1:9010/https://www.youtube.com/watch?v=7KpxsqwNF0o -inp="${inp#*/https://}" +vid="${vid#*/https://}"  # remove util scheme -inp="${inp#*//}" -inp="https://youtube.com/${inp#*/}" -printf "%s" "$inp" +vid="${vid#*//}" +# remove domain +vid="${vid#*/}" +# remove query string +vid="${vid#watch?v=}" + +printf "https://youtube.com/watch?v=%s\n" "$vid" diff --git a/bin/extra/clock b/bin/extra/clock new file mode 100755 index 0000000..fdffae0 --- /dev/null +++ b/bin/extra/clock @@ -0,0 +1,62 @@ +#!/bin/sh + +clocks="${XDG_DATA_HOME:-$HOME}"/clocks.csv + +if [ ! -f "$clocks" ] +then +	printf 'start,end,message\n' > "$clocks" +fi + +if [ "$1" = "-c" ] +then +	# empty +	[ "$(wc -l < "$clocks")" -eq 1 ] && exit + +	timefmt="%y%m%d-%T" +	IFS="," +	# skip csv header +	tail -n +2 "$clocks" |    +	while read -r start end message +	do +		printf "%s - %s | %s\n" "$(date -d "@$start" +"$timefmt" )" "$(date -d "@$end" +"$timefmt")" "$message" +	done +	exit +fi + +if [ "$1" = "-e" ] +then +	$EDITOR "$clocks" +	exit +fi + +trap 'exit 0' INT # The proper way to exit + +while true +do +	>&2 printf ' > '  +	message="$(head -n 1)"  + +	[ "$message" ] || exit 1 +	printf '\033[1A' # move cursor up once: https://en.wikipedia.org/wiki/ANSI_escape_code + +	start_time="$(date +%s)" +	start_time_pretty="$(date -d "@$start_time" +%R)"  +	>&2 printf -- '\r%s- > %s' "$start_time_pretty" "$message" + +	# Wait for EOF +	cat > /dev/null 2>&1 + +	end_time="$(date +%s)" +	end_time_pretty="$(date -d "@$end_time" +%R)"  +	>&2 printf -- '\r%s-%s > %s\n' "$start_time_pretty" "$end_time_pretty" "$message" + +	if printf '%s' "$message" | grep ',' > /dev/null +	then +		# escape potential double quotes +		message="$(printf '%s' "$message" | sed -e 's/"/""/g')" +		message="\"$message\"" +	fi + +	# save clocked time and message +	printf '%s,%s,%s\n' "$start_time" "$end_time" "$message" >> "$clocks" +done diff --git a/bin/extra/curszip b/bin/extra/curszip index 64abdb6..0de772f 100755 --- a/bin/extra/curszip +++ b/bin/extra/curszip @@ -1,13 +1,17 @@  #!/bin/sh -list1() { find "$1" -mindepth 1 -maxdepth 1 -type "${2:-d}" -printf '%f\n'; } +# $1: dir  +# $2: type +list1() { find "$1" -mindepth 1 -maxdepth 1 -type "$2" -printf '%f\n'; } -curs="$(list1 ~/docs/school/Vakken | commander -c)" +curs="$(list1 ~/docs/school/Vakken d | dmenu -c)"  [ "$curs" ] || exit 1 -zip="$(list1 ~/dl f | fzf -f "$curs" | grep '\.zip$')"  >&2 printf "curs: %s\n" "$curs" -[ "$zip" ] || exit 1 +dldir="$(which xdg-user-dir > /dev/null 2>&1 && xdg-user-dir 'DOWNLOAD' || echo '~/dl')" + +zip="$(list1 "$dldir" f | fzf -f "$curs" | grep '\.zip$')" +[ "$zip" ] || exit 1  >&2 printf "zip: %s\n" "$zip"  cd -- ~/docs/school/Vakken/"$curs" || exit 1 diff --git a/bin/extra/ddsurf b/bin/extra/ddsurf new file mode 100755 index 0000000..a3ae0d1 --- /dev/null +++ b/bin/extra/ddsurf @@ -0,0 +1,4 @@ +#!/bin/sh +f="$(mktemp)" +awk '!x[$2]++' ~/.config/surf/history.txt > "$f" +mv "$f" ~/.config/surf/history.txt diff --git a/bin/extra/igdl b/bin/extra/igdl new file mode 100755 index 0000000..1973187 --- /dev/null +++ b/bin/extra/igdl @@ -0,0 +1,21 @@ +#!/bin/sh +lock="/tmp/igdl.lock" + +if [ -f "$lock" ] +then +	herbe "already downloading." +	exit 1 +fi + + +url="$(clipo)" +out="/tmp/igdl.mp4" + +touch "$lock" +herbe "igdl" "downloading: $url"  & +yt-dlp "$url" -o "$out" || rm "$lock" + +printf '%s' "$out" | clipp +herbe "igdl" "copied path." + +rm "$lock" diff --git a/bin/extra/keyboards.txt b/bin/extra/keyboards.txt index db004ce..d6e9b8a 100644 --- a/bin/extra/keyboards.txt +++ b/bin/extra/keyboards.txt @@ -1,2 +1,2 @@  us -us -option ctrl:swapcaps,altwin:menu_win -variant colemak +colemak -option ctrl:swapcaps,altwin:menu_win diff --git a/bin/extra/mtr b/bin/extra/mtr new file mode 100755 index 0000000..486a9b8 --- /dev/null +++ b/bin/extra/mtr @@ -0,0 +1,23 @@ +#!/bin/sh + +list_categories() +{ +    cat <<EOF +music +anime +movies +shows +other +software +games +isos +books +EOF +} + +category="$(list_categories | commander -cl)" +[ "$category" ] || exit 1 + +transmission-remote debuc.com -a "$(clipo)" -w "/downloads/$category" + +notify-send "mtr" "added to <b>$category</b>" diff --git a/bin/extra/muz-sync b/bin/extra/muz-sync new file mode 100755 index 0000000..a81ef74 --- /dev/null +++ b/bin/extra/muz-sync @@ -0,0 +1,10 @@ +#!/bin/sh +trap "exit 1" INT + +music="$(xdg-user-dir MUSIC)" +>&2 printf "music: %s\n" "$music" + +# recursive, links, fuzzy, partial, progress +while ! rsync -rlyP --size-only db:/media/basilisk/music/sorted/ "$music" +do : +done diff --git a/bin/extra/myalscore.sh b/bin/extra/myalscore.sh new file mode 100755 index 0000000..ef68bcc --- /dev/null +++ b/bin/extra/myalscore.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +[ "$1" ] || exit 1 +query="$(printf '%s' "$*" | sed 's/\s/%20/g')" +curl -s "https://myanimelist.net/search/prefix.json?type=all&keyword=$query&v=1" \ +	-H 'Accept: application/json, text/javascript, */*; q=0.01' | +	jq -r '.categories[].items[] | [.payload.score, .name] | join(" ")'  diff --git a/bin/extra/qrclip b/bin/extra/qrclip new file mode 100755 index 0000000..f9dc92e --- /dev/null +++ b/bin/extra/qrclip @@ -0,0 +1,12 @@ +#!/bin/sh +case $1 in +	'-o') +		qrencode -s 16 "$(clipo)" -o - | +			imv -w "imv - $(clipo)" - ;; +	'-s') +		qrencode -s 16 "https://duckduckgo.com/$(clipo)" -o - | +			imv -w "imv - search $(clipo)" - ;; +    *) +        >&2 printf 'qrclip [-s | -o]\n' +        exit 1 +esac diff --git a/bin/extra/spschedule b/bin/extra/spschedule new file mode 100755 index 0000000..b0dd70a --- /dev/null +++ b/bin/extra/spschedule @@ -0,0 +1,2 @@ +#!/bin/sh +curl -s 'https://subsplease.org/api/?f=schedule&tz=UTC' | jq -r ".schedule.$(date +%A).[] | [.time, .title] | join(\" \")" diff --git a/bin/extra/trl b/bin/extra/trl index ee42040..55d65ee 100755 --- a/bin/extra/trl +++ b/bin/extra/trl @@ -1,20 +1,8 @@  #!/bin/sh -# prints on stderr -log () { >&2 echo "$@"; } +# Translate words using http://context.reverso.net and scraping the answers +# with 'pup' and 'curl'. -help ()  -{ -	 >&2 cat <<-EOF -	  h         help -	  l         clear output -	  q         quit - -	  i         invert languages -	  p         select primary -	  s         select secondary -	EOF -}  # returns available languages  languages () {  	cat <<-EOF @@ -46,70 +34,25 @@ languages () {  	EOF  } -# translates a word -# $1: primary language -# $2: secondary language -# $3: word to translate -translate () -{ -	curl -s "https://context.reverso.net/translation/$1-$2/$3" \ -	--compressed \ -	-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0' \ -	-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \ -	-H 'Accept-Language: en-US,en;q=0.5' \ -	-H 'Accept-Encoding: gzip, deflate, br' | -	pup 'a.link_highlighted em text{}' | -	sed 's/.*/\L&/' | -	sort | uniq | sed 's/.*/  &/' -} - -# prints the current language -current_language () -{ -	log "  current: $primary-$secondary" -} - -select_language () -{ -	tmp="$(languages | fzf)" -	[ "$tmp" ] && [ "$tmp" != "$primary" ] && [ "$tmp" != "$secondary" ] && -		eval "$1=\"$tmp\"" -	current_language -} - -# set default languages -primary=french -secondary=dutch - - -main () -{ -	current_language -	while true -	do -		log -n '>' -		read -r prompt  -		test $? -eq 1 && exit 0 # quit on ctrl-d -		case "$prompt" in -			q) break ;; -			l) clear ;; -			i) tmp="$secondary"; secondary="$primary"; primary="$tmp" -				current_language ;; -			h) help ;; # TODO -			p) select_language primary ;; -			s) select_language secondary ;; -			'') ;; -			*) translate "$primary" "$secondary" "$prompt" ;; -		esac -	done -} - - -if  [ "$1" = "--help"  ] || [ "$1" = "-h" ] +if [ -z "${word:=$1}" ]  then -	log "usage: trl" -	help -	exit +    >&2 printf '>' +    word="$(head -n1)"  fi - -main +[ "$word" ] || exit 1 + +primary="$(languages | fzf --prompt="from:")" +[ "$primary" ] || exit 1 + +secondary="$(languages | fzf --prompt="to:")" +[ "$secondary" ] || exit 1 + +curl -s "https://context.reverso.net/translation/$primary-$secondary/$word" \ +    --compressed \ +    -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0' \ +    -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \ +    -H 'Accept-Language: en-US,en;q=0.5' \ +    -H 'Accept-Encoding: gzip, deflate, br' | +    pup 'a.link_highlighted em text{}' | +    sed 's/.*/\L&/' | +    sort | uniq | sed 's/.*/  &/' diff --git a/bin/extra/trmv b/bin/extra/trmv new file mode 100755 index 0000000..22d9e48 --- /dev/null +++ b/bin/extra/trmv @@ -0,0 +1,13 @@ +#!/bin/sh + +trr() { transmission-remote 192.168.178.79 "$@"; } + +id="$(trr -t all -l | tail -n +2 | head -n -1 | fzf | awk '{print $1}')" +[ "$id" ] || exit 1 +name="$(trr -t "$id" -i | grep '^\s*Name:' | cut -f 4- -d ' ')" +location="$(trr -t "$id" -i | grep '^\s*Location:' | cut -f 4- -d ' ')" + +>&2 printf '#%s\n' "$id" +>&2 printf "old name: %s\n" "$name" +>&2 printf 'new name: ' +trr -t "$id" --path "$name" --rename "$(head -n 1)" diff --git a/bin/extra/udict b/bin/extra/udict new file mode 100755 index 0000000..77f9747 --- /dev/null +++ b/bin/extra/udict @@ -0,0 +1,12 @@ +#!/bin/sh + +[ $# -eq 0 ] && printf '%s\n' "Usage: +    udict some term" && exit 1 + +term="$@" + +term="$(printf '%s\n' "${term}" | sed 's/ /\\/g' )" + +curl -s "https://api.urbandictionary.com/v0/define?term=${term}" | +	jq -r '.list[0] | .word, .definition' | +	sed -e 's/\[/\o033[1m/g' -e 's/\]/\o033[0m/g' -e '1s/^.*$/\o033[1;4;34m&\o033[0m/' diff --git a/bin/guiscripts/clipo b/bin/guiscripts/clipo index 078cc13..e554c24 100755 --- a/bin/guiscripts/clipo +++ b/bin/guiscripts/clipo @@ -1,6 +1,6 @@  #!/bin/sh -[ "$1" = "-p" ] && arg='primary' +[ "$1" = "-p" ] && i='primary' j="-p"  if [ "$WAYLAND_DISPLAY" ]  then wl-paste -n "$1" -else xclip -o -selection "${arg:-clipboard}" -r +else xsel -o ${j:--b}  fi diff --git a/bin/guiscripts/clipp b/bin/guiscripts/clipp index c9e4f51..c3ee8f2 100755 --- a/bin/guiscripts/clipp +++ b/bin/guiscripts/clipp @@ -1,6 +1,6 @@  #!/bin/sh -[ "$1" = "-p" ] && arg='primary' +[ "$1" = "-p" ] && i='primary' j='-p'  if [ "$WAYLAND_DISPLAY" ] -then wl-copy -n $1 -else xclip -selection "${arg:-clipboard}" -r +then wl-copy -n $i +else xsel ${j:--b}  fi diff --git a/bin/guiscripts/mega.sh b/bin/guiscripts/mega.sh new file mode 100644 index 0000000..cafca0a --- /dev/null +++ b/bin/guiscripts/mega.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +URL="" + +if [[ $1 =~ ^https?:\/\/mega(\.co)?\.nz ]]; then +	URL="$1" +fi + +if [[ ! $URL ]]; then +	echo "Usage: ${0##*/} url" >&2 +	exit 1 +fi + +CURL="curl -Y 1 -y 10" + +missing=false +for cmd in openssl; do +	if [[ ! $(command -v "$cmd" 2>&1) ]]; then +		missing=true +		echo "${0##*/}: $cmd: command not found" >&2 +	fi +done +if $missing; then +	exit 1 +fi + +if [[ $URL =~ .*/file/[^#]*#[^#]* ]]; then +	id="${URL#*file/}"; id="${id%%#*}" +	key="${URL##*file/}"; key="${key##*#}" +else +	id="${URL#*!}"; id="${id%%!*}" +	key="${URL##*!}" +fi + +raw_hex=$(echo "${key}=" | tr '\-_' '+/' | tr -d ',' | base64 -d -i 2>/dev/null | od -v -An -t x1 | tr -d '\n ') +hex=$(printf "%016x" \ +	$(( 0x${raw_hex:0:16} ^ 0x${raw_hex:32:16} )) \ +	$(( 0x${raw_hex:16:16} ^ 0x${raw_hex:48:16} )) +) + +json=$($CURL -s -H 'Content-Type: application/json' -d '[{"a":"g", "g":"1", "p":"'"$id"'"}]' 'https://g.api.mega.co.nz/cs?id=&ak=') || exit 1; json="${json#"[{"}"; json="${json%"}]"}" +file_url="${json##*'"g":'}"; file_url="${file_url%%,*}"; file_url="${file_url//'"'/}" + +json=$($CURL -s -H 'Content-Type: application/json' -d '[{"a":"g", "p":"'"$id"'"}]' 'https://g.api.mega.co.nz/cs?id=&ak=') || exit 1 +at="${json##*'"at":'}"; at="${at%%,*}"; at="${at//'"'/}" + +json=$(echo "${at}==" | tr '\-_' '+/' | tr -d ',' | openssl enc -a -A -d -aes-128-cbc -K "$hex" -iv "00000000000000000000000000000000" -nopad | tr -d '\0'); json="${json#"MEGA{"}"; json="${json%"}"}" +file_name="${json##*'"n":'}" +if [[ $file_name == *,* ]]; then +	file_name="${file_name%%,*}" +fi +file_name="${file_name//'"'/}" + +aria2c -x 15 -o "$file_name" "$file_url" +cat "$file_name" | openssl enc -d -aes-128-ctr -K "$hex" -iv "${raw_hex:32:16}0000000000000000" > "temp.new" +mv -f temp.new "$file_name" + +echo "$file_url" +echo "$file_name" +echo "$hex" +echo "${raw_hex:32:16}0000000000000000" +sleep 5 +echo "Downloading... (press Ctrl + C to Cancel)" + +aria2c -x 16 -s 16 -o "$file_name" "$file_url" +cat "$file_name" | openssl enc -d -aes-128-ctr -K "$hex" -iv "${raw_hex:32:16}0000000000000000" > "temp.new" +mv -f temp.new "$file_name" diff --git a/bin/guiscripts/osurf b/bin/guiscripts/osurf new file mode 100755 index 0000000..6923848 --- /dev/null +++ b/bin/guiscripts/osurf @@ -0,0 +1,2 @@ +#!/bin/sh +tabbed -c -dn tabbed-surf -r 2 surf -e '' "$1" diff --git a/bin/guiscripts/osurf-fill b/bin/guiscripts/osurf-fill new file mode 100755 index 0000000..311c273 --- /dev/null +++ b/bin/guiscripts/osurf-fill @@ -0,0 +1,113 @@ +#!/bin/sh +# bitwarden dmenu script - based off of the autofill userscript from qutebrowser +# requires the fifo patch +# $1: winid + +fifodir="$HOME/.config/surf/fifo"  +if [ -z "${winid:=$1}" ] +then +    winid="$(osurfls | dmenu -c -F -i | cut -f1 -d' ')" +fi +[ "$winid" ] || exit 1 +fifo="$fifodir/$winid" +[ -p "$fifo" ] || exit 2 + +url="$(xprop -id "$winid" _SURF_URI | +	 cut -f 2 -d'"' | +	 sed 's,^.*://\([^/]*\)/.*,\1,' | +	 sed -r -e 's/^([^.]+)\.([^.]+)\.([^.]+)$/\2.\3/')" +[ "$url" ] || exit 3 +>&2 printf 'url: %s\n' "$url" + + +pass="$({ find $PASSWORD_STORE_DIR/websites/ -type f -name '*.gpg' | +	 grep "$url/" || echo; } | head -n 1 | +	 sed "s,$PASSWORD_STORE_DIR/,,;s/\.gpg$//" | +	 dmenu -c)" +[ $? -gt 0 ] && exit 4 + +if [ -z "$pass" ] +then + 	store="${PASSWORD_STORE_DIR:-$HOME/.password-store}" + 	while [ -d "$store/$file" ] +	do +		choice="$(find "$store/$file" \ +			-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$//' | +			dmenu -c)" +		[ "$choice" ] || exit 1 +		[ -z "$file" ] && file="$choice" || file="$file/$choice" +	done +	pass="$file" +fi +>&2 printf 'pass: %s\n' "$pass" + +herbe "filling ${pass#websites/}" & + +# Get password and username in variables with only one call to 'pass' +eval "$(pass show "$pass" | +	 sed -n "1s/'/'\\\\''/g;1s/.*/password='&'/p;s/^login: \?\(.\+\)/username='\1'/p")" +printf '%s : %s\n' "$username" "$password" + +javascript_escape() { +    printf '%s' "$1" | sed -s 's,['\''"\\\\],\\\\&,g' +} + +js() { +cat <<EOF +    function isVisible(elem) { +        var style = elem.ownerDocument.defaultView.getComputedStyle(elem, null); +        if (style.getPropertyValue("visibility") !== "visible" || +            style.getPropertyValue("display") === "none" || +            style.getPropertyValue("opacity") === "0") { +            return false; +        } +        return elem.offsetWidth > 0 && elem.offsetHeight > 0; +    }; +    function hasPasswordField(form) { +        var inputs = form.getElementsByTagName("input"); +        for (var j = 0; j < inputs.length; j++) { +            var input = inputs[j]; +            if (input.type == "password" || input.autocomplete == "password" || input.name == "password") { +                return true; +            } +        } +        return false; +    }; +    function loadData2Form (form) { +        var inputs = form.getElementsByTagName("input"); +        for (var j = 0; j < inputs.length; j++) { +            var input = inputs[j]; +            if (isVisible(input) && (input.type == "text" || input.type == "email")) { +                input.focus(); +                input.value = "$(javascript_escape "$username")"; +                input.blur(); +                console.log("user: $(javascript_escape "$username")") +            } +            if (input.type == "password" || input.name == "password" || input.autocomplete == "password" || input.id == "password" ) { +                input.focus(); +                input.value = "$(javascript_escape "$password")"; +                input.blur(); +                console.log("password: $(javascript_escape "$password")") +            } +            console.log(input) +        } +    }; +    var forms = document.getElementsByTagName("form"); +    for (i = 0; i < forms.length; i++) { +        if (hasPasswordField(forms[i])) { +            loadData2Form(forms[i]); +	    // forms[i].submit(); +        } +    } +EOF +} + +printjs() { +    js | sed 's,//.*$,,' | tr '\n' ' ' +} + +echo "inject $(printjs)" >> "$fifo" diff --git a/bin/guiscripts/osurfls b/bin/guiscripts/osurfls new file mode 100755 index 0000000..0abdd35 --- /dev/null +++ b/bin/guiscripts/osurfls @@ -0,0 +1,8 @@ +#!/bin/sh +find "$HOME/.config/surf/fifo" -type p -printf '%f\n' | +while read -r winid +do +	title="$(xprop -id "$winid" 2> /dev/null | awk -F'"' '/^_NET_WM_NAME/ {print $2}')" +	[ "$title" ] || continue +	printf '%s %s\n' "$winid" "$title" +done 
\ No newline at end of file diff --git a/bin/guiscripts/osurftabs b/bin/guiscripts/osurftabs new file mode 100755 index 0000000..d41424b --- /dev/null +++ b/bin/guiscripts/osurftabs @@ -0,0 +1,12 @@ +#!/bin/sh + +# list surf tabbed windows  + +# dependencies: lsw, dmenu, xprop +# expects the tabbed windows to be named 'tabbed-surf' +lsw | cut -f1 -d' ' | +	while read -r winid  +	do  +		[ "tabbed-surf" = "$(xprop -id "$winid" WM_CLASS | cut -f2 -d'"')" ] && +			 printf '%s %s\n' "$winid"  "$(xprop -id "$winid" WM_NAME | cut -f2 -d'"')" +	done diff --git a/bin/guiscripts/osurftxt b/bin/guiscripts/osurftxt new file mode 100755 index 0000000..ef60166 --- /dev/null +++ b/bin/guiscripts/osurftxt @@ -0,0 +1,22 @@ +#!/bin/sh + +# open all links in txt file into one tabbed surf + +# dependencies: surf, osurf, dmenu + +# $1: file path for non interactive use +if [ -z "$1" ] +then  +	d="$HOME/dl/txtabs" +	f="$(find "$d" -type f -printf '%f\n' | dmenu)" +	[ "$f" ] || exit 1 +	f="$d"/"$f" +else +	[ -f "$1" ] || exit 1 +	f="$1" +fi + +winid="$(osurf "$(head -n 1 "$f")")" +tail -n +2 "$f" | while read -r url; +	do surf -e "$winid" "$url" & +	done diff --git a/bin/guiscripts/record b/bin/guiscripts/record new file mode 100755 index 0000000..df4b6e6 --- /dev/null +++ b/bin/guiscripts/record @@ -0,0 +1,100 @@ +#!/bin/sh + +# record - record an area of the screen + +lock="/tmp/record.lock" + +# dependencies: ffmpeg, hacksaw (part), xwininfo & lsw (window), xdotool (active)  +# optional: +# 	- hacksaw: part +# 	- xwininfo, lsw, commander: window +# 	- xdotool: active +# 	- xdg-user-dir + +audio= + +# $1: width +# $2: height +# $3: x +# $4: y +# $5: output dir +# $6: output name +record_cmd() +{ +	if [ -f "$lock" ]  +	then +		>&2 printf 'already recording, please stop recording first\n' +		exit 1 +	else +		touch "$lock" +	fi + +	herbe "started recording." & +	w=$(($3 + $3 % 2)) +	h=$(($4 + $4 % 2)) +	ffmpeg $audio        \ +	    -v 16            \ +	    -r 30            \ +	    -f x11grab       \ +	    -s "${w}x${h}"   \ +	    -i ":0.0+$1,$2"  \ +	    -preset slow     \ +	    -c:v h264        \ +	    -pix_fmt yuv420p \ +	    -crf 20          \ +	    "$5/$6.mp4" +	printf '%s\n' "$5/$6.mp4" +	rm -f "$lock" +	herbe "stopped recording." &  +} + +if [ -d "$1" ] +then +	dir="$1"  +	shift +else  +	dir="$(which xdg-user-dir > /dev/null 2>&1 && xdg-user-dir VIDEOS)" +	[ "$dir" ] && dir="$dir/records" || dir="$HOME/vids/records" +fi +mkdir -p "$dir" + +if [ "$1" = "-a" ] +then +	audio="-f pulse -ac 2 -i default" +	shift +fi + +if [ "$1" = "-l" ] +then +	find vids/records/ -type f | sort | tail -n 1 +	exit +fi + +current=$(date +%F_%H-%M-%S) + +[ "$1" ] && option="$1" || option="$(printf 'active\nwindow\npart\nstop\nfull\naudio' | commander -c)" +case "$option" in +    active) +        record_cmd $(xwininfo -id "$(xdotool getactivewindow)" | +            sed -e '/Absolute\|Width:\|Height:/!d;s/.*:\s*//' | tr '\n' ' ') $dir $current +        ;; + +    window) +    	winid="$(lsw | commander -cxl | cut -d' ' -f1)" +    	[ "$winid" ] || exit 1 +    	values="$(xwininfo -id "$winid" | sed -e '/Absolute\|Width:\|Height:/!d;s/.*:\s*//' | tr '\n' ' ')" +	[ "$values" ] || exit 1 +        record_cmd $values $dir $current +        ;; +         +    part)  +        hacksaw | { +            IFS=+x read -r w h x y +            record_cmd $w $h $x $y $dir $current +        } +        ;; +    stop) kill "$(pgrep ffmpeg | xargs ps | grep 'x11grab' | awk '{print $1}')"; rm -f "$lock" ;; +    full) record_cmd 0 0 1920 1080 $dir $current ;; +    audio) $0 -a; exit ;; +    help|*) >&2 printf 'record [dir] (active|window|part|stop|full)\n' ;; +esac diff --git a/bin/guiscripts/setbg b/bin/guiscripts/setbg new file mode 100755 index 0000000..a4109ab --- /dev/null +++ b/bin/guiscripts/setbg @@ -0,0 +1,5 @@ +#!/bin/sh +cd "$HOME/pics/wallpapers" || exit 1 +bg="$(find . -type f -printf '%f\n' | sed 's@^\./@@' | dmenu -c -x)" +[ "$bg" ] || exit 1 +feh --no-fehbg --bg-scale "$bg" diff --git a/bin/guiscripts/startw b/bin/guiscripts/startw index 0383f48..dbf4450 100755 --- a/bin/guiscripts/startw +++ b/bin/guiscripts/startw @@ -1,8 +1,4 @@  #!/bin/sh -  eval "$(keychain --dir "$XDG_CONFIG_HOME/keychain" --eval --quiet --agents gpg,ssh)"  eval "$(keychain --dir "$XDG_CONFIG_HOME/keychain" --eval --quiet --agents gpg 3A626DD20A32EB2E5DD9CE71CFD9ABC97158CD5D 2> /dev/null)" - -(cd ~/.config/waybar/ && ln -sf hyprland.jsonc config.jsonc) -  Hyprland diff --git a/bin/guiscripts/cps b/bin/guiscripts/swclip index 1cae135..1cae135 100755 --- a/bin/guiscripts/cps +++ b/bin/guiscripts/swclip diff --git a/bin/guiscripts/yt b/bin/guiscripts/yt new file mode 100755 index 0000000..72f6e92 --- /dev/null +++ b/bin/guiscripts/yt @@ -0,0 +1,4 @@ +#!/bin/sh +link="$(ytfzf -D -I l)" +[ "$link" ] || exit 1 +yt-dlp $@ -o - "$link" | mpv - 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 diff --git a/checkpoint.sh b/checkpoint.sh new file mode 100755 index 0000000..62c138c --- /dev/null +++ b/checkpoint.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +git commit -m 'checkpoint' +keyadd db +git push diff --git a/config/X/x11/xinitrc b/config/X/x11/xinitrc index bc1824a..8b3cf2b 100755 --- a/config/X/x11/xinitrc +++ b/config/X/x11/xinitrc @@ -22,7 +22,7 @@ export MENUCMD="dmenu"  export IMAGE="feh"  xcompmgr &  feh --no-fehbg --bg-scale ~/pics/wallpaper -setxkbmap us -option ctrl:swapcaps,altwin:menu_win -variant colemak +setxkbmap colemak -option ctrl:swapcaps,altwin:menu_win  # xautolock -locker slock &  gammastep -m randr &  # dunst & diff --git a/config/common/mpv/mpv.conf b/config/common/mpv/mpv.conf index 1fd96da..2e7318e 100755 --- a/config/common/mpv/mpv.conf +++ b/config/common/mpv/mpv.conf @@ -17,10 +17,11 @@ ytdl-raw-options=extractor-args="youtube:player-client=android"  # Default demuxer is 150/75 MB, note that this uses RAM so set a reasonable amount.  # 150MB, Max pre-load for network streams (1 MiB = 1048576 Bytes). -demuxer-max-bytes=150000000  +demuxer-max-bytes=150MiB +demuxer-readahead-secs=20  # 75MB, Max loaded video kept after playback. -demuxer-max-back-bytes=75000000  +demuxer-max-back-bytes=75MiB  # Force stream to be seekable even if disabled.  force-seekable=yes  diff --git a/config/common/mpv/scripts/mpv-skipsilence b/config/common/mpv/scripts/mpv-skipsilence new file mode 160000 +Subproject 2d6fd04dca3c70edf816e9af6fc30b302eb1c7a diff --git a/config/common/newsraft/feeds b/config/common/newsraft/feeds index 77e5420..683490c 100644 --- a/config/common/newsraft/feeds +++ b/config/common/newsraft/feeds @@ -25,8 +25,12 @@ https://arthurmelton.com/blogs.rss "Arthur Melton's blog'"  @ Linux  https://www.youtube.com/feeds/videos.xml?channel_id=UC-V8FVQCUpRRUPNClviki3w "Luke Smith" -https://youtube.com/feeds/video.xml?channel_id=UCngn7SVujlvskHRvRKc1cTw "Bugswriter" -https://youtube.com/feeds/video.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg "DistroTube" +https://www.youtube.com/feeds/videos.xml?channel_id=UCngn7SVujlvskHRvRKc1cTw "Bugswriter" +https://www.youtube.com/feeds/videos.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg "DistroTube" +https://www.youtube.com/feeds/videos.xml?channel_id=UCuGS5mN1_CpPzuOUAu2LluA "NixHero" +https://www.youtube.com/feeds/videos.xml?channel_id=UCWQaM7SpSECp9FELz-cHzuQ "Dreams of Code" +https://www.youtube.com/feeds/videos.xml?channel_id=UCCuoqzrsHlwv1YyPKLuMDUQ "Jonathan Blow" +  @ Entertainment  https://www.youtube.com/feeds/videos.xml?channel_id=UCi8C7TNs2ohrc6hnRQ5Sn2w "Programmers are also human" @@ -37,5 +41,5 @@ https://www.youtube.com/feeds/videos.xml?channel_id=UCVk4b-svNJoeytrrlOixebQ "Th  https://www.youtube.com/feeds/videos.xml?channel_id=UCd3dNckv1Za2coSaHGHl5aA "TJ DeVries"  @ News -https://rss.rtbf.be/article/rss/highlight_rtbf_info.xml?source=internal -https://news.ycombinator.com/rss +https://rss.rtbf.be/article/rss/highlight_rtbf_info.xml?source=internal "RTBF" +https://news.ycombinator.com/rss "HackerNews" diff --git a/config/common/tmux/tmux.conf b/config/common/tmux/tmux.conf index d8a4969..8cf10e5 100755 --- a/config/common/tmux/tmux.conf +++ b/config/common/tmux/tmux.conf @@ -43,11 +43,11 @@ bind  X     confirm -p "Kill Window?"   kill-window  bind  M-x   confirm -p "Kill Session?"  kill-session  bind  M-X   confirm -p "Kill Server?"   kill-server  # Restart pane -bind k run -C "respawn-pane -k; send-keys !! 'C-j'" -bind K respawn-pane -k +bind C-r run -C "respawn-pane -k; send-keys !! 'C-j'" +bind C-R respawn-pane -k  # Splitting  bind v split-window -h -c "#{pane_current_path}" -bind h split-window -v -c "#{pane_current_path}" +bind s split-window -v -c "#{pane_current_path}"  # Swapping left and right a la vim  bind -n M-H swap-pane -U  bind -n M-L swap-pane -D @@ -64,8 +64,10 @@ bind b break-pane -t :  # Reset length and shit  bind z select-layout main-vertical - - +bind-key h select-pane -L +bind-key j select-pane -D +bind-key k select-pane -U +bind-key l select-pane -R  # Pane navigating with h|j|k|l a la vim  # Smart pane switching with awareness of Vim splits. @@ -88,9 +90,6 @@ bind-key -T copy-mode-vi 'M-k' select-pane -U  bind-key -T copy-mode-vi 'M-l' select-pane -R  bind-key -T copy-mode-vi 'M-\' select-pane -l - - -  bind -n M-u previous-window  bind -n M-i next-window  # Session navigeting with S-M-u|i @@ -121,7 +120,7 @@ set -g status on  #+--- Layout ---+  set -g set-titles-string "[#S: #W] #T"  set -g set-titles on -set -g status-position top +set -g status-position bottom  set -g window-status-current-style "underscore"  set -g status-justify left  set -g status-left-length 16 diff --git a/config/essentials/git/config b/config/essentials/git/config index cb16983..99cf21e 100644 --- a/config/essentials/git/config +++ b/config/essentials/git/config @@ -8,9 +8,9 @@  	autosetupremote = true  [pull]  	rebase = false -[commit] -	gpgsign = true  [merge]  	ff = false  [alias]  	change-commits = "!f() { VAR1=$1; VAR='$'$1; OLD=$2; NEW=$3; echo \"Are you sure for replace $VAR  $OLD => $NEW ?(Y/N)\";read OK;if [ \"$OK\" = 'Y' ] ; then shift 3; git filter-branch  --env-filter \"if [ \\\"${VAR}\\\" = '$OLD' ]; then export $VAR1='$NEW';echo 'to $NEW'; fi\" $@; fi;};  f " +[commit] +	gpgsign = true diff --git a/config/essentials/shell/aliases.sh b/config/essentials/shell/aliases.sh index 5db3d65..fdd9d17 100644 --- a/config/essentials/shell/aliases.sh +++ b/config/essentials/shell/aliases.sh @@ -2,7 +2,7 @@  # s/alias \([^-]\)/alias -g \1  # The most important one -alias vi='nvim' +alias vi='vis'  which z > /dev/null 2>&1 &&      alias cd='z' @@ -83,7 +83,7 @@ alias lst2='ls --tree -L2'  alias lst3='ls --tree -L3'  alias ls.='ls -dl .*'  which eza >/dev/null 2>&1 && -	alias ls='eza --sort extension --group-directories-first --no-time --git' || +	alias ls='eza --sort extension --group-directories-first --git' ||  	alias ls='ls --color --group-directories-first --sort=extension'  # pacman aliases @@ -197,7 +197,7 @@ alias gdate='date +%y_%m_%d-%T'  alias tpid='tail -f /dev/null --pid'  alias pwdcp='pwd | clipp'  alias gw="grep -ri" -alias srcsupd='echo ~/src/{installdrier,dotfiles,password-store} ~/proj/suckless/*/ ~/proj/personal/scripts/*/ ~/.config/emacs ~/.config/nvim | supd' +alias srcsupd='echo ~/src/{installdrier,dotfiles,password-store} ~/proj/suckless/*/ ~/.config/emacs ~/.config/nvim | supd'  # systemctl aliases  alias smc='systemctl' @@ -341,6 +341,12 @@ alias ddeps='pactree -r -d 1'  alias update-mirrors='reflector -p https | rankmirrors -n 10 -p -w - | doas tee /etc/pacman.d/mirrorlist'  alias tmpd='cd $(mktemp -d)' +alias tmpf='$EDITOR $(mktemp)'  alias brs='$BROWSER'  which bat > /dev/null 2>&1 &&      alias cat="bat -p" + +alias glf='git pull --ff' +alias glnf='git pull --no-ff' +alias quickvms='/media/cricket/vms/quickemu/"$(find '\''/media/cricket/vms/quickemu/'\'' -type f -iname '\''*.conf'\'' -printf '\''%f +'\'' | sed '\''s/\.conf$//'\'' | fzf)".conf 2> /dev/null' diff --git a/config/essentials/shell/functions.sh b/config/essentials/shell/functions.sh index 3676f26..8e51135 100644 --- a/config/essentials/shell/functions.sh +++ b/config/essentials/shell/functions.sh @@ -45,12 +45,12 @@ o()  	test "$1" && shift  	test -f "$f" && $EDITOR $@ "$f"  } -go() +og()  {  	_googoo_fzf_opt "$1"  	cd "$(goo d "$dest" | fzf $opt)"  } -ogo() +oog()  {  	_googoo_fzf_opt "$1"  	cd "$(dirname "$(goo f "$dest" | fzf $opt)")" @@ -109,7 +109,7 @@ clip() {  	then  		echo -n "$@" | wl-copy  	else -		echo -n "$@" | xclip -selection clipboard -rmlastnl +		echo -n "$@" | xsel -b  	fi  } @@ -241,6 +241,7 @@ pacsize()  mime-default ()  { +	mime=      [ "${mime:=$1}" ] ||          mime="$(find /usr/share/applications/ -iname '*.desktop' -printf '%f\n' |              sed 's/\.desktop$//' | @@ -357,3 +358,23 @@ ssh_port()      ssh -f -N -L 0.0.0.0:"$3":localhost:"$1" "$2"      >&2 printf "Forwarded port '%s' on '%s' to '%s'.\n" "$1" "$2" "$3"  } +ffconcat () { +	tmp=$(mktemp -p . ffconcat.XXXXX)  +	sed 's/.*/file &/' > "$tmp" +	ffmpeg -y -f concat -safe 0 -i $tmp -c copy "$1" +	rm $tmp +} + +# wrap ssh and add key if exists +ssh() { +	if [ "$#" -gt 1 ]  +	then +		/usr/bin/ssh $@ +		return +	fi + +	grep -E "Host\s+$1" $HOME/.ssh/config > /dev/null 2>&1 && +		keyadd "$1" > /dev/null 2>&1 +	/usr/bin/ssh "$1" +} + diff --git a/config/essentials/vis/plugins/vis-cursors b/config/essentials/vis/plugins/vis-cursors new file mode 160000 +Subproject f86c584fc2d4a2bab47df0cd5d187dd81fb7185 diff --git a/config/essentials/vis/plugins/vis-title b/config/essentials/vis/plugins/vis-title new file mode 160000 +Subproject 9c808f7e71b43aca31dee8553dcfce2214d7fc4 diff --git a/config/essentials/vis/themes/nord.lua b/config/essentials/vis/themes/nord.lua new file mode 100644 index 0000000..a21f0fa --- /dev/null +++ b/config/essentials/vis/themes/nord.lua @@ -0,0 +1,123 @@ +-- base16-vis (https://github.com/pshevtsov/base16-vis) +-- by Petr Shevtsov +-- Nord scheme by arcticicestudio + +local lexers = vis.lexers + +local colors = { +	['bg'] = '#2E3440', +	['black'] = '#3B4252', +	['light_black'] = '#434C5E', +	['dark_gray'] = '#4C566A', +	['gray'] = '#D8DEE9', +	['light_gray'] = '#616E88', +	['fg'] = '#E5E9F0', +	['white'] = '#ECEFF4', +	['turquoise'] = '#8FBCBB', +	['light_cyan'] = '#88C0D0', +	['cyan'] = '#81A1C1', +	['blue'] = '#5E81AC', +	['red'] = '#BF616A', +	['orange'] = '#D08770', +	['yellow'] = '#EBCB8B', +	['green'] = '#A3BE8C', +	['magenta'] = '#B48EAD', +} + +lexers.colors = colors + +local fg = 'fore:'..colors.fg +local bg = 'back:'..colors.bg + +lexers.STYLE_DEFAULT = bg..','..fg +lexers.STYLE_NOTHING = bg +lexers.STYLE_CLASS = 'fore:'..colors.blue +lexers.STYLE_COMMENT = 'fore:'..colors.light_gray..',italics' +lexers.STYLE_CONSTANT = 'fore:'..colors.cyan +lexers.STYLE_DEFINITION = 'fore:'..colors.green +lexers.STYLE_ERROR = 'fore:'..colors.light_cyan..',italics' +lexers.STYLE_FUNCTION = 'fore:'..colors.light_cyan..',bold' +lexers.STYLE_HEADING = 'fore:'..colors.bg..',back:'..colors.yellow +lexers.STYLE_KEYWORD = 'fore:'..colors.cyan..',bold' +lexers.STYLE_LABEL = 'fore:'..colors.blue +lexers.STYLE_NUMBER = 'fore:'..colors.magenta +lexers.STYLE_OPERATOR = 'fore:'..colors.light_cyan +lexers.STYLE_REGEX = 'fore:'..colors.orange +lexers.STYLE_STRING = 'fore:'..colors.green +lexers.STYLE_PREPROCESSOR = 'fore:'..colors.blue +lexers.STYLE_TAG = 'fore:'..colors.blue +lexers.STYLE_TYPE = 'fore:'..colors.cyan +lexers.STYLE_VARIABLE = 'fore:'..colors.cyan..',bold' +lexers.STYLE_WHITESPACE = 'fore:'..colors.light_black +lexers.STYLE_EMBEDDED = 'fore:'..colors.magenta +lexers.STYLE_IDENTIFIER = fg..',bold' + +lexers.STYLE_LINENUMBER = 'fore:'..colors.light_black..',back:'..colors.bg +lexers.STYLE_CURSOR = 'fore:'..colors.bg..',back:'..colors.fg +lexers.STYLE_CURSOR_PRIMARY = 'fore:'..colors.bg..',back:'..colors.fg +lexers.STYLE_CURSOR_LINE = 'back:'..colors.black +lexers.STYLE_COLOR_COLUMN = 'back:'..colors.black +lexers.STYLE_SELECTION = 'back:'..colors.light_black +lexers.STYLE_STATUS = 'fore:'..colors.gray..',back:'..colors.black +lexers.STYLE_STATUS_FOCUSED = 'fore:'..colors.cyan..',back:'..colors.black +lexers.STYLE_SEPARATOR = lexers.STYLE_DEFAULT +lexers.STYLE_INFO = 'fore:default,back:default,bold' +lexers.STYLE_EOF = '' + +-- lexer specific styles + +-- Diff +lexers.STYLE_ADDITION = 'back:'..colors.green..',fore:'..colors.bg +lexers.STYLE_DELETION = 'back:'..colors.red..',fore:'..colors.bg +lexers.STYLE_CHANGE = 'back:'..colors.yellow..',fore:'..colors.bg + +-- CSS +lexers.STYLE_PROPERTY = lexers.STYLE_ATTRIBUTE +lexers.STYLE_PSEUDOCLASS = '' +lexers.STYLE_PSEUDOELEMENT = '' + +-- HTML +lexers.STYLE_TAG_UNKNOWN = lexers.STYLE_TAG .. ',italics' +lexers.STYLE_ATTRIBUTE_UNKNOWN = lexers.STYLE_ATTRIBUTE .. ',italics' + +-- Latex, TeX, and Texinfo +lexers.STYLE_COMMAND = lexers.STYLE_KEYWORD +lexers.STYLE_COMMAND_SECTION = lexers.STYLE_CLASS +lexers.STYLE_ENVIRONMENT = lexers.STYLE_TYPE +lexers.STYLE_ENVIRONMENT_MATH = lexers.STYLE_NUMBER + +-- Makefile +lexers.STYLE_TARGET = '' + +-- Markdown +lexers.STYLE_HR = '' +lexers.STYLE_HEADING_H1 = 'fore:'..colors.orange..',bold' +lexers.STYLE_HEADING_H2 = 'fore:'..colors.red..',bold' +for i = 3,6 do lexers['STYLE_HEADING_H'..i] = 'fore:'..colors.magenta..',bold' end +lexers.STYLE_BOLD = 'bold' +lexers.STYLE_ITALIC = 'italics' +lexers.STYLE_LIST = lexers.STYLE_KEYWORD +lexers.STYLE_LINK = 'fore:'..colors.yellow..',italics' +lexers.STYLE_REFERENCE = 'fore:'..colors.blue +lexers.STYLE_CODE = 'back:'..colors.black..',fore:'..colors.turquoise + +-- Output +lexers.STYE_FILENAME = 'bold' +lexers.STYLE_LINE = 'fore:'..colors.green +lexers.STYLE_COLUMN = 'underline' +lexers.STYLE_MESSAGE = '' + +-- Python +lexers.STYLE_KEYWORD_SOFT = '' + +-- YAML +lexers.STYLE_ERROR_INDENT = 'back:'..colors.red + + +-- GO +lexers.STYLE_CONSTANT_BUILTIN = 'fore:'..colors.yellow +lexers.STYLE_FUNCTION_METHOD = 'fore:'..colors.light_cyan +lexers.STYLE_FUNCTION_BUILTIN = 'fore:'..colors.light_cyan..',bold' + +-- Lua +lexers.STYLE_ATTRIBUTE = 'fore:'..colors.yellow..',bold' diff --git a/config/essentials/vis/visrc.lua b/config/essentials/vis/visrc.lua new file mode 100644 index 0000000..a424613 --- /dev/null +++ b/config/essentials/vis/visrc.lua @@ -0,0 +1,84 @@ +------------------------------------ +--- LIBRARIES +------------------------------------ + +require('vis') +require('plugins/vis-cursors') +require('plugins/vis-title') + +------------------------------------ +--- EVENTS +------------------------------------ + +vis.events.subscribe(vis.events.INIT, function() +	vis.options.ignorecase = true +	vis.options.autoindent = true +	vis.options.shell = "/bin/sh" +	theme = "nord" +	vis:command("set theme " .. theme) +end) + +vis.events.subscribe(vis.events.WIN_OPEN, function(win) -- luacheck: no unused args +	win.options.relativenumbers = true +end) + +------------------------------------ +--- FUNCTIONS +------------------------------------ + +function map_cmd(mode, map, command, help) +	vis:map(mode, map, function() +		vis:command(command) +	end, help) +end + +function map_cmd_restore(mode, map, command, help) +	vis:map(mode, map, function() +		if (mode == vis.modes.INSERT) then +			vis:feedkeys("<Escape>") +		end +			 +		vis:feedkeys("m") +		vis:command(command) +		vis:feedkeys("M") + +		if (mode == vis.modes.INSERT) then +			vis:feedkeys("i") +		end  +	end, help) +end + +------------------------------------ +--- VARIABLES +------------------------------------ + +local m = vis.modes + +------------------------------------ +--- COMMANDS +------------------------------------ + +vis:command_register("Q", function(argv, force, win, selection, range) +	vis:command("qa!") +end, "Quit all") + +------------------------------------- +--- MAPPINGS +------------------------------------- + +map_cmd_restore(m.NORMAL, " r", "e $vis_filepath", "Reload active file") + +map_cmd(m.NORMAL, " c", "e ~/.config/vis/visrc.lua", "Edit config file") +map_cmd(m.NORMAL, " q", "q!", "Quit (force)") +map_cmd(m.NORMAL, " s", "!doas vis $vis_filepath", "Edit as superuser") +map_cmd(m.NORMAL, " w", "w", "Write") +map_cmd(m.NORMAL, " x", "!chmod u+x $vis_filepath", "Make active file executable") + +vis:map(m.NORMAL, " eh", function() +	vis:command("!lowdown $vis_filepath > ${vis_filepath%.md}.html") +	vis:info("exported.") +end, "Export markdown to html") +vis:map(m.NORMAL, " nl", function() vis:feedkeys(":<seq -f '%0.0f. ' 1 ") end, "Insert numbered list") + + +-- select markdown list element:	,x/^(\d+\.|[-*])\s+.+\n(^ .+\n)*/ diff --git a/config/essentials/zsh/.zshrc b/config/essentials/zsh/.zshrc index 2b3ae1a..5981fd9 100644 --- a/config/essentials/zsh/.zshrc +++ b/config/essentials/zsh/.zshrc @@ -33,20 +33,16 @@ eval "$(zoxide init zsh)"  [ -f "$HOME/.local/share/zap/zap.zsh" ] && source "$HOME/.local/share/zap/zap.zsh"  # plug "MichaelAquilina/zsh-you-should-use"  plug "chivalryq/git-alias" -plug "kutsan/zsh-system-clipboard"  # plug "marlonrichert/zsh-autocomplete" -plug "xPMo/zsh-toggle-command-prefix"  plug "zap-zsh/fzf" -plug "zap-zsh/vim"  plug "zdharma-continuum/fast-syntax-highlighting"  plug "zsh-users/zsh-autosuggestions"  plug "zsh-users/zsh-completions" -plug "zsh-users/zsh-history-substring-search"  plug "MichaelAquilina/zsh-auto-notify"  export AUTO_NOTIFY_TITLE="zsh"  export AUTO_NOTIFY_BODY="%command [%exit_code]" -AUTO_NOTIFY_IGNORE+=("gurk" "ttyper" "pulsemixer" "tmux" "btop" "vis") +AUTO_NOTIFY_IGNORE+=("gurk" "ttyper" "pulsemixer" "tmux" "btop" "vis" "clock")  # Substring search settings  export HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND="bg=blue,fg=black,bold" @@ -63,7 +59,7 @@ fi  # Add nnn shell level to prompt -[ -n "$NNNLVL" ] && PS1="N$NNNLVL $PS1" +[ -n "$NNNLVL" ] && PS1="N$NNNLVL$PS1"  # cd on nnn quiting  nnn_cd () diff --git a/config/essentials/zsh/comp.zsh b/config/essentials/zsh/comp.zsh index 4836111..076882d 100644 --- a/config/essentials/zsh/comp.zsh +++ b/config/essentials/zsh/comp.zsh @@ -2,11 +2,10 @@  # Find most of the stuff at https://github.com/zap-zsh/completions  zmodload zsh/complist -autoload -Uz compinit; compinit  zstyle ':compinstall' filename '/home/aluc/.zshrc'  # cache -zstyle ':completion:*' use-cache on  zstyle ':completion:*' cache-path "$ZDOTDIR/zcompcache" +zstyle ':completion:*' use-cache on  # completers  zstyle ':completion:*' completer _extensions _complete @@ -37,6 +36,9 @@ zstyle ':completion:*' keep-prefix true  # ui  zstyle ':completion:*' menu select +ZSH_COMPDUMP="$ZDOTDIR"/zcompcache +autoload -Uz compinit; compinit -d "$ZSH_COMPDUMP" +  _dotnet_zsh_complete()  {    local completions=("$(dotnet complete "$words")") diff --git a/config/extra/qrclip b/config/extra/qrclip deleted file mode 100755 index 2f5da5c..0000000 --- a/config/extra/qrclip +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -if [ "$WAYLAND_DISPLAY" ] -then -	which wl-copy > /dev/null || exit 1 -	clipp () {  -		wl-copy -	} -	clipo () {  -		wl-paste -	} -else -	which xclip > /dev/null || exit 1 -	clipp () {  -		xclip -selection clipboard -r -	} -	clipo () {  -		xclip -o -selection clipboard -r -	} -fi - -case $1 in -	'-o') -		qrencode -s 16 "$(clipo)" -o - | -			imv -w "imv - $(clipo)" - ;; -	'-s') -		qrencode -s 16 "https://duckduckgo.com/$(clipo)" -o - | -			imv -w "imv - search $(clipo)" - ;; -esac diff --git a/config/home/.zshenv b/config/home/.zshenv index 1af14cf..a87f01d 100644 --- a/config/home/.zshenv +++ b/config/home/.zshenv @@ -1,8 +1,8 @@  #!/bin/zsh -export EDITOR="nvim" -export VISUAL="nvim" +export EDITOR="vis" +export VISUAL="vis" -export BROWSER="surf" +export BROWSER="osurf"  export VIEWER="zathura"  export PLAYER="mpv" @@ -81,8 +81,8 @@ export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS'  export LESS="-i -r"  # Colored manpages -export MANPAGER="less -R --use-color -Dd+r -Du+b" -export MANROFFOPT="-P -c" +# export MANPAGER="less -R --use-color -Dd+r -Du+b" +# export MANROFFOPT="-P -c"  export CM_LAUNCHER="commander -c" @@ -92,3 +92,7 @@ export PATH="$HOME/go/bin:$PATH"  export PATH="$XDG_CONFIG_HOME/cargo/bin:$PATH"  export PATH="$PATH:./node_modules/.bin"  export PATH="$PATH:$HOME/.dotnet/tools" +export PATH="$PATH:$GOPATH/bin" + +export PLAN9=/usr/lib/plan9 +export PATH="$PATH:$PLAN9/bin" diff --git a/config/theme/gtk-2.0/gtkfilechooser.ini b/config/theme/gtk-2.0/gtkfilechooser.ini index f477cff..bfbffb9 100644 --- a/config/theme/gtk-2.0/gtkfilechooser.ini +++ b/config/theme/gtk-2.0/gtkfilechooser.ini @@ -2,8 +2,8 @@  LocationMode=path-bar  ShowHidden=false  ShowSizeColumn=true -GeometryX=0 -GeometryY=0 +GeometryX=567 +GeometryY=160  GeometryWidth=836  GeometryHeight=626  SortColumn=name diff --git a/config/wayland/foot/foot.ini b/config/wayland/foot/foot.ini index 00e7a37..a1fc1e8 100644 --- a/config/wayland/foot/foot.ini +++ b/config/wayland/foot/foot.ini @@ -9,7 +9,7 @@ term=xterm-256color  title=""  # locked-title=no -font=monospace:size=11 +font=monospace:size=10.5  # font-bold=<bold variant of regular font>  # font-italic=<italic variant of regular font>  # font-bold-italic=<bold+italic variant of regular font> diff --git a/config/wayland/hypr/hyprland.conf b/config/wayland/hypr/hyprland.conf index eb232c9..d084eb9 100644 --- a/config/wayland/hypr/hyprland.conf +++ b/config/wayland/hypr/hyprland.conf @@ -8,9 +8,9 @@ exec-once = $HOME/.config/hypr/startup.sh  input {      kb_layout = us -    kb_variant = +    kb_variant = colemak      kb_model = -    kb_options = ctrl:swapcaps +    kb_options = ctrl:swapcaps,altwin:menu_win      kb_rules =      follow_mouse = 2 @@ -31,7 +31,7 @@ general {      layout = dwindle -	cursor_inactive_timeout = 0 +	# cursor_inactive_timeout = 0  }  misc { diff --git a/config/wayland/waybar/colors.css b/config/wayland/waybar/colors.css deleted file mode 120000 index 38b29a4..0000000 --- a/config/wayland/waybar/colors.css +++ /dev/null @@ -1 +0,0 @@ -/home/aluc/.config/waybar/colors/colors-nord
\ No newline at end of file diff --git a/config/wayland/waybar/config.jsonc b/config/wayland/waybar/config.jsonc index 24065d3..aa93297 120000..100644 --- a/config/wayland/waybar/config.jsonc +++ b/config/wayland/waybar/config.jsonc @@ -1 +1,16 @@ -hyprland.jsonc
\ No newline at end of file +{ +	"modules-left": ["hyprland/workspaces", "custom/layout", "hyprland/window"], +	"modules-right": ["custom/status"], +	"hyprland/window": { +		"format": " {} " +	}, +	"custom/layout": {  +		"format": " []= ", +		"interval": "once", +	}, +	"custom/status": {  +		"exec": "~/.config/waybar/status.sh", +		"format": " {} ", +		"interval": 1 +	} +}  | 
