I currently maintain a repository with my current dotfiles which you can clone here:
git clone https://github.com/richinfante/dotfiles-archive.git
~/.bash_profile
First, I start with some configuration options.
Depending on the system I may change these in the config file (~/.bash_config
)
# Customizable Options
GIT_BRANCH_CHAR="↳"
PROMPT_GIT="true"
PROMPT_DATE="false"
# If we're in a tty,
if [ -t 1 ] ; then
export TERM=xterm-256color
COLORS_ENABLED=true
# Bash tab completion
bind 'TAB:menu-complete'
fi
# Run Bash config
if [ -f ~/.bash_config ]; then
source ~/.bash_config
fi
Next, I set up color support. This includes variables for light/dark variants, as well as control sequences for resetting and blinking text.
# Colors
if [ "$COLORS_ENABLED" != "false" ]; then
export RED="\033[31m"
export LIGHT_RED="\033[91m"
# ... (removed for brevity)
export RESET="\033[0m"
export BOLD="\033[1m"
export DIM="\033[2m"
export UNDERLINE="\033[4m"
export BLINK="\033[5m"
export INVERTED="\033[7m"
export HIDDEN="\033[8m"
fi
Since I’ve been experimenting with debian chroot recently, I’ve copied this line from the default debian ~/.bashrc
file:
# Debian CHROOT Support
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
The prompt string! This is a bit complicated. The date section, git section, shell type are all scripts that are enclosed in an escaped $()
block. They are set into the $PS1
as strings and aren’t evaluated when the bash_profile
script runs. The debian chroot block, as well as the host section, are immediately evaluated here.
# Bash Prompt String
export PS1="\[$RESET\]\$(\
$(
# DATE SECTION
# This is run on every new line.
)\
if [[ \"\$PROMPT_DATE\" == \"true\" ]]; then\
echo \"\[$DIM$GRAY\]\D\{\%Y-%m-%d %H:%M:%S} \";\
else\
echo \"\";
fi\
)\
$(
# HOST SECTION
# (hidden if not using ssh or remote)
)\
\[$RESET\]\[$WHITE\]\[$BOLD\]\
${debian_chroot:+($debian_chroot) }\u$(\
if [ -n "$SSH_CLIENT" ] || \
[ -n "$SSH_TTY" ] || \
[ -f /.dockerenv ]; then \
echo "@\h";\
fi
): \
$(
# USER NAME
)\
\[\]\w \
$(
# GIT COMPONENT
# Attempt to get git branch
# Errors piped to stdout so if no branch, no display.
)\
\[$LIGHT_BLUE\]\$(\
if [[ \"\$PROMPT_GIT\" == "true" ]]; then\
if git diff-index --quiet HEAD -- 2> /dev/null; then\
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/('"$GIT_BRANCH_CHAR"' \1) /';\
else \
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/('"$GIT_BRANCH_CHAR"' \1 \*) /';\
fi\
fi\
)\
$(
# SHELL TYPE INDICATOR
# "$" or "#" depending on user/superuser
)\
\[$GREEN\]\$(\
if [[ `whoami` == "root" ]]; then \
echo '#'; \
else echo '$';\
fi\
)\[$RESET\] "
The $PS2
indicators are used for continuing entry on a new line. $PS4
is used when using set -x
inside of a shell script, and is echoed before each command.
export PS2="\[$DIM$GRAY\]> \[$RESET\]"
export PS4="\[$DIM$GRAY\]+ \[$RESET\]"
Next, we enable some color support flags here:
# Enable some colors
if [ "$COLORS_ENABLED" != "false" ]; then
export CLICOLOR=1
export LSCOLORS=hxfxcxdxbxegedabagacad
export GREP_OPTIONS='--color=auto'
# alias ls='ls --color=auto'
fi
$PATH
construction. There are two flavors here. the export_path
function checks if a path exists BEFORE generating the path. others using the traditional method (for example, relative paths) are always added to the search $PATH
.
# Export paths only if they exist.
function export_path {
if [ -d "$1" ]; then
export PATH="$PATH:$1"
fi
}
# Path variables
export PATH="/usr/local/bin"
export_path "/bin"
export_path "/sbin"
export_path "/usr/bin"
export_path "/usr/sbin"
export_path "/Applications/Postgres.app/Contents/Versions/latest/bin"
export_path "$HOME/.local/bin"
export_path "$HOME/.npm-global/bin"
export_path "$HOME/.fastlane/bin"
export_path "$HOME/.cargo/bin"
export_path "$HOME/bin"
export_path "/Applications/Sublime Text.app/Contents/SharedSupport/bin/"
# Since export_path is conditional, we must add directory-dependent paths here:
export PATH="$PATH:./node_modules/.bin"
Since some systems don’t adhere to these paths or requrie installation specific ones, I add them in this separate file, called ~/.bash_path
. This allows me to keep this file portable while installation specific things can be done here:
# Source custom paths.
if [ -f ~/.bash_path ]; then
source ~/.bash_path
fi
Git completion support:
# Add git completion
if [ -f ~/scripts/git-completion.bash ]; then
source ~/scripts/git-completion.bash
fi
Custom shortcuts for various tasks, aliases to make life easier:
# Shortcuts
alias finder='open .'
alias l='ls -a'
alias ll='ls -l'
alias la='ls -la'
alias root='sudo su'
alias serve='python -m SimpleHTTPServer 8888'
alias prettyjson='python -m json.tool'
alias c='code'
alias s='subl'
alias t='tmux new-session -A -s main'
alias pdb='python -m pdb'
alias lowercase='tr "[:upper:]" "[:lower:]"'
alias uppercase='tr "[:lower:]" "[:upper:]"'
Support functions for gpg, etc. of note is the dvm
shortcut that I use frequently alongside docker to allow for quick virtualization of linux systems on my mac:
# Shortcut to make GPG forget cached passwords.
function gpg-forget { echo RELOADAGENT | gpg-connect-agent; }
# Open in projects folder
function p { cd ~/Projects/$@; }
# Create and open a directory
function cf { mkdir $@; cd $@; }
# youtube-mp3
function youtube-mp3 { youtube-dl --extract-audio --audio-format mp3 -o "%(title)s.%(ext)s" $@; }
# Hash functions
function sha1 { openssl sha1 $@; }
function sha256 { shasum -a 256 $@; }
# Start and attach a docker instance.
function dvm { docker start $@ 1>/dev/null; docker attach $@; }
Final configuration:
# Bash History
HISTCONTROL=ignoreboth
# GPG Support
GPG_TTY=$(tty)
export GPG_TTY
That’s it!