#!/bin/bash
# ~/.bashrc: executed by bash(1) for non-login shells.
# A basically sane bash environment.
-# Tony Duckles <http://nynim.org/about/> (based on http://github.com/rtomayko/dotfiles)
+# Resources:
+# - https://github.com/rtomayko/dotfiles/blob/rtomayko/.bashrc
+
+# ---------------------------------------------------------------------------
+# BASICS
+# ---------------------------------------------------------------------------
+
+# short-circuit for non-interactive sessions
+[ -z "$PS1" ] && return
# the basics
: ${HOME=~}
# readline config
INPUTRC=~/.inputrc
-# if current $TERM isn't valid, fall-back to TERM=xterm-color
+# if current $TERM isn't valid, fall-back to TERM=xterm-color or TERM=xterm
case $(tput colors 2>&1) in
tput* )
export TERM=xterm-color
+ case $(tput colors 2>&1) in
+ tput* )
+ export TERM=xterm
+ ;;
+ esac
;;
esac
-if [ "$UNAME" = "Darwin" ]; then
- # Fink init, for OSX
- test -r /sw/bin/init.sh &&
- source /sw/bin/init.sh
-fi
-
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# SHELL OPTIONS
-# ----------------------------------------------------------------------
-
-# bring in system bashrc
-test -r /etc/bashrc &&
- . /etc/bashrc
+# ---------------------------------------------------------------------------
# notify of bg job completion immediately
set -o notify
# shell opts. see bash(1) for details
shopt -s cdspell >/dev/null 2>&1
+shopt -s checkjobs >/dev/null 2>&1
+shopt -s checkwinsize >/dev/null 2>&1
shopt -s extglob >/dev/null 2>&1
shopt -s histappend >/dev/null 2>&1
shopt -s hostcomplete >/dev/null 2>&1
# default umask
umask 0022
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# PATH
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
-# we want the various sbins on the path along with /usr/local/bin
+unset path_start path_end manpath_start manpath_end
+
+# make sure $MANPATH has some sane defaults
+MANPATH="/usr/share/man:/usr/local/share/man:$MANPATH"
+
+# include the various sbin's along with /usr/local/bin
PATH="$PATH:/usr/local/sbin:/usr/sbin:/sbin"
PATH="/usr/local/bin:$PATH"
-# put ~/bin on PATH if you have it
-test -d "$HOME/bin" &&
- PATH="$HOME/bin:$PATH"
+# use $HOME specific bin and sbin
+path_start="$path_start:$HOME/bin"
+test -d "$HOME/sbin" && path_start="$path_start:$HOME/sbin"
+
+# macOS homebrew
+if [ -x "/opt/homebrew/bin/brew" ]; then
+ eval "$(/opt/homebrew/bin/brew shellenv)"
+ # include non-prefixed coreutils
+ if [ -d "/opt/homebrew/opt/coreutils/libexec" ]; then
+ path_start="/opt/homebrew/opt/coreutils/libexec/gnubin:$path_start"
+ manpath_start="/opt/homebrew/opt/coreutils/libexec/gnuman:$manpath_start"
+ fi
+fi
-# ----------------------------------------------------------------------
+# SmartOS: local pkgin binaries
+if [ -d "/opt/local" ]; then
+ path_start="$path_start:/opt/local/sbin:/opt/local/bin"
+ manpath_start="$manpath_start:/opt/local/man"
+fi
+# SmartOS: local custom scripts
+if [ -d "/opt/custom" ]; then
+ path_start="$path_start:/opt/custom/sbin:/opt/custom/bin"
+ manpath_start="$manpath_start:/opt/custom/man"
+fi
+# SmartOS: SDC
+if [ -d "/smartdc" ]; then
+ path_start="$path_start:/smartdc/bin:/opt/smartdc/bin:/opt/smartdc/agents/bin"
+ manpath_start="$manpath_start:/smartdc/man"
+fi
+# SmartOS: native binaries, for OS/LX zones
+if [ -d "/native" ]; then
+ path_end="$path_end:/native/usr/sbin:/native/usr/bin:/native/sbin:/native/bin"
+ manpath_end="$manpath_end:/native/usr/share/man"
+fi
+
+PATH="$path_start:$PATH:$path_end"
+MANPATH="$manpath_start:$MANPATH:$manpath_end"
+unset path_start path_end manpath_start manpath_end
+
+# python: pip --user
+for python in "python" "python2" "python3"; do
+ if [ -n "$(type -P $python)" ]; then
+ pybin="$($python -m site --user-base)/bin"
+ test -d "$pybin" && PATH="$PATH:$pybin"
+ fi
+done
+unset python pybin
+
+# ---------------------------------------------------------------------------
# ENVIRONMENT CONFIGURATION
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# detect interactive shell
case "$-" in
# ignore backups, CVS directories, python bytecode, vim swap files
FIGNORE="~:CVS:#:.pyc:.swp:.swa:apache-solr-*"
+
+# history stuff
HISTCONTROL=ignoreboth
+HISTFILESIZE=10000
+HISTSIZE=10000
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# PAGER / EDITOR
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
-# See what we have to work with ...
+# see what we have to work with ...
HAVE_VIM=$(command -v vim)
# EDITOR
# PAGER
if test -n "$(command -v less)" ; then
- PAGER="less -FirSwX"
- MANPAGER="less -FiRswX"
+ PAGER="less"
+ MANPAGER="less"
+ LESS="-FiRX"
+ export LESS
else
PAGER=more
MANPAGER="$PAGER"
fi
export PAGER MANPAGER
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# PROMPT
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
}
prompt_color() {
- PS1="\[\033[0;90m\][${PS_C1}\u@\h\[\033[0m\]\[\033[0;90m\]:${PS_C2}\w\[\033[0;90m\]]${PS_P}\[\033[0m\] "
+ # if git and the git bash_completion scripts are installed, use __git_ps1()
+ # to show current branch info.
+ # - never show branch info for $HOME (dotfiles) repo.
+ # - optionally hide branch info for git repo's with `bash.hidePrompt`
+ # config flag set. use the following to exclude a given repo:
+ # `git config --local --bool --add bash.hidePrompt true`
+ if [ -n "$(type -P git)" -a "$(type -t __git_ps1)" = "function" ]; then
+ home_canonical="$(test -n "$(type -P realpath)" && realpath $HOME || echo $HOME)"
+ PS_GIT='$(test -n "$(__git_ps1 %s)" &&
+ test "$(git rev-parse --show-toplevel)" != "$home_canonical" &&
+ test "$(git config --bool bash.hidePrompt)" != "true" &&
+ __git_ps1 "{\[\033[0;40;36m\]%s\[\033[0;90m\]}")'
+ export GIT_PS1_SHOWDIRTYSTATE=1
+ fi
+ PS1="\[\033[0;90m\][${PS_C1}\u@\h\[\033[0m\]\[\033[0;90m\]:${PS_C2}\w\[\033[0;90m\]]${PS_GIT}${PS_P}\[\033[0m\] "
PS2="> "
}
-# ----------------------------------------------------------------------
-# MACOS X / DARWIN SPECIFIC
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
+# ALIASES
+# ---------------------------------------------------------------------------
+
+# 'ls' helpers
+alias ll="ls -l"
+alias l.="ls -d .*"
+alias ll.="ls -ld .*"
+alias lla="ls -la"
-if [ "$UNAME" = Darwin ]; then
- # put ports on the paths if /opt/local exists
- test -x /opt/local -a ! -L /opt/local && {
- PORTS=/opt/local
+# use 'git diff --no-index' as a prettier 'diff' alternative (if available)
+test -n "$(type -P git)" && alias diff="git diff --no-index"
- # setup the PATH and MANPATH
- PATH="$PORTS/bin:$PORTS/sbin:$PATH"
- MANPATH="$PORTS/share/man:$MANPATH"
+# alias 'vi' to 'vim' if Vim is installed
+test -n "$(type -P vim)" && alias vi='vim'
- # nice little port alias
- alias port="sudo nice -n +18 $PORTS/bin/port"
- }
-fi
+# alias csh-style "rebash" to bash equivalent
+alias rehash="hash -r"
-# ----------------------------------------------------------------------
-# ALIASES / FUNCTIONS
-# ----------------------------------------------------------------------
+# svn-wrapper
+alias svn=svn-wrapper
-# alias 'vi' to 'vim' if Vim is installed
-vim="$(type -P vim)"
-test -n "$vim" && {
- alias vi='vim'
-}
-unset vim
+# docker helpers
+if [ -n "$(type -P docker)" ]; then
+ alias docker-ps="docker ps -a --format \"table {{.ID}}\t{{.Names}}\t{{.State}}\t{{.Status}}\t{{.Networks}}\""
+ alias docker-tail="docker logs -tf --tail 50"
+ alias docker-top="docker run --name ctop -it --rm -v /var/run/docker.sock:/var/run/docker.sock quay.io/vektorlab/ctop"
+ alias ctop="docker-top"
+fi
-# disk usage with human sizes and minimal depth
-alias du1='du -h --max-depth=1'
-alias fn='find . -name'
-alias hi='history | tail -20'
+if [ "$UNAME" = SunOS ]; then
+ # Solaris: use GNU versions of coreutils
+ test -x /usr/gnu/bin/grep && alias grep="/usr/gnu/bin/grep"
+ test -x /usr/gnu/bin/sed && alias sed="/usr/gnu/bin/sed"
+ test -x /usr/gnu/bin/awk && alias awk="/usr/gnu/bin/awk"
+fi
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# BASH COMPLETION
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
test -z "$BASH_COMPLETION" && {
bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.}
for f in /usr/local/etc/bash_completion \
/usr/pkg/etc/bash_completion \
/opt/local/etc/bash_completion \
- /etc/bash_completion
+ /etc/bash_completion \
+ /etc/bash/bash_completion
do
test -f $f && {
. $f
unset bash bmajor bminor
}
+# restore some key environment variables which may have been unset
+# by bash_completion script
+: ${HOME=~}
+: ${LOGNAME=$(id -un)}
+: ${UNAME=$(uname)}
+
# override and disable tilde expansion
-_expand()
-{
+_expand() {
return 0
}
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# LS AND DIRCOLORS
-# ----------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# we always pass these to ls(1)
-unset LS_COMMON
-## OS-specific options
-#case "$UNAME" in
-# "Linux" ) LS_COMMON="--color=auto";;
-# "Cygwin" ) LS_COMMON="--color=auto";;
-# "Darwin" ) LS_COMMON="--color=auto";;
-#esac
+LS_COMMON="-p"
# if the dircolors utility is available, set that up for ls
dircolors="$(type -P gdircolors dircolors | head -1)"
test -n "$LS_COMMON" &&
alias ls="command ls $LS_COMMON"
-# these use the ls aliases above
-alias ll="ls -l"
-alias l.="ls -d .*"
-alias ll.="ls -ld .*"
-alias lla="ls -la"
-
# setup color grep output if available
-test -n "$COLORS" &&
- alias grep="command grep --color=auto"
-
-# --------------------------------------------------------------------
-# MISC COMMANDS
-# --------------------------------------------------------------------
-
-# push SSH public key to another box
-push_ssh_cert() {
- local _host
- test -f ~/.ssh/id_rsa.pub || ssh-keygen -t rsa -b 4096
- for _host in "$@";
- do
- echo $_host
- ssh $_host 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub
- done
+if [ -n "$COLORS" ]; then
+ case "$UNAME" in
+ "Darwin")
+ export GREP_COLOR='1;32' # BSD grep
+ ;;
+ *)
+ export GREP_COLORS='fn=36:ln=33:ms=1;32' # GNU grep
+ ;;
+ esac
+ case "$UNAME" in
+ "SunOS")
+ test -x /usr/gnu/bin/grep && alias grep="/usr/gnu/bin/grep --color=always"
+ test -x /opt/local/bin/grep && alias grep="/opt/local/bin/grep --color=always"
+ ;;
+ *)
+ alias grep="command grep --color=always"
+ ;;
+ esac
+fi
+
+# ---------------------------------------------------------------------------
+# MISC FUNCTIONS
+# ---------------------------------------------------------------------------
+
+# set 'screen' window title
+settitle_screen() {
+ printf "\033k%s\033\\" "$@"
+}
+# set 'xterm' window title
+settitle_window() {
+ printf "\033]0;%s\007" "$@"
}
-# --------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# PATH MANIPULATION FUNCTIONS
-# --------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# Usage: pls [<var>]
# List path entries of PATH or environment variable <var>.
-pls () { eval echo \$${1:-PATH} |tr : '\n'; }
-
-# Usage: pshift [-n <num>] [<var>]
-# Shift <num> entries off the front of PATH or environment var <var>.
-# with the <var> option. Useful: pshift $(pwd)
-pshift () {
- local n=1
- [ "$1" = "-n" ] && { n=$(( $2 + 1 )); shift 2; }
- eval "${1:-PATH}='$(pls |tail -n +$n |tr '\n' :)'"
-}
+pls () { eval echo \$${1:-PATH} | tr ':' '\n'; }
# Usage: ppop [-n <num>] [<var>]
# Pop <num> entries off the end of PATH or environment variable <var>.
ppop () {
- local n=1 i=0
+ local n=1
[ "$1" = "-n" ] && { n=$2; shift 2; }
- while [ $i -lt $n ]
- do eval "${1:-PATH}='\${${1:-PATH}%:*}'"
- i=$(( i + 1 ))
+ local i=0 var=${1:-PATH}
+ local list=$(eval echo \$$var)
+ while [ $i -lt $n ]; do
+ list=${list%:*}
+ i=$(( i + 1 ))
+ done
+ eval "$var='$list'"
+}
+
+# Usage: ppush <path> [<var>]
+# Push an entry onto the end of PATH or enviroment variable <var>.
+ppush () {
+ local var=${2:-PATH}
+ local list=$(eval echo \$$var)
+ local i=0 dir=""
+ IFS=':' read -a dirs <<< "$1"
+ for ((i=0; i<${#dirs[@]}; i++)); do
+ dir=$(eval echo "${dirs[$i]}")
+ [ ! -d "$dir" ] && continue
+ [ -n "$list" ] && list="$list:$dir" || list="$dir"
+ done
+ eval "$var='$list'"
+}
+
+# Usage: pinsert <path> [<var>]
+# Push an entry onto the start of PATH or enviroment variable <var>.
+pinsert () {
+ local var=${2:-PATH}
+ local list=$(eval echo \$$var)
+ local i=0 dir=""
+ IFS=':' read -a dirs <<< "${1}"
+ for ((i=${#dirs[@]}-1; i>=0; i--)); do
+ dir=$(eval echo "${dirs[$i]}")
+ [ ! -d "$dir" ] && continue
+ [ -n "$list" ] && list="$dir:$list" || list="$dir"
done
+ eval "$var='$list'"
}
# Usage: prm <path> [<var>]
# Remove <path> from PATH or environment variable <var>.
-prm () { eval "${2:-PATH}='$(pls $2 |grep -v "^$1\$" |tr '\n' :)'"; }
+prm () { eval "${2:-PATH}='$(pls $2 | grep -v "^$1\$" | tr '\n' ':')'"; }
-# Usage: punshift <path> [<var>]
-# Shift <path> onto the beginning of PATH or environment variable <var>.
-punshift () { eval "${2:-PATH}='$1:$(eval echo \$${2:-PATH})'"; }
-
-# Usage: puniq [<path>]
+# Usage: puniq [<pathlist>]
# Remove duplicate entries from a PATH style value while retaining
# the original order. Use PATH if no <path> is given.
#
# Example:
# $ puniq /usr/bin:/usr/local/bin:/usr/bin
# /usr/bin:/usr/local/bin
-puniq () {
- echo "$1" | tr : '\n' | nl | sort -u -k 2,2 | sort -n |
- cut -f 2- | tr '\n' : | sed -e 's/:$//' -e 's/^://'
-}
+puniq () { echo "$1" | tr ':' '\n' | grep -v "^$" | nl | sort -u -k 2,2 | sort -n | cut -f 2- | paste -s -d ':' -; }
-# -------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# USER SHELL ENVIRONMENT
-# -------------------------------------------------------------------
+# ---------------------------------------------------------------------------
# source ~/.shenv now if it exists
test -r ~/.shenv &&
. ~/.shenv
# condense PATH entries
-PATH=$(puniq $PATH)
-MANPATH=$(puniq $MANPATH)
+PATH=$(puniq "$PATH")
+MANPATH=$(puniq "$MANPATH")
-# Use the color prompt by default when interactive
+# use the color prompt by default when interactive
test -n "$PS1" &&
prompt_color
+# ripgrep
+export RIPGREP_CONFIG_PATH="$HOME/.ripgreprc"
+
+# fzf
+export FZF_DEFAULT_COMMAND="rg --files --hidden --follow --color=never 2> /dev/null"
+export FZF_DEFAULT_OPTS='--bind J:down,K:up --reverse --ansi --multi'
+
+# ---------------------------------------------------------------------------
+# MOTD / FORTUNE
+# ---------------------------------------------------------------------------
+
+test -n "$INTERACTIVE" -a -n "$LOGIN" && {
+ # get current uname and uptime (if exists on this host)
+ # strip any leading whitespace from uname and uptime commands
+ t_uname="$(test -n "`type -P uname`" && uname -npsr | sed -e 's/^\s+//')"
+ t_uptime="$(test -n "`type -P uptime`" && uptime | sed -e 's/^\s+//')"
+ if [ -n "$t_uname" ] || [ -n "$t_uptime" ]; then
+ echo " --"
+ test -n "$t_uname" && echo $t_uname
+ test -n "$t_uptime" && echo $t_uptime
+ echo " --"
+ fi
+ unset t_uname t_uptime
+}
+
# vim: ts=4 sts=4 shiftwidth=4 expandtab