# -----------------------------------------------------------------------------
# Stephen Niedzielski
# This file is sourced by .bash_profile at bash launch.
# -----------------------------------------------------------------------------
# Safety Options
# Fail if undefined variables are used.
set -u
# Status of pipeline is last non-zero status of command or rightmost command
# status.
set -o pipefail
# Prohibit redirection overwriting >.
set -C
# -----------------------------------------------------------------------------
# Print
# http://wiki.archlinux.org/index.php/Color_Bash_Prompt
colorless='\e[0m'
red='\e[1;31m'
yellow='\e[1;33m'
green='\e[1;32m'
alias e=echo
print_ng() { echo -e ${red}ng:${colorless} "$@" >&2; }
print_wn() { echo -e ${yellow}wn:${colorless} "$@" >&2; }
print_ok() { echo -e ${green}ok:${colorless} "$@" ; }
# -----------------------------------------------------------------------------
# Version Determination
CYG_1_7_5=0
DAR_10_3_0=0
case "`uname -sr`" in
CYGWIN_NT-*\ 1.7.5\(0.225/5/3\))
CYG_1_7_5=1
;;
'Darwin 10.3.0')
DAR_10_3_0=1
;;
*)
print_ng 'unknown terminal'
;;
esac
# -----------------------------------------------------------------------------
# Common Shell Aliases
alias mv='mv -i'
alias m=mv
alias cp='cp -i'
alias rm='rm -i'
alias r=rm
alias md=mkdir
alias se=set
alias mktmp=mktemp
alias h=history
if [ $CYG_1_7_5 -eq 1 ]
then
alias l='ls -A1p --color=always --group-directories-first' # Alphabetically.
elif [ $DAR_10_3_0 -eq 1 ]
then
alias l='ls -A1pG' # Alphabetically.
fi
alias lex='l -X' # By extension.
alias lsi='l -S' # By size.
alias lct='l -c' # By creation time.
alias lmt='l -t' # By modification time.
alias lat='l -u' # By access time.
if [ $CYG_1_7_5 -eq 1 ]
then
alias tree='cmd tree'
elif [ $DAR_10_3_0 -eq 1 ]
then
true #alias tree='d -T'
fi
# -----------------------------------------------------------------------------
# Pipe
# Generate script for detecting existence of stdin pipe.
[ ! -e ~/scripts/is_pipe.sh ] && \
rm -f ~/scripts/is_pipe.sh && \
echo 'readlink /proc/$$/fd/0|egrep -v ^/dev/console$ > /dev/null' > ~/scripts/is_pipe.sh
alias is_pipe='~/scripts/is_pipe.sh'
alias ip=is_pipe
# -----------------------------------------------------------------------------
# Miscellaneous
# xargs newline delimited.
alias x="xargs -d '\n'"
# Bastard son of find; newline delimited.
alias f='find -O3 . -nowarn -depth -regextype egrep'
a() { [ $1 -gt 0 ]; } # args
na() { [ $1 -eq 0 ]; } # no args
ipoa() { ip || test $1 -gt 0; } # Is pipe or argument(s).
ipana() { ip && [ $1 -eq 0 ]; } # Is pipe and no arguments.
np() { ! ip; }
npana() { np && na $1; } # no pipe and no args
alias timestamp='date +%F-%H-%M-%S'
if [ $CYG_1_7_5 -eq 1 ]
then
alias cls='cmd cls' # Clear screen.
#alias bell='! sndrec32 /play "C:\Windows\Media\ding.wav"' # /close
alias bell='"$PROGRAMFILES"/Windows\ Media\ Player/wmplayer "c:\\Windows\\Media\\ding.wav"'
fi
alias path="echo \$PATH|sed 's_:_\n_g'" # Print each path on a newline.
alias pdftotext='pdftotext -layout'
alias str='strings -a'
alias s='sed -r'
dic() { ! wn "$@" -over; } # Dictionary definition.
alias doxygen='cmd doxygen'
t()
{
if ip
then
d2u|x touch "$@" < /dev/fd/0
else
touch "$@"
fi
}
# Doesn't handle embedded comments like const char * foo = "choo /* choo */".
strip_c_cmt()
{
ipana $# && \
python -c 'import re, sys; sys.stdout.write(re.sub("/\*(.|\r?\n)*?\*/", "", sys.stdin.read(), 0))'
}
exp() { "$WINDIR/explorer" "`cygpath -w "${1:-.}"`"& }
notepad() { "$WINDIR/notepad" ${1:+"`cygpath -w "$1"`"}& }
tag() # Index workspace.
{
npana || return 1
f > f.txt && \
egrep '\.(c|cpp|h|hpp)$' f.txt > fxchpp.txt && \
ctags - < fxchpp.txt
bell
}
beep_off()
{
# TODO: I think this only works in cygwin for backspace and tab bells.
bind 'set bell-style none'
net stop beep
sc config beep start= disabled
}
cb() # Clipboard.
{
na $# || return 1
if ip
then
putclip
else
getclip
fi
}
# These look strange because they're evaluated once by the shell and once by
# sed.
alias esc="s 's_(\\\\| )_\\\\\\1_g'"
alias escex="s 's_[^a-zA-Z0-9]_\\\\\\0_g'"
# -----------------------------------------------------------------------------
# grep
alias g='egrep --color=always'
alias gd='aspell dump master|g -i' # grep dictionary
xg() { d2u|x egrep --color=always "$@"; } # xargs newline delimited grep
alias gp='pls|ntip 2|g -i' # grep process
# -----------------------------------------------------------------------------
# Head / Tail
# One screen worth.
alias ead='head -n $LINES'
alias ail='tail -n $LINES'
alias tip='head -n 1'
ntip() { tail -n +"$@"; } # All from tip offset.
alias base='tail -n 1'
nbase() { head -n +"$@"; } # All to base offset.
# -----------------------------------------------------------------------------
# Filename Manipulation
cy()
{
if ip
then
cygpath "$@" -f -
else
if a $# && [ "${1:0:1}" != '-' -o $# -gt 1 ]
then
cygpath "$@"
else
cygpath "$@" "$PWD"
fi
fi
}
alias cyw='cy -w' # Windows.
alias cyu='cy -u' # UNIX.
alias cym='cy -m' # Mixed.
bn() # Basename.
{
if ipana $#
then
d2u|x -n 1 basename < /dev/fd/0
else
basename "$@"
fi
}
dn() # Dirname.
{
if ipana $#
then
d2u|x -n 1 dirname < /dev/fd/0
else
dirname "$@"
fi
}
# -----------------------------------------------------------------------------
# Processes
alias kill='kill -f'
alias pls='ps -asW'
# Process grep and kill.
pk() { gp --color=none "$@"|s 's_[ \t]+([0-9]+).*_\1_'|x kill -f; }
alias jobs='jobs -l'
# -----------------------------------------------------------------------------
# gVim
if [ $CYG_1_7_5 -eq 1 ]
then
alias gvim="/c/Program\ Files*/Vim/vim72/gvim.exe"
fi
alias vanilla_gvim='gvim -U NONE' # for visitors
v() { gvim -p "$@"& }
# -----------------------------------------------------------------------------
# File Type Detection
# These functions *guess*. Return matching inputs.
is_txt()
{
if ipana $#
then
file -N0 --mime-encoding -f -
else
file -N0 --mime-encoding "$@"|grep -av binary|s 's_\x0 .*__'
fi
}
is_bin()
{
if ipana $#
then
file -N0 --mime-encoding -f -
else
file -N0 --mime-encoding "$@"|grep -a binary|s 's_\x0 binary$__'
fi
}
# -----------------------------------------------------------------------------
# Last.fm
# API documentation available at http://www.last.fm/api.
# $1 Last.fm API method.
# ... Optional method parameters.
fm()
{
local method="$1"
shift
# Append '-d' to specify URL encoding is necessary. There's probably a better
# way to do this.
local params=
local i=0
while [ $# -gt 0 ]
do
params[i]="-d$1"
let i+=1
shift
done
curl \
-d 'api_key=fede83da81dbe5c79f0f056286a0c379' \
-d "method=$method" \
${params:+"${params[@]}"} \
'http://ws.audioscrobbler.com/2.0/'
}
alias fmsn="sed -nr 's_^ (.*)_\1_p'"
# $1 Artist.
# $2 Number of similar artists returned (optional).
fm_sim_art()
{
fm artist.getSimilar "artist=$1" ${2:+"limit=$2"}
}
#cat *|sort|uniq -dc|sort -r
# -----------------------------------------------------------------------------
# cmd
if [ $CYG_1_7_5 -eq 1 ]
then
cmd()
{
# This looks like a bit of a hack, but in general parents propagate their
# environment to their children, whether it's Popen in Python or
# CreateProcess in Win32. I think this is the proper way to do it -- get it
# from the registry. I could use env here, but the prompt seems to expect
# environment variables to be fully expanded.
# Some programs require this, like p4.
local pwd="$(cygpath -w "$PWD")"
# Restore path to system default.
local path="$(cat '/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment/Path')" && \
"$SYSTEMROOT/system32/cmd" /S /E:ON /F:ON /V:ON /C 'set PWD='"$pwd"'& set PATH='"$path"'&' "$@"
}
alias cmd_win='cmd start cmd'
alias cyg_win='cmd_win /c "`cyw /`\\cygwin.bat"'
fi # CYG_1_7_5
# -----------------------------------------------------------------------------
# p4
# Wrapping p4 like this let's let's us pipe to and from the clipboard easily
# at this layer and all higher level wrappers.
p4()
{
if ip
then
cmd p4 -x - "$@"
else
cmd p4 "$@"
fi
}
alias p4win='cmd start p4win' # winners don't use drugs, they use p4win
alias p4w=p4win
alias p4v='cmd start p4v'
# TODO: Some or all of these are busted with the new P4. Try fstat in this
# version but see if can maintain backward compatibility.
# Will not work if # is used within filenames.
alias p4sd="s 's_^(\.\.\. )?(//[^#]+).*_\2_'"
alias p4sv="s 's_^(\.\.\. )?//[^#]+#([0-9]+).*_\2_'"
alias p4sdv="s 's_^(\.\.\. )?(//[^#]+#[0-9]+).*_\2_'"
alias p4sl="s 's_^//[^#]+#[0-9]+ - ([a-z]+ )?(.+)_\2_'"
alias p4scl="s 's_Change ([0-9]+) on [0-9]{4}/[0-9]{2}/[0-9]{2} by .*_\1_'"
# TODO: integrate / fix.
# Requires dominant cs to new location.
p4replace()
{
p4 revert -k "$@" && \
p4 sync -k "$@" && \
p4 edit "$@"
}
# Accepts labels and files from stdin. Prints tip revs for outdated files.
p4tip()
{
ipana $# && p4sd|p4 files|p4sd|p4 sync -n 2>/0
}
# Accepts labels and file revs from stdin. prints changelist delta between have
# and specified.
p4dcl()
{
! ipana $# && return 1
local chgs=`mktmp`
local stdin=`mktmp`
cat >> $stdin
p4 files|s 's_^(\.\.\. )?(//[^#]+).*_\2#head_' < $stdin|p4 changes|sort -u >> $chgs && \
p4sd < $stdin|p4 have|p4sdv|p4 changes >> $chgs && \
sort $chgs|uniq -u
rm -f $chgs $stdin
}
# -----------------------------------------------------------------------------
# Find Files with Extension
# (Newline delimited.)
# $1 opt iregex for file ext
# $2, ... opt args passed to find
fx()
{
local rex=
if [ $# -gt 0 ]
then
rex="($1)"
shift
fi
f -type f -iregex '^.*'"${rex}"'$' ${@:+"$@"}
}
alias fxc="fx '\.c'"
alias fxh="fx '\.h'"
alias fxch="fx '\.c|\.h'"
alias fxcpp="fx '\.c|\.cpp'"
alias fxhpp="fx '\.h|\.hpp'"
alias fxchpp="fx '\.c|\.cpp|\.h|\.hpp'"
# -----------------------------------------------------------------------------
# Jump
# If no arguments specified, pushd.
# Else if $1 specified and is a dir, pushd dir.
# Else treat $1 as an iregex describing a portion of the PWD. If result of
# iregex is a dir, pushd dir, else error.
j()
{
if [ $# -eq 0 ]
then
P
return
fi
if [ -d "$1" ]
then
P "$1"
return
fi
# Ideally use nuls or newlines. e foo|s $'s\1oo\1aa\1' works but
# e foo|s $'s\0oo\0aa\0' does not.
local d="`cym "$PWD"|s -n "s"$'\r'"(.*(^|:|/)$1[^/:]*($|\:|/)).*"$'\r'"\1"$'\r'"ip"`"
if [ $? -eq 0 ] && [ -n "$d" ]
then
P "$d"
return
fi
return 1
}
J() { P ${@:++"$@"}; }
alias dirs='dirs -v'
p() { popd "$@" > /0 && dirs; }
P() { pushd "$@" > /0 && dirs; }
alias b='cd ..'
alias b1='b'
alias b2='b1;b'
alias b3='b2;b'
alias b4='b3;b'
alias b5='b4;b'
alias c=cd
# -----------------------------------------------------------------------------
# Bash History
# Append to history instead of overwriting.
shopt -s histappend
# Save history regardless of number of terminals.
# TODO: confirm this works...
export SAVEHIST=1
export HISTSIZE=10000
# Ignore duplicate lines so we don't have to keep tapping up.
export HISTIGNORE='&'
# Convert multi-line commands to single line in history.
shopt -s cmdhist
# -----------------------------------------------------------------------------
# Miscellaneous
# Specify a Python configuration file.
export PYTHONSTARTUP=~/.pythonrc
# Some programs use this to determine what shell to use.
export SHELL
win_title=Cygwin
# Adjust window size after each command as appropriate.
shopt -s checkwinsize
# Extended globbing. See features at http://www.caliban.org/bash/.
shopt -s extglob
# Return files beginning with . in path-name expansion.
shopt -s dotglob
# Prompt.
# Change to:
# $PWD
# :
# With adjustable title.
# Note: colors here must be between \[\033[ and \]
if [ $CYG_1_7_5 -eq 1 ]
then
PS1='\[\033]0;${win_title}\007\]\n\[\033[\e[0;32m\]`e=$?;cygpath -am "$PWD";if [ $e -eq 0 ];then echo -e \[\033[\e[0m\];else echo -e "\[\033[\e[1;31m\]";fi`: \[\033[\e[0m\]'
elif [ $DAR_10_3_0 -eq 1 ]
then
PS1='\[\033]0;${win_title}\007\]\n\[\033[\e[0;32m\]$PWD\n`if [ $? -eq 0 ];then echo -e \[\033[\e[0m\];else echo -e "\[\033[\e[1;31m\]";fi`: \[\033[\e[0m\]'
fi
# Not quite sure what these do. They seem to change the CL interface a bit.
set editing-mode vi
set -o vi
# -----------------------------------------------------------------------------
# Links
if [ ! -e /0 ]
then
rm -f /0
ln -s /dev/null /0
fi
if [ $CYG_1_7_5 -eq 1 ]
then
if [ ! -e ~/desktop ]
then
# Either symbolic link is broken or non-existent.
# Hose the link if it exists.
rm -f ~/desktop
# Make a new link.
ln -s /cygdrive/c/Documents\ and\ Settings/"`whoami`"/Desktop ~/desktop
fi
if [ ! -e /c ]
then
rm -f /c
ln -s /cygdrive/c /c
fi
if [ ! -e /cb ]
then
rm -f /cb
ln -s /dev/clipboard /cb
fi
elif [ $DAR_10_3_0 -eq 1 ]
then
if [ ! -e /dat ]
then
ln -s /Volumes/DAT/sn /dat
fi
fi
tmp_derar_dir()
{
for i in *.rar *.zip
do
# unrar x -ad -- "$i" . > /0 &&
unrar e -ad -- "$i" > /0 && \
mv "$i" "$i".bk
done
}
# -----------------------------------------------------------------------------
# Notes
# echo|dd bs=110M conv=sync of=110MB.bin - gen big fat file
# objdump, dumpbin
#nodosfilewarning
# is_bin also returns dirs, sym links, & other non-reg files, which normally
# isn't what i want. NOTE: this will return Windows links
#is_binf()
#{
# # newline is delimter
# local IFS=$'\n'
# local rv=''
# for f in `is_bin "$@"`
# #is_bin "$@"|while read -r f
# do
# if [ -f "$f" ]
# then
# # HACK: escape backslashes, then delimit with a newline. under limited
# # testing, this is slightly faster than echoing each match to stdout
# # direct
# rv+="${f//\\/\\\\}\n"
# #echo "$f"
# fi
# done
# if [ -n "$rv" ]
# then
# echo -en "$rv"
# fi
#}
#g '\' # find word foo
# find duplicates - sort|uniq -d
# 2>&1 stderr to stdout
# &> stderr and stdout to file
# net config server /hidden:yes
# paste, join, cut
# reverse list: tac
# cp ../M8660SRFXXXWSA0037_0/{clientspec_updates.cs,core_wiredconnectivity_depends.plf,properties.ini} .
# {1..10} --> 1 2 3 4 5 6 7 8 9 10