#!/usr/bin/env bash # Best bashrc in history # # Author: Shane Peters # SSH agent SSH_ENV="$HOME/.ssh/agent-environment" start_agent() { /usr/bin/ssh-agent | sed 's/^echo/#echo/' >"$SSH_ENV" chmod 600 "$SSH_ENV" . {$SSH_ENV} >/dev/null /usr/bin/ssh-add; } if [ -f "${SSH_ENV}" ]; then . ${SSH_ENV} >/dev/null ps -ef | grep $SSH_AGENT_PID | grep ssh-agent$ >/dev/null || { start_agent } else start_agent fi # Set environment # Support colors in less export LESS_TERMCAP_mb=$(tput bold; tput setaf 1) export LESS_TERMCAP_md=$(tput bold; tput setaf 1) export LESS_TERMCAP_me=$(tput sgr0) export LESS_TERMCAP_se=$(tput sgr0) export LESS_TERMCAP_so=$(tput bold; tput setaf 3; tput setab 4) export LESS_TERMCAP_ue=$(tput sgr0) export LESS_TERMCAP_us=$(tput smul; tput bold; tput setaf 2) export LESS_TERMCAP_mr=$(tput rev) export LESS_TERMCAP_mh=$(tput dim) export LESS_TERMCAP_ZN=$(tput ssubm) export LESS_TERMCAP_ZV=$(tput rsubm) export LESS_TERMCAP_ZO=$(tput ssupm) export LESS_TERMCAP_ZW=$(tput rsupm) # # Alternate Paths # [[ -d ~/Bin ]] && export PATH=~/Bin:$PATH # local binaries & scripts [[ -d ~/Bin/streams ]] && export PATH=~/Bin/streams:$PATH # radio streams [[ -d /usr/local/cuda/bin ]] && export PATH=/usr/local/cuda-11.8/bin:$PATH [[ -d /opt/node/node/bin ]] && export PATH=/opt/node/node/bin:$PATH # local binaries & scripts [[ -d /opt/zeek/bin ]] && export PATH=/opt/zeek/bin:$PATH [[ -d ~/.local/bin ]] && export PATH=~/bin:~/.local/bin:$PATH [[ -d ~/.cargo/bin ]] && export PATH=~/.cargo/bin:$PATH # # App env variables # export EDITOR='vim' export GREP_COLOR='1;36' export HISTIGNORE="&:[ ]*:ls:ls -a:cd:cd .." # leave commands out of history log export HISTCONTROL='ignoredups' export HISTSIZE=5000 export HISTFILESIZE=5000 export LSCOLORS='ExGxbEaECxxEhEhBaDaCaD' export PAGER='less' export TZ='America/New_York' export VAULT_TOKEN=root export VAULT_ADDR=http://127.0.0.1:8200 export LANG=en_US.utf8 export VISUAL=$EDITOR [[ -x /usr/bin/lesspipe ]] && eval "$(SHELL=/bin/sh lesspipe)" # less more friendly for non-text # # bash options # shopt -s cdspell shopt -s extglob shopt -s checkwinsize # updates values of LINES and COLUMNS shopt -s nocaseglob # case-insensitive pathname expansion shopt -s autocd # enter directory without cd shopt -s cdspell # correct minor errors in directory names with cd shopt -s dirspell # attempt spelling correction on directory names in completion shopt -s dotglob # includes filenames beginning with a `.' in filename expansion shopt -s histappend # append to history file, instead of overwriting it shopt -s no_empty_cmd_completion # not attempt to search for possible completions on an empty line. shopt -s globstar # recursive globbing with ** shopt -s expand_aliases # expand aliases shopt -s cmdhist # save all lines of a multiline command in same entry shopt -s lithist # save all lines of a multiline command in same entry stty -ixon # disable ^S/^Q flow control # # colors # #alias ls='ls --color=auto' # ls colored output export GREP_COLOR="mt=1;36" # grep colored ouput alias grep='grep --color=auto' # grep colored ouput export LESS="-R" # less colored output export LESS_TERMCAP_mb=$'\E[01;31m' # begin blinking export LESS_TERMCAP_md=$'\E[01;38;5;74m' # begin bold export LESS_TERMCAP_me=$'\E[0m' # end mode export LESS_TERMCAP_se=$'\E[0m' # end standout-mode export LESS_TERMCAP_so=$'\E[38;5;246m' # begin standout-mode - info box export LESS_TERMCAP_ue=$'\E[0m' # end underline export LESS_TERMCAP_us=$'\E[04;38;5;146m' # begin underline # Aliases alias ..='echo "cd .."; cd ..' alias ag='rg' # sorry silver searcher alias chomd='chmod' alias curl='curl -A "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"' alias externalip='curl -sS https://www.daveeddy.com/ip' alias gerp='grep' alias hl='rg --passthru' alias l='ls' alias ll='ls -lrtha' alias suod='sudo' alias gl='git log -p' alias wget='wget --user-agent="Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"' alias vrd='VAULT_UI=true VAULT_REDIRECT_ADDR=http://127.0.0.1:8200 vault server -log-level=trace -dev -dev-root-token-id=root' # Git Aliases alias nb='git checkout -b "$USER-$(date +%s)"' # new branch alias ga='git add . --all' alias gb='git branch' alias gc='git clone' alias gci='git commit -a' alias gco='git checkout' alias gd="git diff ':!*lock'" alias gdf='git diff' # git diff (full) alias gi='git init' alias gl='git log' alias gp='git push origin HEAD' alias gr='git rev-parse --show-toplevel' # git root alias gs='git status' alias gt='git tag' alias gu='git pull' # gu = git update # Functions sscreate() { openssl req \ -x509 \ -nodes \ -newkey rsa:4096 \ -keyout $1_key.pem \ -out $1_cert.pem \ -days 365 \ -subj "/C=US/ST=Ohio/L=Columbus/O=ColumOps/OU=OPS/CN=$1" } compress() { FILE=$1 case $FILE in *.tar.bz2) shift && tar cjf $FILE $* ;; *.tar.gz) shift && tar czf $FILE $* ;; *.tgz) shift && tar czf $FILE $* ;; *.zip) shift && zip $FILE $* ;; *.rar) shift && rar $FILE $* ;; *.7z) shift && 7za a $FILE $* ;; esac } extract() { local e=0 i c for i; do if [ -f $i && -r $i ]; then c= case $i in *.tar.bz2) c='tar xjf' ;; *.tar.gz) c='tar xzf' ;; *.bz2) c='bunzip2' ;; *.gz) c='gunzip' ;; *.tar) c='tar xf' ;; *.tbz2) c='tar xjf' ;; *.tgz) c='tar xzf' ;; *.7z) c='7z x' ;; *.Z) c='uncompress' ;; *.exe) c='cabextract' ;; *.rar) c='unrar x' ;; *.xz) c='unxz' ;; *.zip) c='unzip' ;; *) echo "$0: cannot extract \`$i': Unrecognized file extension" >&2; e=1 ;; esac [ $c ] && command $c "$i" else echo "$0: cannot extract \`$i': File is unreadable" >&2; e=2 fi done return $e } mkiso() { mkisofs -V $2 -J -r $1 -o isoimage.iso } # because `master` is sometimes `main` (or others), these must be functions. gmb() { # git main branch local main main=$(git symbolic-ref --short refs/remotes/origin/HEAD) main=${main#origin/} [[ -n $main ]] || return 1 echo "$main" } # show the diff from inside a branch to the main branch gbd() { # git branch diff local mb=$(gmb) || return 1 git diff "$mb..HEAD" } # checkout the main branch and update it gcm() { # git checkout $main local mb=$(gmb) || return 1 git checkout "$mb" && git pull } # merge the main branch into our branch gmm() { # git merge $main local mb=$(gmb) || return 1 git merge "$mb" } # Prompt # Store `tput` colors for future use to reduce fork+exec # the array will be 0-255 for colors, 256 will be sgr0 # and 257 will be bold COLOR256=() COLOR256[0]=$(tput setaf 1) COLOR256[256]=$(tput sgr0) COLOR256[257]=$(tput bold) # Colors for use in PS1 that may or may not change when # set_prompt_colors is run PROMPT_COLORS=() # Change the prompt colors to a theme, themes are 0-29 set_prompt_colors() { local h=${1:-0} local color= local i=0 local j=0 for i in {22..231}; do ((i % 30 == h)) || continue color=${COLOR256[$i]} # cache the tput colors if [[ -z $color ]]; then COLOR256[$i]=$(tput setaf "$i") color=${COLOR256[$i]} fi PROMPT_COLORS[$j]=$color ((j++)) done } # Construct the prompt # [(exit code)] - [git branch] <$|#> # exit code of last process PS1='$(ret=$?;(($ret!=0)) && echo "\[${COLOR256[0]}\]($ret) \[${COLOR256[256]}\]")' # username (red for root) PS1+='\[${PROMPT_COLORS[0]}\]\[${COLOR256[257]}\]$(((UID==0)) && echo "\[${COLOR256[0]}\]")\u\[${COLOR256[256]}\]@' # hostname PS1+='\[${PROMPT_COLORS[3]}\]\h ' # zonename (global zone warning) # PS1+='\[${COLOR256[0]}\]\[${COLOR256[257]}\]'"$(zonename 2>/dev/null | grep -q '^global$' && echo 'GZ:')"'\[${COLOR256[256]}\]' # uname #PS1+='\[${PROMPT_COLORS[2]}\]'"$(uname | tr '[:upper:]' '[:lower:]')"' ' # cwd PS1+='\[${PROMPT_COLORS[5]}\]\w ' # optional git branch PS1+='$(branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null); [[ -n $branch ]] && echo "\[${PROMPT_COLORS[2]}\](\[${PROMPT_COLORS[3]}\]git:$branch\[${PROMPT_COLORS[2]}\]) ")' # prompt character PS1+='\[${PROMPT_COLORS[0]}\]\$\[${COLOR256[256]}\] ' # set the theme set_prompt_colors 24 # Prompt command _prompt_command() { local user=$USER local host=${HOSTNAME%%.*} local pwd=${PWD/#$HOME/\~} local ssh= [[ -n $SSH_CLIENT ]] && ssh='[ssh] ' printf "\033]0;%s%s@%s:%s\007" "$ssh" "$user" "$host" "$pwd" } PROMPT_COMMAND=_prompt_command PROMPT_DIRTRIM=6 # Print all 256 colors colors() { local i for i in {0..255}; do printf "\x1b[38;5;${i}mcolor %d\n" "$i" done tput sgr0 } # Copy stdin to the clipboard copy() { pbcopy 2>/dev/null || xsel 2>/dev/null || clip.exe } # Convert epoch to human readable (print current date if no args) epoch() { local num=${1:--1} printf '%(%B %d, %Y %-I:%M:%S %p %Z)T\n' "$num" } # Open the current path or file in GitHub gho() { local file=$1 local remote=${2:-origin} # get the git root dir, branch, and remote URL local gr=$(git rev-parse --show-toplevel) local branch=$(git rev-parse --abbrev-ref HEAD) local url=$(git config --get "remote.$remote.url") [[ -n $gr && -n $branch && -n $remote ]] || return 1 # construct the path local path=${PWD/#$gr/} [[ -n $file ]] && path+=/$file # extract the username and repo name local a IFS=:/ read -a a <<< "$url" local len=${#a[@]} local user=${a[len-2]} local repo=${a[len-1]%.git} url="https://github.com/$user/$repo/tree/$branch$path" echo "$url" open "$url" } # Platform-independent interfaces interfaces() { node <<-EOF var os = require('os'); var i = os.networkInterfaces(); Object.keys(i).forEach(function(name) { i[name].forEach(function(int) { if (int.family === 'IPv4') { console.log('%s: %s', name, int.address); } }); }); EOF } # Calculate CPU load / Core Count load() { node -p <<-EOF var os = require('os'); var c = os.cpus().length; os.loadavg().map(function(l) { return (l/c).toFixed(2); }).join(' '); EOF } # Platform-independent memory usage meminfo() { node <<-EOF var os = require('os'); var free = os.freemem(); var total = os.totalmem(); var used = total - free; console.log('memory: %dmb / %dmb (%d%%)', Math.round(used / 1024 / 1024), Math.round(total / 1024 / 1024), Math.round(used * 100 / total)); EOF } # print lines over X columns (defaults to 80) over() { awk -v c="${1:-80}" 'length($0) > c { printf("%4d %s\n", NR, $0); }' } # print a rainbow if truecolor is available to the terminal truecolor-rainbow() { local i r g b for ((i = 0; i < 77; i++)); do r=$((255 - (i * 255 / 76))) g=$((i * 510 / 76)) b=$((i * 255 / 76)) ((g > 255)) && g=$((510 - g)) printf '\033[48;2;%d;%d;%dm ' "$r" "$g" "$b" done tput sgr0 echo } # Follow redirects to untiny a tiny url untiny() { local location=$1 local last_location='' while [[ -n $location ]]; do [[ -n $last_location ]] && echo " -> $last_location" last_location=$location read -r _ location < \ <(curl -sI "$location" | grep 'Location: ' | tr -d '[:cntrl:]') done echo "$last_location" } # load completions source /usr/share/bash-completion/completions/fzf source /usr/share/doc/fzf/examples/key-bindings.bash source /etc/bash/bash_completion 2>/dev/null # done true