From 5eb0dbf136a9ad582192e003b7573a080514f063 Mon Sep 17 00:00:00 2001 From: Xiao Pan Date: Tue, 9 Jan 2024 04:09:59 -0800 Subject: init from config_local_arch personal shell scripts git log history see https://git.flylightning.xyz/config_local_arch/tree/home/xyz/.local/bin?id=d266c511cffb7eeb20bf1e4610d9d32557b7d0e6 --- alarm | 11 +++++++++ backlight | 23 +++++++++++++++++++ bell | 7 ++++++ ccgsl | 7 ++++++ cfg | 29 +++++++++++++++++++++++ chmodef | 6 +++++ curlqb | 27 ++++++++++++++++++++++ dateft | 29 +++++++++++++++++++++++ dirnameall | 19 ++++++++++++++++ gita | 17 ++++++++++++++ gitfork | 10 ++++++++ gitmetap | 17 ++++++++++++++ gitmetar | 7 ++++++ gitpu | 19 ++++++++++++++++ grrc | 4 ++++ il | 6 +++++ lastarg | 5 ++++ loop | 15 ++++++++++++ lsp | 3 +++ mll | 6 +++++ mmi | 27 ++++++++++++++++++++++ mpra | 44 +++++++++++++++++++++++++++++++++++ mpva | 17 ++++++++++++++ mpvy | 44 +++++++++++++++++++++++++++++++++++ mvln | 27 ++++++++++++++++++++++ mvtr | 11 +++++++++ mvtu | 13 +++++++++++ news | 31 +++++++++++++++++++++++++ o | 27 ++++++++++++++++++++++ orgext | 18 +++++++++++++++ pa | 8 +++++++ pq | 13 +++++++++++ px | 10 ++++++++ qg | 15 ++++++++++++ qw | 16 +++++++++++++ rate | 11 +++++++++ reco | 28 +++++++++++++++++++++++ rfp | 11 +++++++++ sbar | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ta | 5 ++++ time-uuid | 6 +++++ topa | 8 +++++++ vinfo | 4 ++++ wh | 11 +++++++++ wtr | 43 +++++++++++++++++++++++++++++++++++ xmq | 3 +++ 46 files changed, 795 insertions(+) create mode 100755 alarm create mode 100755 backlight create mode 100755 bell create mode 100755 ccgsl create mode 100755 cfg create mode 100755 chmodef create mode 100755 curlqb create mode 100755 dateft create mode 100755 dirnameall create mode 100755 gita create mode 100755 gitfork create mode 100755 gitmetap create mode 100755 gitmetar create mode 100755 gitpu create mode 100755 grrc create mode 100755 il create mode 100755 lastarg create mode 100755 loop create mode 100755 lsp create mode 100755 mll create mode 100755 mmi create mode 100755 mpra create mode 100755 mpva create mode 100755 mpvy create mode 100755 mvln create mode 100755 mvtr create mode 100755 mvtu create mode 100755 news create mode 100755 o create mode 100755 orgext create mode 100755 pa create mode 100755 pq create mode 100755 px create mode 100755 qg create mode 100755 qw create mode 100755 rate create mode 100755 reco create mode 100755 rfp create mode 100755 sbar create mode 100755 ta create mode 100755 time-uuid create mode 100755 topa create mode 100755 vinfo create mode 100755 wh create mode 100755 wtr create mode 100755 xmq diff --git a/alarm b/alarm new file mode 100755 index 0000000..5342e7d --- /dev/null +++ b/alarm @@ -0,0 +1,11 @@ +#!/bin/sh + +min="$1" +[ "$1" ] && shift +printf "notify-send -u critical %s; bell" "$(/usr/bin/printf '%q ' "${@:-alarm}")" | at now + "${min:-0}" minutes && [ "$min" ] && [ "$min" -ne 0 ] && notify-send "Successfully Scheduled" + +# at used to not like string like 'Boiling Water!', don't know why now it works, if see similar issue, use folllowing codes +#at now + "$1" minutes << EOF && notify-send 'Successfully Scheduled' +#notify-send -u critical "${2:-alarm}" +#bell +#EOF diff --git a/backlight b/backlight new file mode 100755 index 0000000..3de87f5 --- /dev/null +++ b/backlight @@ -0,0 +1,23 @@ +#!/bin/sh + +brightness=$(cat /sys/class/backlight/intel_backlight/brightness) +max_brightness=$(cat /sys/class/backlight/intel_backlight/max_brightness) +step=$((max_brightness/20)) + +case "$1" in + '-u') + case "$brightness" in + 0) echo 1;; + 1) echo "$step";; + *) echo "$((brightness+step))";; + esac + ;; + '-d') + case "$brightness" in + 1) echo 0;; + "$step") echo 1;; + *) echo "$((brightness-step))";; + esac + ;; + *) exit 1;; +esac > /sys/class/backlight/intel_backlight/brightness diff --git a/bell b/bell new file mode 100755 index 0000000..a0395ac --- /dev/null +++ b/bell @@ -0,0 +1,7 @@ +#!/bin/sh + +bef="$(amixer get Master | awk -F '[][]' 'END{print $2}')" +amixer set Master 10% +# code steal from https://unix.stackexchange.com/a/163716/459013 +speaker-test -t sine -f 1000 -l 1 +amixer set Master "$bef" diff --git a/ccgsl b/ccgsl new file mode 100755 index 0000000..31bd325 --- /dev/null +++ b/ccgsl @@ -0,0 +1,7 @@ +#!/bin/sh +# steal codes from https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/compiler + +base="${1%.*}" +# -lm link math library? needed for sqrt(). not sure +# https://stackoverflow.com/questions/44175151/what-is-the-meaning-of-lm-in-gcc +cc -Wall -lgsl -lgslcblas -lm -o "$base" "$1" && ./"$base" diff --git a/cfg b/cfg new file mode 100755 index 0000000..92a097e --- /dev/null +++ b/cfg @@ -0,0 +1,29 @@ +#!/bin/sh + +umask 077 +while getopts lsmM opt; do + case $opt in + #c) + # work_tree_dir="$HOME" + # meta_file="$XDG_CONFIG_HOME/myconf/cfg${opt}_meta" + # cmd="git --git-dir=$HOME/.cfg$opt/ --work-tree=$HOME" + # ;; + l|s) + work_tree_dir=/ + meta_file="/etc/myconf/cfg${opt}_meta" + cmd="sudo -E git --git-dir=/etc/.cfg$opt/ --work-tree=/" + ;; + m) + sudo gitmetap "$cmd" "$work_tree_dir" "$meta_file" + $cmd diff + exit + ;; + M) + sudo gitmetar "$meta_file" + exit + ;; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) +$cmd "$@" diff --git a/chmodef b/chmodef new file mode 100755 index 0000000..446bc23 --- /dev/null +++ b/chmodef @@ -0,0 +1,6 @@ +#!/bin/sh +# chmodef: CHMOD DEFault + +# https://wiki.archlinux.org/title/File_permissions_and_attributes#Numeric_method +find "$@" -type d -execdir chmod 755 -- '{}' \+ +find "$@" -type f -execdir chmod 644 -- '{}' \+ diff --git a/curlqb b/curlqb new file mode 100755 index 0000000..d2851cd --- /dev/null +++ b/curlqb @@ -0,0 +1,27 @@ +#!/bin/sh + +# need --no-clobber if don't want overwrite when same name +# if do this also need change .py.1 to .py else qbt will not accept +# also if a.py and a_1.py, qbt will not accept the latter, maybe need to change some .py codes inside +# now, I choose to let three files to be overwrited, those are "with categories" .py files that overwrite without categories .py files, which is what I want so I don't use --no-clobber +curl -s 'https://github.com/qbittorrent/search-plugins/wiki/Unofficial-search-plugins' | awk -F'"' ' +/user-content-plugins-for-private-sites/ {exit} +/\.py/ { + url=$2 + getline + getline + getline + if($0 !~ /❗|✖/) + print url +} +' | xargs curl -s -Z -L --remote-name-all --create-dirs --output-dir "$1" -- + +# an alternative awk command: +#awk -F'"' ' +#/require an account/ {exit} +#/\.py/ { +# url=$2 +# line=NR +#} +#url && NR==line+3 && !/❗|✖/ {print url} +#' diff --git a/dateft b/dateft new file mode 100755 index 0000000..b317474 --- /dev/null +++ b/dateft @@ -0,0 +1,29 @@ +#!/bin/sh +# DATE From To + +while getopts cfF:t:T: opt; do + case $opt in + c) tz_from="Asia/Shanghai";; + f) tz_from="$(tzselect)";; + F) tz_from="$OPTARG";; + # one extra ',' at the end will not let `for tz in ...` loop one extra time? + t) for i in $(seq "$OPTARG"); do + tz_to="$(tzselect),$tz_to" + done;; + T) tz_to="$OPTARG,$tz_to";; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) + +time_from="TZ=\"${tz_from:-$(readlink /etc/localtime | sed 's#.*/\(.*/.*\)$#\1#')}\" ${1:-now}" + +date -d "$time_from" +TZ="Asia/Shanghai" date -d "$time_from" +date -d "$time_from" -u +date -d "$time_from" +%s +[ "$tz_from" ] && [ "$tz_from" != "Asia/Shanghai" ] && TZ="$tz_from" date -d "$time_from" +IFS=',' +for tz in $tz_to; do + TZ="$tz" date -d "$time_from" +done diff --git a/dirnameall b/dirnameall new file mode 100755 index 0000000..befd347 --- /dev/null +++ b/dirnameall @@ -0,0 +1,19 @@ +#!/bin/sh + +while read -r line; do + if [ "$paths" ]; then + paths="$paths +$line" + else + paths="$line" + fi +done + +dirs="$paths" +while [ "$dirs" != '.' ]; do + [ "$dirs" ] && paths="$paths +$dirs" + dirs="$(echo "$dirs" | tr '\n' '\0' | xargs -0 dirname | awk '!a[$0]++')" +done + +echo "$paths" | awk '!a[$0]++' | grep -v '^\.$' diff --git a/gita b/gita new file mode 100755 index 0000000..ee00306 --- /dev/null +++ b/gita @@ -0,0 +1,17 @@ +#!/bin/sh +# note message string must come after options + +cmd=git + +while getopts ls f; do + case $f in + l|s) cmd="cfg -$f";; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) + +mes="${1:-update}" + +$cmd commit --all -m "$mes" +$cmd push diff --git a/gitfork b/gitfork new file mode 100755 index 0000000..9736c4c --- /dev/null +++ b/gitfork @@ -0,0 +1,10 @@ +#!/bin/sh + +git clone "$1" +cd "$(basename "$1" .git)" || exit +git remote add upstream "$2" +if ! git checkout fly; then + git branch fly + git checkout fly + git push --set-upstream origin fly +fi diff --git a/gitmetap b/gitmetap new file mode 100755 index 0000000..c058986 --- /dev/null +++ b/gitmetap @@ -0,0 +1,17 @@ +#!/bin/sh +# GIT META Print + +# -rw-r--r-- == binary 110100100 == octal 644 +# https://stackoverflow.com/a/1796009 +$1 ls-tree -r --name-only --full-tree HEAD | dirnameall | awk -v a="$2/" '{printf("%s%s\n",a,$0)}' | tr '\n' '\0' | xargs -0 ls -ldA -- | awk '{ + k=0 + for(i=0;i<=8;i++) + k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i)) + if(k) { + for(i=10;$i && $i!="->";i++) + $9=$9" "$i + printf("%0o %s %s %s\n",k,$3,$4,$9) + } +}' > "$3" + +#$1 ls-tree -r --name-only --full-tree HEAD | awk -v a="$2/" '{printf("%s%s\n",a,$0)}' | tr '\n' '\0' | xargs -0 ls -ldA -- | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k){for(i=10;$i && $i!="->";i++)$9=$9" "$i;printf("%0o %s %s %s\n",k,$3,$4,$9)}}' > "$3" diff --git a/gitmetar b/gitmetar new file mode 100755 index 0000000..1bfdc15 --- /dev/null +++ b/gitmetar @@ -0,0 +1,7 @@ +#!/bin/sh +# GIT META Read + +while read -r mod user group path; do + chown -hc "$user:$group" -- "$path" + [ "$mod" -ne 777 ] && chmod -c "$mod" -- "$path" +done < "$1" diff --git a/gitpu b/gitpu new file mode 100755 index 0000000..5453fae --- /dev/null +++ b/gitpu @@ -0,0 +1,19 @@ +#!/bin/sh + +if [ -z "$1" ]; then + git checkout master + git pull upstream master + git push + git checkout fly + git merge --no-edit master + git push +else + for dir; do + git -C "$dir" checkout master + git -C "$dir" pull upstream master + git -C "$dir" push + git -C "$dir" checkout fly + git -C "$dir" merge --no-edit master + git -C "$dir" push + done +fi diff --git a/grrc b/grrc new file mode 100755 index 0000000..66a7200 --- /dev/null +++ b/grrc @@ -0,0 +1,4 @@ +#!/bin/sh +# GRep -R Code + +[ "$1" ] && find "$HOME/archive/programs/public_archive_codes" "$HOME/archive/programs/private_archive_codes" "$HOME/archive/programs/me106_proj_fall2021" "$HOME/archive/programs/car_job/av_dev" "$HOME/archive/programs/VisualDimension" "$XDG_DOCUMENTS_DIR/notes" -mindepth 1 -maxdepth 1 -path "*/\.git" -prune -o -type d -print0 2>/dev/null | xargs -0 grep -s --color=always -iIR "$@" "$HOME/.local/bin" "$HOME/.bashrc" "$HOME/.profile" "$HOME/.xinitrc" "$HOME/programs/suckless/dwm_fly/config.def.h" "$XDG_CONFIG_HOME/nsxiv/exec/key-handler" | "$PAGER" diff --git a/il b/il new file mode 100755 index 0000000..7c75a71 --- /dev/null +++ b/il @@ -0,0 +1,6 @@ +#!/bin/sh +# InterpoLation + +# x=$1, xa=$2, xb=$3, ya=$4, yb=$5 +# https://en.wikipedia.org/wiki/Interpolation#Linear_interpolation +echo "scale=4;$4+($5-$4)*($1-$2)/($3-$2)" | bc diff --git a/lastarg b/lastarg new file mode 100755 index 0000000..b52afcd --- /dev/null +++ b/lastarg @@ -0,0 +1,5 @@ +#!/bin/sh +# usage: lastarg "$@" + +shift $(($# - 1)) +echo "$1" diff --git a/loop b/loop new file mode 100755 index 0000000..6a57826 --- /dev/null +++ b/loop @@ -0,0 +1,15 @@ +#!/bin/sh + +while getopts t: opt; do + case $opt in + t) time="$OPTARG";; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) + +while :; do + # suggested by https://github.com/koalaman/shellcheck/wiki/SC2294 + "$@" + sleep "${time:-1}" +done diff --git a/lsp b/lsp new file mode 100755 index 0000000..4e2caa0 --- /dev/null +++ b/lsp @@ -0,0 +1,3 @@ +#!/bin/sh + +loop ssh "${1:-pp}" diff --git a/mll b/mll new file mode 100755 index 0000000..9f7d5df --- /dev/null +++ b/mll @@ -0,0 +1,6 @@ +#!/bin/sh +# Map Latitude Longitude + +# https://help.openstreetmap.org/questions/9669/jumping-to-a-specific-set-of-coordinates-on-the-map +# another way is to manually search xx.xxxxx,xx.xxxxx +o "$BROWSER" "https://www.openstreetmap.org/?mlat=$1&mlon=$2&zoom=5" diff --git a/mmi b/mmi new file mode 100755 index 0000000..350fe50 --- /dev/null +++ b/mmi @@ -0,0 +1,27 @@ +#!/bin/sh + +mi () { + make + sudo make install +} + +origin="$PWD" +cmd='mi' + +while getopts q opt; do + case $opt in + q) cmd='qmake6;mi';; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) + +if [ -z "$1" ]; then + eval "$cmd" +else + for dir; do + cd "$dir" || exit + eval "$cmd" + cd "$origin" || exit + done +fi diff --git a/mpra b/mpra new file mode 100755 index 0000000..0801e55 --- /dev/null +++ b/mpra @@ -0,0 +1,44 @@ +#!/bin/sh +# MakePkg Repo-Add + +fn () { + if ! { [ -f PKGBUILD ] || [ -h PKGBUILD ];}; then + exit + fi + find . -maxdepth 1 -type f -name "*.pkg.tar.$ext*" -delete + makepkg --sign -sf + newpkg="$(find . -maxdepth 1 -type f -name "*.pkg.tar.$ext")" + [ -d ../repo ] || mkdir ../repo + mv "$newpkg" "$newpkg.sig" ../repo + # need manually repo-add new database for first time initialization + repo-add -s -v -R "$(find ../repo -maxdepth 1 -type f -name '*.db.tar.gz')" "../repo/$newpkg" + # seems no need to delete *.old and *.old.sig, see https://mirror.fcix.net/archlinux/core/os/x86_64/ it do include *.old + #find ../repo -maxdepth 1 -type f \( -name '*.old' -o -name '*.old.sig' \) -delete +} + +ext=zst +copy_any= + +while getopts ac opt; do + case $opt in + # arch linux arm still using .xz instead of .zst as package compression format + a) ext=xz;; + # copy arch linux fly-any repo + c) copy_any=1;; + \?) exit 1;; + esac +done +shift $((OPTIND-1)) + +if [ $# -eq 0 ]; then + fn +else + for dir; do + cd -- "$(realpath -- "$dir")" || exit + fn + done +fi + +[ "$copy_any" ] && sudo rsync -vPrlt --delete ../repo/ /srv/http/mirrors/archlinux/fly/os/any + +upd -p diff --git a/mpva b/mpva new file mode 100755 index 0000000..d80c9f3 --- /dev/null +++ b/mpva @@ -0,0 +1,17 @@ +#!/bin/sh +# MPV Audio + +# fzf has --read0, maybe useful +# use --loop-file for single file, better performance maybe +# fzf --scheme=path for better fzf result when searching path, like the old time: +# https://github.com/junegunn/fzf/commit/6fb41a202a97ad3f2437f6e5aee8890268560412 + +if [ $# -eq 0 ]; then + find "$XDG_MUSIC_DIR" | fzf -m --print0 --scheme=path +fi | xargs -0 sh -c ' +if [ $# -eq 1 ] && ! [ -d "$1" ]; then + mpv --af= --loop-file=inf --video=no "$1" +else + mpv --af= --shuffle --loop-playlist=inf --video=no "$@" +fi +' shell "$@" diff --git a/mpvy b/mpvy new file mode 100755 index 0000000..1cf17a7 --- /dev/null +++ b/mpvy @@ -0,0 +1,44 @@ +#!/bin/sh +# MPV Yank/Youtube videos +# references: +# https://www.rockyourcode.com/til-how-to-watch-youtube-videos-with-mpv-and-keyboard-shortcuts/ + +fps=30 +height=$SCR_HEIGHT +url="$(xsel -ob)" +flag=s + +# option f and h may do nothing if redownload? since same filename exist. yt-dlp won't download same file even without --auto-file-renameing=false. how improve? pass argument to aria2c? +while getopts Aabd:f:h:su: opt; do + case $opt in + # s: streaming, a: aria2c then mpv, A: aria2c + A|a|s) flag=$opt;; + b) format='bestvideo+bestaudio/best';; + d) download_dir="$OPTARG";; + f) fps="$OPTARG";; + h) height="$OPTARG";; + u) url="$OPTARG";; + \?) exit 1;; + esac +done +if [ -z "$format" ]; then + #vformat="[height<=?$height][fps<=?$fps][vcodec!^=?vp9][vcodec!^=?av01]" + vformat="[height<=?$height][fps<=?$fps][vcodec!^=?av01]" + # usually get .mp4 video + .webm audio on youtube, yt-dlp needs to merge them to .mkv + # it used to cause problem, but I forget + format="bestvideo$vformat+bestaudio/best$vformat" +fi + +case $flag in + # here if use --write-sub, mpv doesn't recognize subtitles? + # --embed-subs is a little bit better, but still worse then direct streaming + # --sponsorblock-remove will make audio/video goes out of sync, need --force-keyframes-at-cuts which need re-encode which is slow, more see comments at the bottom of https://github.com/yt-dlp/yt-dlp/issues/871 + # another way is using mpv-sponsorblock-minimal-git for streaming and sponsorblock-mpv-local for local videos + A) yt-dlp -f "$format" --embed-subs -P "${download_dir:-"$XDG_DOWNLOAD_DIR/mpvy/"}" --sponsorblock-remove default --sponsorblock-mark default "$url";; + a) yt-dlp -f "$format" --embed-subs -P "${download_dir:-"$XDG_DOWNLOAD_DIR/mpvy/"}" --sponsorblock-remove default --sponsorblock-mark default "$url" --exec 'mpv --fs --speed=2';; + s) mpv --ytdl-format="$format" --ytdl-raw-options='write-sub=' --fs --speed=2 "$url";; +esac +# not sure if this is the best practice, but it seems working ;) +status=$? +[ $status -ne 0 ] && notify-send 'mpvy failed' +exit $status diff --git a/mvln b/mvln new file mode 100755 index 0000000..54cef54 --- /dev/null +++ b/mvln @@ -0,0 +1,27 @@ +#!/bin/sh +# edge cases give me headache + +lns () { + # prevent `mvln file1 file1` or `mvln dir1/file1 dir1/` + # which means `ln -s samename samename` or `ln -s dir/file dir/` + # both $1 and $2 here are realpath + [ "$1" != "$2" ] && ln -s -- "$1" "$2" +} + +mv -i -- "$@" +# consider `mvln file1 dir/file2` +if [ $# -eq 2 ] && ! [ -d "$2" ]; then + # use realpath here + lns "$(realpath "$2")" "$(realpath "$1")" +else + dir="$(realpath -- "$(lastarg "$@")")" + # steal from https://unix.stackexchange.com/a/353833/459013 + while [ $# -gt 1 ]; do + to="$(realpath -- "$1")" + # prevent `mvln dir1/ dir1/` + if [ "$dir" != "$to" ]; then + lns "$dir/$(basename "$1")" "$to" + fi + shift + done +fi diff --git a/mvtr b/mvtr new file mode 100755 index 0000000..28eebf0 --- /dev/null +++ b/mvtr @@ -0,0 +1,11 @@ +#!/bin/sh + +# can use ls pipe to sed pipe to bash, similar to eval? see comment at link: +# link also show perl-rename approach +# https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-characters +# if only change ' ' to '_' `rename` might be sufficient, for upper to lower case might need perl-rename if want concise + +# ./_filename will be renamed ./filename, not what I want, need improve +# -exec can't replace -execdir here, can write a -exec version + +find "$@" -depth -execdir sh -c 'dest="$(echo "$1" | tr -d "\047" | sed -E -e "s/([[:lower:]])([[:upper:]])/\1_\2/g" | tr "[:upper:] " "[:lower:]_" | tr -s "[:punct:]" | sed -E -e "s#/-#/#g" -e "s/_([[:punct:]])/\1/g" -e "s/([[:punct:]])_/\1/g" | tr -s "[:punct:]")"; [ -e "$dest" ] || mv -v -- "$1" "$dest"' shell '{}' \; diff --git a/mvtu b/mvtu new file mode 100755 index 0000000..6160507 --- /dev/null +++ b/mvtu @@ -0,0 +1,13 @@ +#!/bin/sh +# MV Time-Uuid + +find "$@" -type f -execdir sh -c ' + file="$(basename "$1")" + ext="${file##*.}" + if [ "$ext" != "$file" ]; then + dest="$(time-uuid).$ext" + else + dest="$(time-uuid)" + fi + [ -e "dest" ] || mv -v -- "$1" "$dest" +' shell '{}' \; diff --git a/news b/news new file mode 100755 index 0000000..e0d2ffa --- /dev/null +++ b/news @@ -0,0 +1,31 @@ +#!/bin/sh + +daily () { + # mail.yahoo.com/d/folders/6 is spam folder + o "$BROWSER" https://github.com/notifications https://mail.google.com 'https://mail.google.com/mail/u/0/#spam' https://mail.yahoo.com https://mail.yahoo.com/d/folders/6 https://en.wikipedia.org/wiki/Portal:Current_events + # alacritty --hold must be before -e + # full window: -w156, am and pm in one line: -w114 + o alacritty --hold -e rem -cu+2 -@ -w114 + o alacritty --hold -e wtr + o alacritty -e newsboat + o alacritty --hold -e pass practice_password0 +} + +monthly () { + o "$BROWSER" https://smtp.cheogram.com/ http://download.huzheng.org + o alacritty --hold -e rate + # Show 3 months' remind. I use 3 months because it is better to know I20 deadline 3 months earlier so I have 2 months to prepare the money for extension. + # (2*31+30+6)/7=14. Consider month 1 day 1 is on Sunday and make sure month 3 day 31 is shown. Tested with `rem -cu+14 -@ -w114 2025-03-01` + o alacritty --hold -e sh -c 'rem -cu+14 -@ -w114 | $PAGER' +} + +if [ $# -eq 0 ]; then + daily +else + while getopts m opt; do + case $opt in + m) monthly;; + \?) exit 1;; + esac + done +fi diff --git a/o b/o new file mode 100755 index 0000000..8fb066c --- /dev/null +++ b/o @@ -0,0 +1,27 @@ +#!/bin/sh + +# useful links +# https://stackoverflow.com/questions/3430330/best-way-to-make-a-shell-script-daemon +# https://serverfault.com/questions/117152/do-background-processes-get-a-sighup-when-logging-off +# https://wiki.archlinux.org/title/default_applications + +# I don't care about errors, I don't want to handle errors, just shut up please. +# nohup seems not necessary if don't care about daemon SIGHUP requirement + +# when close a shell script's stdout or stderr with `>&-` or `2>&-`, `xsel -ib` in that script has no effect +# https://github.com/kfish/xsel/issues/43 +# using `>&-` or `2>&-` doesn't completely close mpv's output when run sth. like `o mpv file.mkv` +# base on above observations, I choose to use `>/dev/null 2>&1` instead + +# need ; before } when it is in the same line as { ? https://www.shellcheck.net/wiki/SC1056 + +if [ $# -eq 1 ] && [ -e "$1" ] && { ! [ -x "$1" ] || [ -d "$1" ];}; then + case "$1" in + # libreoffice, please don't let firefox eat your shit + *.docx|*.pptx) cmd=libreoffice;; + *) cmd=xdg-open;; + esac + nohup "$cmd" "$1" 0<&- >/dev/null 2>&1 & +else + nohup "$@" 0<&- >/dev/null 2>&1 & +fi diff --git a/orgext b/orgext new file mode 100755 index 0000000..0143e62 --- /dev/null +++ b/orgext @@ -0,0 +1,18 @@ +#!/bin/sh + +outdir () { + find . -type f -execdir mv -t "$PWD" -- '{}' \+ + find . -mindepth 1 -maxdepth 1 -type d -execdir rmdir -- '{}' \+ +} + +indir () { + # https://stackoverflow.com/questions/1842254/how-can-i-find-all-of-the-distinct-file-extensions-in-a-folder-hierarchy + find . -maxdepth 1 -type f | awk -F. '!a[$NF]++{print $NF}' | xargs mkdir -- + find . -mindepth 1 -maxdepth 1 -type d -execdir basename -az -- '{}' \+ | xargs -0 -I _ find . -maxdepth 1 -type f -name '*._' -execdir mv -t '_' -- '{}' \+ +} + +case "$1" in + '-o') outdir;; + '-i') indir;; + *) outdir; indir;; +esac diff --git a/pa b/pa new file mode 100755 index 0000000..86ae4e5 --- /dev/null +++ b/pa @@ -0,0 +1,8 @@ +#!/bin/sh +# Ping Alarm + +while ! ping -w5 "$1"; do + sleep 5 +done +notify-send "$1 on" +bell diff --git a/pq b/pq new file mode 100755 index 0000000..bad9c35 --- /dev/null +++ b/pq @@ -0,0 +1,13 @@ +#!/bin/sh +# Pacman Query, to manually determine remove the package or not + +[ "$1" ] && { + #sed -n '/^Depends On/,/^Conflicts With/{/^Conflicts With/!p}; /^Description\|^URL\|^Groups\|^Installed Size\|^Install Reason/p' + pacman -Qi "$1" | awk '/^Groups/{f=1} /^Conflicts With/{f=0} f||/^Description|^URL|^Installed Size|^Install Reason/' + printf '\n' + pacman -Ql "$1" | grep '/bin/[^$]' + printf '\n' + pactree -r "$1" + printf '\n' + grrc "$1" +} | "$PAGER" diff --git a/px b/px new file mode 100755 index 0000000..1b4e849 --- /dev/null +++ b/px @@ -0,0 +1,10 @@ +#!/bin/sh +# Printf Xsel + +if [ $# -eq 0 ]; then + /usr/bin/printf '%q' "$PWD" +else + for dir; do + /usr/bin/printf '%q ' "$(realpath -- "$dir")" + done +fi | xsel -ib diff --git a/qg b/qg new file mode 100755 index 0000000..dde5190 --- /dev/null +++ b/qg @@ -0,0 +1,15 @@ +#!/bin/sh + +# more resources see comments in my script qw +# https://guix.gnu.org/manual/en/html_node/Running-Guix-in-a-VM.html +# `-enable-kvm` same as `-accel kvm`, see archwiki +qemu-system-x86_64 \ + -accel kvm \ + -cpu host \ + -device virtio-blk,drive=myhd \ + -display gtk,zoom-to-fit=on \ + -drive if=none,file="$XDG_DOWNLOAD_DIR/qemu/guix.img",format=qcow2,id=myhd \ + -m 8G \ + -nic user,model=virtio-net-pci,hostfwd=::53684-:22 \ + -smp 2,sockets=1,cores=1,threads=2 \ + -usb -device usb-tablet diff --git a/qw b/qw new file mode 100755 index 0000000..e77b88f --- /dev/null +++ b/qw @@ -0,0 +1,16 @@ +#!/bin/sh + +# For better performance, it needs CPU-pinning with `taskset`, GPU pass-through, and other more tweaks +# https://github.com/cardi/qemu-windows-10 +# https://wiki.archlinux.org/title/QEMU +## https://wiki.archlinux.org/title/QEMU#Mouse_integration +# https://qemu-project.gitlab.io/qemu/system/devices/usb.html +qemu-system-x86_64 \ + -accel kvm \ + -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \ + -display gtk,zoom-to-fit=on \ + -drive file="$XDG_DOWNLOAD_DIR/qemu/win10.img",format=qcow2 \ + -m 8G \ + -nic user,hostfwd=::53683-:22 \ + -smp 2,sockets=1,cores=1,threads=2 \ + -usb -device usb-tablet diff --git a/rate b/rate new file mode 100755 index 0000000..1625df6 --- /dev/null +++ b/rate @@ -0,0 +1,11 @@ +#!/bin/sh + +while getopts f:t: opt; do + case $opt in + f) from="$OPTARG";; + t) to="$(echo "$OPTARG" | tr '[:lower:]' '[:upper:]')";; + \?) exit 1;; + esac +done +# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates +curl -s "https://api.coinbase.com/v2/exchange-rates?currency=${from:-xmr}" | jq -r ".data.rates.${to:-USD}" diff --git a/reco b/reco new file mode 100755 index 0000000..7ee726d --- /dev/null +++ b/reco @@ -0,0 +1,28 @@ +#!/bin/sh + +# useful urls: +# https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/dmenurecord +# https://wiki.archlinux.org/title/FFmpeg#Screen_capture +# https://trac.ffmpeg.org/wiki/Capture/Desktop + +infofile="/tmp/recoinfo" +recodir="$XDG_VIDEOS_DIR/recordings/" +tmpdir="$recodir/tmp/" +mkdir -p "$recodir" "$tmpdir" + +if [ -e "$infofile" ]; then + read -r pid tmpfile < "$infofile" + kill "$pid" + notify-send 'finish recording, start converting' + ffmpeg -i "$tmpfile" "$recodir/$(time-uuid).mkv" + notify-send 'finish converting' + rm "$tmpfile" "$infofile" +else + tmpfile="$tmpdir/$(time-uuid).mkv" + notify-send 'prepare recording' + # arch wiki way, no audio, less cpu use during capturing (fast?), large file size, need convert afterward + xrectsel '%w %h %x %y' | xargs sh -c 'ffmpeg -y -loglevel quiet -f x11grab -framerate 25 -s "$2x$3" -i "$DISPLAY+$4,$5" -c:v ffvhuff "$1" & echo $!' shell "$tmpfile" | xargs -I {} printf '%s\t%s' '{}' "$tmpfile" > "$infofile" + # another way to get subshell ffmpeg child pid + #xrectsel '%w %h %x %y' | xargs sh -c 'ffmpeg -y -f x11grab -framerate 25 -s "$2x$3" -i "$DISPLAY+$4,$5" -c:v ffvhuff "$1"' shell "$tmpfile" & + #printf '%s\t%s' "$(ps -o pid= --ppid $!)" "$tmpfile" > "$infofile" +fi diff --git a/rfp b/rfp new file mode 100755 index 0000000..c1a3e1f --- /dev/null +++ b/rfp @@ -0,0 +1,11 @@ +#!/bin/sh + +if grep -q '^//user_pref("privacy.resistFingerprinting", false);$' "$HOME/.mozilla/firefox/xxxxxxxx.fly/user-overrides.js"; then + sed -i 's#^//\(user_pref("privacy.resistFingerprinting", false);\)$#\1#' "$HOME/.mozilla/firefox/xxxxxxxx.fly/user-overrides.js" + notify-send -u critical 'RFP disabled' +else + sed -i 's#^\(user_pref("privacy.resistFingerprinting", false);\)$#//\1#' "$HOME/.mozilla/firefox/xxxxxxxx.fly/user-overrides.js" + notify-send 'RFP enabled' +fi +upd -j +o "$BROWSER" diff --git a/sbar b/sbar new file mode 100755 index 0000000..392b65a --- /dev/null +++ b/sbar @@ -0,0 +1,77 @@ +#!/bin/sh +# modified from pystardust, GPLv3 license: https://github.com/pystardust/sbar + +# INIT +sec=0 + +# MODULES +update_time () { + time="$(date '+%a %m/%d %H:%M') $(TZ=Asia/Shanghai date '+/%d %H:') $(date -u '+/%d %H:')" +} + +#update_cap () { +# cap="$(if xset q | grep -q "Caps Lock: *on"; then echo A; else echo a; fi)" +#} + +update_net () { + net="$(if nmcli -t --fields type,state device | grep -q '^\(ethernet\|wifi\):connected$'; then echo 1; else echo 0; fi)" + nm_device_state="$(nmcli -t --fields device,state device)" + vpn="$( + if echo "$nm_device_state" | grep -q '^wg_ka:connected$'; then + echo K + elif echo "$nm_device_state" | grep -q '^wg_studio:connected$'; then + echo S + else + echo 0 + fi + )" +} + +update_vol () { + # $(NF-1) for both alsa and pulseaudio + vol="$(amixer get Master | awk -F'[][]' 'END{printf("%d %s",($(NF-1)=="on")?1:0,$2)}')" +} + +update_mic () { + # $(NF-1) for both alsa and pulseaudio + mic="$(amixer get Capture | awk -F '[][]' 'END{print ($(NF-1)=="on")?1:0}')" +} + +update_bat () { + bat="$(cat /sys/class/power_supply/BAT0/capacity)%" +} + +update_gpu () { + gpu="$(envycontrol -q | awk 'END{print toupper(substr($NF,0,1))}')" +} + +display () { + xsetroot -name "$time | N $net V $vpn | M $vol C $mic | $gpu | $bat" +} + +# modules that don't update on their own need to be run at the start for getting their initial value +update_net +update_vol +update_mic +update_gpu + +# SIGNALLING +# trap ";display" "RTMIN+n" +trap "update_mic;display" "RTMIN" +trap "update_vol;display" "RTMIN+1" +# xev can't read my toggle internet keyboard key, don't know what key to use in sxhkd to send signal +trap "update_net;display" "RTMIN+2" +# to update it from external commands +## kill -m $(pidof -x sbar) +# where m = 34 + n + +while :; do + sleep 1 & + wait + [ $((sec % 5 )) -eq 0 ] && update_time # update time every 5 seconds + [ $((sec % 60)) -eq 0 ] && update_net + [ $((sec % 60)) -eq 0 ] && update_bat + # how often the display updates ( 5 seconds ) + [ $((sec % 5 )) -eq 0 ] && display + sec=$((sec + 1)) +done diff --git a/ta b/ta new file mode 100755 index 0000000..ae386c1 --- /dev/null +++ b/ta @@ -0,0 +1,5 @@ +#!/bin/sh +# TIme Alarm + +time -p "$@" +o alarm 0 'Command Finished' "$(/usr/bin/printf '%q ' "$@")" diff --git a/time-uuid b/time-uuid new file mode 100755 index 0000000..bdaf4b3 --- /dev/null +++ b/time-uuid @@ -0,0 +1,6 @@ +#!/bin/sh + +# echo current nanosecond since epoch and alpha-numerically ordered UUID +# https://stackoverflow.com/questions/28681650/generate-alpha-numerically-ordered-uuids-over-time?noredirect=1&lq=1 +# https://askubuntu.com/questions/342842/what-does-this-command-mean-awk-f-print-4 +echo "$(date '+%s-%N')-$(uuidgen -t | awk -F- '{OFS="-"; print $3,$2,$1,$4,$5}')" diff --git a/topa b/topa new file mode 100755 index 0000000..3252997 --- /dev/null +++ b/topa @@ -0,0 +1,8 @@ +#!/bin/sh + +o alacritty -e htop +#o alacritty -e radeontop -c +o alacritty -e iotop +o alacritty -e nethogs +o alacritty -e intel_gpu_top +o alacritty -e nvtop diff --git a/vinfo b/vinfo new file mode 100755 index 0000000..190de19 --- /dev/null +++ b/vinfo @@ -0,0 +1,4 @@ +#!/bin/sh + +# steal from https://github.com/HiPhish/info.vim +"$EDITOR" -RM +"Info $1 $2" +only diff --git a/wh b/wh new file mode 100755 index 0000000..d20f0de --- /dev/null +++ b/wh @@ -0,0 +1,11 @@ +#!/bin/sh + +# blue, see `man terminfo` +setaf="$(tput setaf 4)" +sgr0="$(tput sgr0)" + +# dash `command -V "$@"` will only output first command's type, same as `type`, but different than posix specification? so not use here +for cmd in type whatis whereis which "pacman -Qo --color always"; do + printf '\n%s\n%s\n' "$setaf$cmd $*$sgr0" "$($cmd "$@" 2>&1)" + #printf '\n\033[0;34m%s\033[0m\n%s\n' "$setaf$cmd $*$sgr0" "$($cmd "$@" 2>&1)" +done | "$PAGER" diff --git a/wtr b/wtr new file mode 100755 index 0000000..c9907d9 --- /dev/null +++ b/wtr @@ -0,0 +1,43 @@ +#!/bin/sh + +# https://github.com/open-meteo/open-meteo +i=0 +curl -s -G -d "latitude=${1:-37.34}" -d "longitude=${2:--121.89}" -d 'daily=weathercode,temperature_2m_max,temperature_2m_min,sunrise,sunset' -d 'timezone=auto' 'https://api.open-meteo.com/v1/forecast' | jq -r '[.daily|.time, .weathercode, .temperature_2m_max, .temperature_2m_min, .sunrise, .sunset]|transpose|.[]|@tsv' | while read -r time code max min sunrise sunset; do + # https://open-meteo.com/en/docs + case "$code" in + 0) code='clear sky';; + 1) code='mainly clear';; + 2) code='partly cloudy';; + 3) code=overcast;; + 45) code=fog;; + 48) code='depositing rime fog';; + 51) code='light drizzle';; + 53) code='moderate drizzle';; + 55) code='dense drizzle';; + 56) code='light freezing drizzle';; + 57) code='dense freezing drizzle';; + 61) code='slight rain';; + 63) code='moderate rain';; + 65) code='heavy rain';; + 66) code='light freeze rain';; + 67) code='heavy freeze rain';; + 71) code='slight snow fall';; + 73) code='moderate snow fall';; + 75) code='heavy snow fall';; + 77) code='snow grains';; + 80) code='slight rain showers';; + 81) code='moderate rain showers';; + 82) code='violent rain showers';; + 85) code='slight snow showers';; + 86) code='heavy snow showers';; + 95) code='slight or moderate thunderstorm';; + 96) code='thunderstorm with slight hail';; + 99) code='thunderstorm with heavy hail';; + *) exit 1;; + esac + if [ "$i" -ne 1 ]; then + printf 'sunrise: %s | sunset: %s\n' "${sunrise#*T}" "${sunset#*T}" + i=1 + fi + printf '%s\t%s\t%s\t%s\n' "${time#*-}" "$max" "$min" "$code" +done diff --git a/xmq b/xmq new file mode 100755 index 0000000..83eca0f --- /dev/null +++ b/xmq @@ -0,0 +1,3 @@ +#!/bin/sh + +xdg-mime query filetype "$1" | tee /dev/tty | xargs xdg-mime query default -- cgit v1.2.3-70-g09d2