From ff41d9acc805099f27f1cf060ca9db72d2fdb74f Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Mon, 30 Jan 2023 12:24:02 -0600 Subject: Bash! --- bash/aliases.bash | 20 ++++-- bash/bashrc | 2 +- bash/functions.bash | 166 +++++++++++++++++++++++++++++++++----------------- bash/history.bash | 38 +++++++++++- bash/prompt.bash | 56 +++++++++++------ bash/vterm-emacs.bash | 23 ------- 6 files changed, 201 insertions(+), 104 deletions(-) delete mode 100644 bash/vterm-emacs.bash diff --git a/bash/aliases.bash b/bash/aliases.bash index e29f62a..0132d33 100644 --- a/bash/aliases.bash +++ b/bash/aliases.bash @@ -20,17 +20,27 @@ alias ll='ls -l' alias tree='tree -F' # make locally -alias lake='make PREFIX=$HOME/usr ' +alias lake='make PREFIX=$LOCAL_PATH ' # bash meta alias rebash='source ~/.bash_profile' -# Debugging -alias emacs_goddamnit='pushd ~/.emacs.d;emacs --debug-init;popd' - # other alias radio=radish -if ! command -v fd >/dev/null 2>&1; then + +# `fd' installs as `fdfind' on some systems +if ! command -v fd >/dev/null 2>&1 && + command -v fdfind >/dev/null 2>&1 +then alias fd=fdfind fi +alias e="$EDITOR" + +## ffmpeg +# agafnd | i have ffmpeg and ffprobe aliased to ffwhatever -hide_banner +# agafnd | because if you don't do this it spits out all of the options it was +# | configured with every time you run it + +alias ffmpeg='ffmpeg -hide_banner' +alias ffprobe='ffprobe -hide_banner' diff --git a/bash/bashrc b/bash/bashrc index 63e56d4..9409c78 100644 --- a/bash/bashrc +++ b/bash/bashrc @@ -10,7 +10,7 @@ BASH_SOURCE_FIRST=( BASH_SOURCE_LAST=( blesh - vterm-emacs + emacs ) for f in "${BASH_SOURCE_FIRST[@]}"; do diff --git a/bash/functions.bash b/bash/functions.bash index 64e8001..97f89b8 100644 --- a/bash/functions.bash +++ b/bash/functions.bash @@ -1,89 +1,141 @@ # Functions memq() { # memq ITEM ARRAY - ## Test whether an ITEM is a member of ARRAY. - ## Pass ARRAY as ${ARRAY[@]}. - local e needle="$1" - shift - for e; do - [[ "$e" == "$needle" ]] && { - return 0 - } - done - return 1 + ## Test whether an ITEM is a member of ARRAY. + ## Pass ARRAY as ${ARRAY[@]}. + local e needle="$1" + shift + for e; do + [[ "$e" == "$needle" ]] && { + return 0 + } + done + return 1 } rebashrc() { # rebashrc - ## Reload ~/.bashrc - printf "Loading ~/.bashrc..." >&2 - if source "$HOME/.bashrc"; then - echo "OK." >&2 - else - echo "ERROR!" >&2 - fi + ## Reload ~/.bashrc + printf "Loading ~/.bashrc..." >&2 + if source "$HOME/.bashrc"; then + echo "OK." >&2 + else + echo "ERROR!" >&2 + fi } first_which() { # first_which COMMAND... - ## Return the fully-qualified path of the first COMMAND found in $PATH. - while :; do - command -v "$1" && break - [ -z "$1" ] && return 1 - shift - done + ## Return the fully-qualified path of the first COMMAND found in $PATH. + while :; do + command -v "$1" && break + [ -z "$1" ] && return 1 + shift + done } please() { # please [COMMAND...] - # if run without arguments, run the last command with 'sudo' (aka sudo !!) - # if run WITH arguments, alias as sudo - history -d -1 - if [ -z "$1" ]; then - #set -- $(HISTTIMEFORMAT=$'\t' history 2 | sed 's/^.*\t//;q') - set -- $(fc -lnr | sed 1q) - fi - echo >&2 sudo "$@" - history -s sudo "$@" - "${DEBUG:-false}" || sudo "$@" + # if run without arguments, run the last command with 'sudo' (aka sudo !!) + # if run WITH arguments, alias as sudo + history -d -1 + if [ -z "$1" ]; then + #set -- $(HISTTIMEFORMAT=$'\t' history 2 | sed 's/^.*\t//;q') + set -- $(fc -lnr | sed 1q) + fi + echo >&2 sudo "$@" + history -s sudo "$@" + "${DEBUG:-false}" || sudo "$@" } mkcd() { - if [ $# -lt 1 ]; then - command cd - return "$?" - fi - if [ "x$1" = x- ]; then - command cd - - return "$?" - fi - if ! [ -d "$1" ]; then - read -p "$1 doesn't exist. Create (y/N)? " yn - case "$yn" in - n* | N*) return 1 ;; - y* | Y*) mkdir -p "$1" ;; - *) return 1 ;; - esac - fi - command cd "$1" + if [ $# -lt 1 ]; then + command cd + return "$?" + fi + if [ "x$1" = x- ]; then + command cd - + return "$?" + fi + if ! [ -d "$1" ]; then + read -p "$1 doesn't exist. Create (y/N)? " yn + case "$yn" in + n* | N*) return 1 ;; + y* | Y*) mkdir -p "$1" ;; + *) return 1 ;; + esac + fi + command cd "$1" } alias cd='mkcd ' # from tomasino # alias julian='echo "x = $(date +%s); scale=5; x / 86400 + 2440587.5" | bc' julian() { - echo "x = $(date ${1:+-d "$*"} +%s); scale=5; x / 86400 + 2440587.5" | bc + echo "x = $(date ${1:+-d "$*"} +%s); scale=5; x / 86400 + 2440587.5" | bc } # find files for pipelines f() { - find "${1:-$PWD}" -depth | - while read -r file; do - printf '%q\n' "$file" - done + find "${1:-$PWD}" -depth | + while read -r file; do + printf '%q\n' "$file" + done } words() { grep "$1" /usr/share/dict/words } -dict() { - curl "dict://dict.org/d:$1" | less +if ! command -v dict >/dev/null 2>&1; then + dict() { + curl "dict://dict.org/d:$1" | less + } +fi + +if command -v thesauracles >/dev/null 2>&1; then + thesauraphrase() { + for word in "$@"; do + thesauracles -q "$word" + done | tr '\n' ' ' + echo + } +fi + +up() { + : "${UP_TODIRECTORY:=..}" + : "${UP_SPECIALARGS:=true}" + local ret=0 + # echo "$UP_TODIRECTORY" "$UP_SPECIALARGS" + if "$UP_SPECIALARGS"; then + case "$1" in + '') cd "$UP_TODIRECTORY" ;; + up) UP_TODIRECTORY="${UP_TODIRECTORY}/.." up "${@:2}" ;; + --) UP_SPECIALARGS=false up "${@:2}" ;; + -*) if (( "$1" == -1 )); then + up + else + UP_TODIRECTORY="${UP_TODIRECTORY}/.." up $(( "$1" + 1 )) + fi + ;; + *) while cd ..; do + case "$PWD" in + /) ret=1; break ;; + */"$1") break ;; + esac + done + ;; + esac + else + case "$1" in + '') cd "$UP_TODIRECTORY" ;; + *) while cd ..; do + case "$PWD" in + /) ret=1; break ;; + */"$1") break ;; + esac + done + ;; + esac + fi + UP_TODIRECTORY= + UP_SPECIALARGS= + return "$ret" } diff --git a/bash/history.bash b/bash/history.bash index 95edf9d..d2bdceb 100644 --- a/bash/history.bash +++ b/bash/history.bash @@ -1,5 +1,5 @@ # Bash history settings -# I don't export any variables in this file because history settings +# I don't export any variables in this file because history settings # really only apply in an interactive session. # XDG compliance @@ -33,3 +33,39 @@ HISTIGNORE="$HISTIGNORE:ls:exit:cd" # Automatically append to HISTFILE on every command PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-:}" + +## Make a new function from a history item: WIP +# In particular, the arguments of this function could be better imo +histfunc() { # histfunc NAME QUERY + local name="$1" + local query="$2" + local -a cands + while read -r cmd; do + cands=( "${cands[@]}" "$cmd" ) + done < <(grep -E "$query" "$HISTFILE" | sort | uniq) + if (( "${#cands[@]}" == 1 )); then + funcbody="${cands[0]}" + else + select funcbody in "${cands[@]}"; do break; done + fi + eval "$name() { $funcbody; }" +} + +funcsave() { # funcsave FUNC FILENAME + (( $# == 2 )) || { + echo "Wrong number of arguments (need 2)" >&2 + return 1 + } + cat < "$2" +#!/usr/bin/env bash +# saved with 'funcsave' + +$(type "$1" | sed 1d) + +if [[ "\${BASH_SOURCE[0]}" == "\$0" ]]; then + [[ "\$DEBUG" ]] && set -x + "$1" "\$@" +fi +EOF + chmod +x "$2" +} diff --git a/bash/prompt.bash b/bash/prompt.bash index 06ca638..f09d3ab 100644 --- a/bash/prompt.bash +++ b/bash/prompt.bash @@ -1,8 +1,32 @@ # bash prompt -if [[ -n "$INSIDE_EMACS" ]]; then - PS1="\n\[\e[34m\]\$ \[\e[0m\]" -else +MY_BASH_PROMPT=smiley_prompt + +# terminal title (current directory) +__prompt_term_title() { # __prompt_term_title TITLE... + printf '\033]0;%s\007\n' "$*" +} + +__prompt_exit_code() { # __prompt_exit_code CODES... + # Each CODE is of the form N=STR. If the code doesn't match one of CODES, + # its number will be printed. + local ec=$? + for code; do + if ((ec == ${code%=*})); then + printf '%s\n' "${code#*=}" + return + elif ((ec == 0)) && [[ "${code%=*}" = ok ]]; then + printf '%s\n' "${code#*=}" + return + elif ((ec > 0)) && [[ "${code%=*}" = fail ]]; then + printf '%s\n' "${code#*=}" + return + fi + done + printf '%s\n' "$ec" +} + +two_line_prompt() { PS1= # user, host, and cwd @@ -21,7 +45,7 @@ else for file in "${possible_git_prompt_locations[@]}"; do if [[ -f "$file" ]]; then source "$file" && - PS1+='\[\e[35m\]$(__git_ps1)' + PS1+='\[\e[0m\]\[\e[35m\]$(__git_ps1)' break fi done @@ -29,20 +53,18 @@ else # newline PS1+='\[\e[0m\]\n' - # exit code (only if error) - __prompt_exit_code() { - local ec=$? - (($ec > 0)) && - printf "$ec" - } - PS1+='\[\e[31m\]$(__prompt_exit_code)\[\e[0m\]' - - # terminal title (current directory) - __prompt_term_title() { - printf '\033]0;%s\007\n' "$*" - } + PS1+='\[\e[31m\]$(__prompt_exit_code 0=)\[\e[0m\]' PS1+='\[$(__prompt_term_title "$USER@$(hostname): $PWD")\]' # delimiter PS1+='; ' -fi +} + +smiley_prompt() { + __prompt_ec() { case $? in 0) echo '^_^' ;; *) echo ';_;' ;; esac } + PS1='\[\e[1m\]$(__prompt_exit_code "ok=^_^" "fail=;_;") \w\[\e[0m\] ' + PS1+='\[$(__prompt_term_title "$USER@$(hostname): $PWD")\]' + PS1+='\$ ' +} + +eval "$MY_BASH_PROMPT" diff --git a/bash/vterm-emacs.bash b/bash/vterm-emacs.bash deleted file mode 100644 index 88d3e09..0000000 --- a/bash/vterm-emacs.bash +++ /dev/null @@ -1,23 +0,0 @@ -# shell-side configuration for Emacs vterm module -# https://github.com/akermu/emacs-libvterm#shell-side-configuration -# Make sure this is the last file loaded by ~/.bashrc! - -# Load the requisite code from the vterm install directory -if [[ "$INSIDE_EMACS" = 'vterm' ]] \ - && [[ -n ${EMACS_VTERM_PATH} ]] \ - && [[ -f ${EMACS_VTERM_PATH}/etc/emacs-vterm-bash.sh ]]; then - source ${EMACS_VTERM_PATH}/etc/emacs-vterm-bash.sh -fi - -# Extra commands for `vterm-eval-cmds' - -find_file() { - vterm_cmd find-file "$(realpath "${@:-.}")" -} - -say() { - vterm_cmd message "%s" "$*" -} - - - -- cgit 1.4.1-21-gabe81