bin/ack: ack v3.8.1
[dotfiles.git] / .bashrc
diff --git a/.bashrc b/.bashrc
index e9f61a9b625b1034f8a3dbceabd5d657bfc13508..c549c458fed60f214eb0388590dcfdec8ce2b253 100644 (file)
--- a/.bashrc
+++ b/.bashrc
@@ -1,7 +1,15 @@
 #!/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=~}
@@ -16,32 +24,29 @@ HOSTFILE=~/.ssh/known_hosts
 # 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
@@ -58,21 +63,70 @@ ulimit -S -c 0
 # 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
@@ -96,13 +150,17 @@ export LANG LANGUAGE LC_CTYPE LC_ALL
 
 # 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
@@ -113,17 +171,19 @@ export 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
 
@@ -166,47 +226,64 @@ prompt_compact() {
 }
 
 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#*.}
@@ -215,7 +292,8 @@ test -z "$BASH_COMPLETION" && {
         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
@@ -226,24 +304,23 @@ test -z "$BASH_COMPLETION" && {
     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)"
@@ -264,93 +341,144 @@ test -n "$COLORS" &&
 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