### ### SECTION: global settings ### shopt -s autocd cdspell dirspell checkjobs globstar histappend ### ### SECTION: environment ### #export GIT_AUTHOR_NAME="" #export GIT_AUTHOR_EMAIL="" #export GIT_COMMITTER_NAME="" #export GIT_COMMITTER_EMAIL="" #export LD_LIBRARY_PATH="" #export ANSIBLE_CONFIG="$HOME/..." #export GOPATH="$HOME/..." #export GOROOT="$HOME/..." export SHELL="bash" export PAGER="bat" export VISUAL="nvim" export BROWSER="firefox" export TIME_STYLE=long-iso ### ### SECTION: CLI stdlib ### ## Helper functions for bash scripting err-error() { local MSG="$*" if [ -z "$MSG" ]; then MSG="(error message is missing)" fi if [ -t 1 ]; then printf " [\033[1;31mERROR\033[0m] \033[1m%s\n\033[0m" "$MSG" >&2 else printf " [ERROR] %s\n" "$MSG" >&2 fi } err-warn() { local MSG="$*" if [ -z "$MSG" ]; then MSG="(warning message is missing)" fi if [ -t 1 ]; then printf " [\033[1;33mWARN\033[0m] \033[1m%s\n\033[0m" "$MSG" >&2 else printf " [WARN] %s\n" "$MSG" >&2 fi } err-log() { local MSG="$*" if [ -z "$MSG" ]; then MSG="(log message is missing)" fi if [ -t 1 ]; then printf ":: \033[1;37m%s\n\033[0m" "$MSG" >&2 else printf ":: %s\n" "$MSG" >&2 fi } out-log() { local MSG="$*" if [ -z "$MSG" ]; then MSG="(log message is missing)" fi if [ -t 1 ]; then printf "\033[1;33m → \033[1;37m%s\n\033[0m" "$MSG" else printf " → %s\n" "$MSG" fi } out-pass() { if [ -t 1 ]; then printf "\033[1;32m ✔️ %s\n\033[0m" "$*"; else printf " ✔️ %s\n" "$*"; fi } out-fail() { if [ -t 1 ]; then printf "\033[1;31m 🗴 %s\n\033[0m" "$*"; else printf " 🗴 %s\n" "$*"; fi } key-value() { if [ -z "$1" ]; then err-error "key-value expects a key and value as argument" return 1 fi; python3 -c "key='$1'; value='$2'; width=int('$3' or 20); print('{}\033[1;34m{}\033[0m:: \033[1m{}\033[0m'.format(' ' * max(1, width - len(key)), key, value))" } step() { local VARS_DECL="nr='{:02}'.format(int('$2' or 0)) if '$2' else ''; text='$1'; desc='{}'.format(text) if text else ''; desc=' ' + desc if nr else desc;" local REPR="'\033[0;33;49m{}\033[0m ({}{}) \033[0;33;49m{}\033[0m'.format('-' * 8, nr, desc, '-' * (80 - len(nr) - len(desc)))" python3 -c "${VARS_DECL} print(${REPR})" } ### ### SECTION: functions ### up() { [ "${1/[^0-9]/}" == "$1" ] && { local ups="" for i in $(seq 1 "$1"); do ups=$ups"../" done cd "$ups" } || echo "usage: up INTEGER" } observe() { watch -c -n 1 $@ } wait-for() { time "$@" && zenity --info --text="Command finished" } my-latest-git-commits() { git log --all --no-walk=sorted --author="$GIT_COMMIT_AUTHOR" #--format="%H" } alias text-ansi-seqs-remove='sed -r "s/\x1b\[([0-9]{1,2}(;[0-9]{1,2})*)?m//g"' # search directory of files where some files are zipped alias zgrep-r='function zgrep-recursive() { find -name \*.gz -print0 | xargs -0 zgrep "$@" ; }; zgrep-recursive' alias py="python3" alias ac="source ./venv/bin/activate" alias ls='ls --color=auto' alias grep='grep --color=auto' alias ll='ls -lat' ### ### SECTION: shorthands ### # FUNCTION: d := disk usage information / directory size d() { df -h } # FUNCTION: e := open file for editing # I prefer an edit command where additionally the path might be suffixed with a line number like_this:43: e() { if [ -z "$1" ]; then err-error "filepath expected as argument" return 1 fi; if [ -z "$2" ]; then $EDITOR "$1" else if [ -z "$3" ]; then if [[ $2 =~ '^[0-9]+$' ]]; then local PARSED=$(perl -e "my \$input = '$@'; if (\$input =~ m/(.*):([0-9]+):.*$/) { print('+', \$2, ' ', \$1) } else { print(\$input) }") $EDITOR $PARSED else $EDITOR "$1" "$2" fi else $EDITOR $@ fi fi; } # FUNCTION: f := find a file by a substring # find abstraction (search for substring in the basename) f() { if [ -z "$1" ]; then err-error "filepath expected as argument" return 1 fi; if [ -z "$2" ]; then find . -name "*$(echo $1 | sed 's/\*//g' -)*" else find "$2" -name "*$(echo $1 | sed 's/\*//g' -)*" fi; } # FUNCTION: g := search for a substring in text files #g() { # # rg -z --color=always -g '!venv' -g '!*.min.js' # if [ -z "$1" ]; then # err-error "filepath expected as argument" # return 1 # fi; # if [ -z "$2" ]; then # grep -rn "$1" . # else # grep -rn "$1" "$2" # fi; #} # CHANGED g() { local PATTERN="$1" local BASEDIR="$2" if [ -z "$BASEDIR" ]; then BASEDIR="." fi rg --colors 'match:fg:blue' --colors 'line:fg:red' --color=always -g "**/*" -g "\!*venv" -g "\!*.log" -g "\!*.depr" -g "\!node_module/**" -g "\!.git/**" "$PATTERN" "$BASEDIR" } # FUNCTION: i := inform me with a text message i() { zenity --info --text "$1" } # FUNCTION: l := list current working directory content l() { pwd ls -la $@ } # FUNCTION: m := create folder and change to it m() { mkdir -p "$1" cd "$1" || return } # FUNCTION: o := open file for viewing or current folder in file explorer o() { QUERY="$1" if [ -z "$QUERY" ]; then err-error "filepath expected as argument" return 1 fi; if [ -d "$QUERY" ]; then xdg-open "$QUERY" ; return 0; fi; if echo $(file "$QUERY") | grep " text"; then if which bat >/dev/null 2>&1 ; then # NOTE: bat improves the output representation and can be used instead # proposal #1: "v file_to_show.xml 42" if [ -z "$2" ]; then bat --style full --paging always "$QUERY" else bat --style full --paging always -H "$2" "$QUERY" fi ## proposal #2: "v file_to_show.xml:42" #local OPT_LINENO_WITH_PATH=$(perl -e "my \$input = '$1'; if (\$input =~ m/(.*):([0-9]+):.*$/) { print(\$1, ' -H ', \$2, ':', \$2) } else { print(\$input) }") #bat --style full --paging always "$OPT_LINENO_WITH_PATH" else less +G "$@" fi; else xdg-open "$QUERY" fi } # FUNCTION: t := show file system tree with maxdepth 3 t() { DIR="$1" if [ -z "$DIR" ]; then DIR="." fi find "$DIR" -maxdepth 3 } ## Directory shorthands alias dir-go="$HOME/dev/go/src/github.com/meisterluk" alias dir-management="$HOME/management-sphinx/source" ## convenience tools alias pcat="pygmentize -f terminal256 -O style=native -g" alias rsync="rsync --progress --human-readable" alias v="$PAGER" webp2png() { local SRC="$1" dwebp "$SRC" -o ${$SRC%.*}".png" } mem() { # https://stackoverflow.com/a/20277787 if [ -z "$1" ]; then echo "provide a process ID as first argument" return 1; else ps -eo rss,pid,euser,args:100 --sort %mem | grep -v grep | grep -i "$1" | awk '{printf \$1/1024 "MB"; \$1=""; print }' fi } website-backup() { URL="$1" if [ -z "$URL" ]; then echo "provide a URL as first argument" return 1; else wget --mirror --convert-links --adjust-extension --page-requisites --no-parent "$URL"; fi } epdf() { echo "Running vim with PDF options" vim -b "$1" -c "set statusline+=%o laststatus=2" } c() { cd "$1" && find . -maxdepth 1 -type d && echo && echo "Current working directory: $PWD" } exifsetartist() { local ARTIST="$1" local INPUT="$2" local OUTPUT="$3" if [ -z "$ARTIST" || -z "$INPUT" || -z "$OUTPUT" ]; then echo "usage: exifsetartist " return fi exif --output="$OUTPUT" --ifd="EXIF" --tag="Artist" --set-value="$ARTIST" "$INPUT" } svg2plainsvg() { local SRC="$1" inkscape "$SRC" --export-text-to-path --export-pdf=/tmp/tmp.pdf inkscape -l "${SRC%.*}.plain.svg" /tmp/tmp.pdf rm /tmp/tmp.pdf } # common unicode symbols chars() { echo " ♡ ♥ ❤ 💕 🧡 💓 "; echo " sup: ⁰¹²³⁴⁵⁶⁷⁸⁹ ⁺⁻⁼⁽⁾ ᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁⱽᵂ "; echo " sub: ₀₁₂₃₄₅₆₇₈₉ ₊₋₌₍₎ ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ "; echo " 😀 😁 😂 😄 😅 😆 😃 😇 😉 😎 😊 🙂 😍 😘 😙 😚"; echo " 😛 😜 😝 🤓 😶 😐 😋 😌 😈 😏 😒 😓 😔 😑 😗 😲 "; echo " 😕 😖 😞 😟 🤔 🙃 👍 💩 🖥️ 💻 ⌨️ 🖊️ ✒️ ✍️ 🇦🇹 🇯🇵"; echo " ½ ¼ ¾ ⅐ ⅑ ⅒ ⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ ↉ ‰ ‱ © ® "; echo " ⟷ ← → ↓ ↑ × ✖ ⋮ … · ・ ÷ - - — ↤ ↦ ↧ ↥ ⟻ ⟼ "; echo " ⇔ ⇐ ⇒ ⇓ ⇑ ‖ ⟸ ⟹ ⤆ ⤇ ⇩ ⇧ ⟽ ⟾ ⟺ "; echo " ∀ ∃ ∈ ∉ ⊂ ⊆ ⊇ ⊃ ⋀ ∧ ⋁ ∨ ≠ ≡ ≢ ≅ ≤ ≥ ∆ ⊲ ¬ ℚ ℕ ℤ ℂ ℝ ∞ ∑ "; echo " “en” ‘en’ „dt“ ‚dt‘ «Guillemets» ‹fr› 《アルバム》【quote】「kagikakko」 † € £ ¥ 円 "; echo " α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω "; echo " Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω "; echo " ā ē ī ō ū ä ë ï ö ü ß Ä Ë Ï Ö Ü § … ♂ ♀ € ĉ ŭ "; echo " ✓ 🗸 ✔ ✔️ ☑️ 🗹 ✅ ⍻ ⭕ 🗴 🗙 ❌ ❎ "; echo " “English” ‘quotation’ marks " echo " „Deutsche“ (99-66) ‚Anführungszeichen‘ »angeführt« ›erklärt‹ " echo " «Guillemets» " echo " TeX: ``english'' and ,,german``. " } wttr () { curl -4 http://wttr.in/Graz } lastmod() { local FP="$1" if [ -z "$FP" ]; then find . -exec stat "\\{\\}" --printf="%y\n" "\\;" | sort -n -r | head -n 1 else find "$FP" -exec stat "\\{\\}" --printf="%y\n" "\\;" | sort -n -r | head -n 1 fi } url-exists() { curl --output /dev/null --silent --head --fail $url if [ "$?" -ne 0 ]; then echo "URL does not exist"; fi } ## set environment variables #export EDITOR="nvim" #export PS1="\033[1m\033[38;2;40;80;255m《\033[38;2;80;200;80m\u\033[38;2;40;80;255m per \033[38;2;160;180;160m\h\033[38;2;40;80;255m ĉe \033[38;2;180;255;180m\W\033[38;2;40;80;255m je \033[38;2;0;220;0m\$(date --iso-8601=seconds)\033[38;2;40;80;255m》\033[0m\n⎔ " #export TERMINAL="konsole" export LC_ALL="en_US.UTF-8" #export GPGKEY="9B54D95F" #export TERM="xterm-256color" #export BAT_THEME=ansi # python config #export PYTHONSTARTUP="$HOME/.python/start.py" # golang config #export GOPATH="$HOME/dev/go" #export GOROOT="/opt/go" #export PATH="$PATH:$GOROOT/bin" #export PATH="$PATH:$GOPATH/bin" #export GOARM=7 #export GOMAXPROCS=4 # Qt config #export QT_ACCESSIBILITY=1 # bash config #HISTSIZE=-1 #HISTFILESIZE=-1