Browse Source

Squashed down

master
David Trudgian 4 years ago
commit
fbd136c1ea
  1. 14
      .gitignore
  2. 3
      .gitmodules
  3. 22
      LICENSE-MIT
  4. 8
      README.md
  5. 329
      bin/dotfiles
  6. 91
      bin/eachdir
  7. 182
      bin/git-jump
  8. 280
      bin/gpr
  9. 26
      bin/isip
  10. 43
      bin/manh
  11. 35
      bin/manp
  12. 4
      bin/org_convert
  13. 23
      bin/pid
  14. 310
      bin/rename
  15. 38
      bin/resample-dpi
  16. 26
      bin/ssid
  17. 37
      conf/manh/styles.css
  18. 20
      copy/.gitconfig
  19. 205
      copy/.muttrc
  20. 7
      copy/.ssh/config
  21. 9
      init/10_osx_xcode.sh
  22. 39
      init/20_osx_homebrew.sh
  23. 59
      init/30_osx_homebrew_casks.sh
  24. 41
      init/30_osx_homebrew_recipes.sh
  25. 8
      init/50_vim.sh
  26. 26
      link/.Xresources
  27. 4
      link/.bash_profile
  28. 30
      link/.bashrc
  29. 475
      link/.dircolors
  30. 65
      link/.gitignore_global
  31. 24
      link/.minttyrc
  32. 15
      link/.screenrc
  33. 537
      link/.spacemacs
  34. 2504
      link/.vim/autoload/plug.vim
  35. 2019
      link/.vim/autoload/plug.vim.old
  36. 109
      link/.vim/colors/monokai.vim
  37. 46
      link/.vim/nerdtree_plugin/expanderrific.vim
  38. 75
      link/.vim/plugin/bclose.vim
  39. 233
      link/.vimrc
  40. 36
      manual/Package Control.sublime-settings
  41. 27
      manual/Preferences.sublime-settings
  42. 2
      source/00_dotfiles.sh
  43. 3
      source/10_user_bin.sh
  44. 17
      source/45_linuxbrew.sh
  45. 15
      source/50_anaconda.sh
  46. 4
      source/50_dircolors.sh
  47. 5
      source/50_editor.sh
  48. 42
      source/50_file.sh
  49. 18
      source/50_history.sh
  50. 22
      source/50_misc.sh
  51. 16
      source/50_osx.sh
  52. 2
      source/50_prompt.sh
  53. 15
      source/50_pyenv.sh
  54. 16
      source/50_rbenv.sh
  55. 54
      source/99_biohpc_only.sh
  56. 6
      vendor/rename/README.txt
  57. 310
      vendor/rename/rename

14
.gitignore

@ -0,0 +1,14 @@
# Lots of junk goes in here.
/caches/
/backups/
# Top secret stuff!
/link/.ssh/authorized_keys
/link/.ssh/id_*
/link/.ssh/known_hosts
# Don't commit Vim plugins, vim-plug will install them.
/link/.vim/plugged
# Ignore any file with LOCAL in the name (good for per-machine vars/functions)
*LOCAL*

3
.gitmodules

@ -0,0 +1,3 @@
[submodule "vendor/bash-git-prompt"]
path = vendor/bash-git-prompt
url = https://github.com/magicmonty/bash-git-prompt.git

22
LICENSE-MIT

@ -0,0 +1,22 @@
Copyright (c) 2014 "Cowboy" Ben Alman
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

8
README.md

@ -0,0 +1,8 @@
# Dave's dotfiles
A customized version of https://github.com/cowboy/dotfiles
## Original License
Copyright (c) 2014 "Cowboy" Ben Alman
Licensed under the MIT license.
<http://benalman.com/about/license/>

329
bin/dotfiles

@ -0,0 +1,329 @@
#!/usr/bin/env bash
[[ "$1" == "source" ]] || \
echo 'Dotfiles - "Cowboy" Ben Alman - http://benalman.com/'
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Usage: $(basename "$0")
See the README for documentation.
https://github.com/cowboy/dotfiles
Copyright (c) 2014 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
###########################################
# GENERAL PURPOSE EXPORTED VARS / FUNCTIONS
###########################################
# Where the magic happens.
export DOTFILES=~/.dotfiles
# Logging stuff.
function e_header() { echo -e "\n\033[1m$@\033[0m"; }
function e_success() { echo -e " \033[1;32m✔\033[0m $@"; }
function e_error() { echo -e " \033[1;31m✖\033[0m $@"; }
function e_arrow() { echo -e " \033[1;34m➜\033[0m $@"; }
# For testing.
function assert() {
local success modes equals actual expected
modes=(e_error e_success); equals=("!=" "=="); expected="$1"; shift
actual="$("$@")"
[[ "$actual" == "$expected" ]] && success=1 || success=0
${modes[success]} "\"$actual\" ${equals[success]} \"$expected\""
}
# OS detection
function is_osx() {
[[ "$OSTYPE" =~ ^darwin ]] || return 1
}
function is_ubuntu() {
[[ "$(cat /etc/issue 2> /dev/null)" =~ Ubuntu ]] || return 1
}
function get_os() {
for os in osx ubuntu; do
is_$os; [[ $? == ${1:-0} ]] && echo $os
done
}
# Remove an entry from $PATH
# Based on http://stackoverflow.com/a/2108540/142339
function path_remove() {
local arg path
path=":$PATH:"
for arg in "$@"; do path="${path//:$arg:/:}"; done
path="${path%:}"
path="${path#:}"
echo "$path"
}
# Display a fancy multi-select menu.
# Inspired by http://serverfault.com/a/298312
function prompt_menu() {
local exitcode prompt choices nums i n
exitcode=0
if [[ "$2" ]]; then
_prompt_menu_draws "$1"
read -t $2 -n 1 -sp "To edit this list, press any key within $2 seconds. "
exitcode=$?
echo ""
fi 1>&2
if [[ "$exitcode" == 0 ]]; then
prompt="Toggle options (Separate options with spaces, ENTER when done): "
while _prompt_menu_draws "$1" 1 && read -rp "$prompt" nums && [[ "$nums" ]]; do
_prompt_menu_adds $nums
done
fi 1>&2
_prompt_menu_adds
}
function _prompt_menu_iter() {
local i sel state
local fn=$1; shift
for i in "${!menu_options[@]}"; do
state=0
for sel in "${menu_selects[@]}"; do
[[ "$sel" == "${menu_options[i]}" ]] && state=1 && break
done
$fn $state $i "$@"
done
}
function _prompt_menu_draws() {
e_header "$1"
_prompt_menu_iter _prompt_menu_draw "$2"
}
function _prompt_menu_draw() {
local modes=(error success)
if [[ "$3" ]]; then
e_${modes[$1]} "$(printf "%2d) %s\n" $(($2+1)) "${menu_options[$2]}")"
else
e_${modes[$1]} "${menu_options[$2]}"
fi
}
function _prompt_menu_adds() {
_prompt_menu_result=()
_prompt_menu_iter _prompt_menu_add "$@"
menu_selects=("${_prompt_menu_result[@]}")
}
function _prompt_menu_add() {
local state i n keep match
state=$1; shift
i=$1; shift
for n in "$@"; do
if [[ $n =~ ^[0-9]+$ ]] && (( n-1 == i )); then
match=1; [[ "$state" == 0 ]] && keep=1
fi
done
[[ ! "$match" && "$state" == 1 || "$keep" ]] || return
_prompt_menu_result=("${_prompt_menu_result[@]}" "${menu_options[i]}")
}
# Given strings containing space-delimited words A and B, "setdiff A B" will
# return all words in A that do not exist in B. Arrays in bash are insane
# (and not in a good way).
# From http://stackoverflow.com/a/1617303/142339
function setdiff() {
local debug skip a b
if [[ "$1" == 1 ]]; then debug=1; shift; fi
if [[ "$1" ]]; then
local setdiffA setdiffB setdiffC
setdiffA=($1); setdiffB=($2)
fi
setdiffC=()
for a in "${setdiffA[@]}"; do
skip=
for b in "${setdiffB[@]}"; do
[[ "$a" == "$b" ]] && skip=1 && break
done
[[ "$skip" ]] || setdiffC=("${setdiffC[@]}" "$a")
done
[[ "$debug" ]] && for a in setdiffA setdiffB setdiffC; do
echo "$a ($(eval echo "\${#$a[*]}")) $(eval echo "\${$a[*]}")" 1>&2
done
[[ "$1" ]] && echo "${setdiffC[@]}"
}
# If this file was being sourced, exit now.
[[ "$1" == "source" ]] && return
###########################################
# INTERNAL DOTFILES "INIT" VARS / FUNCTIONS
###########################################
# Initialize.
init_file=$DOTFILES/caches/init/selected
function init_files() {
local i f dirname oses os opt remove
dirname="$(dirname "$1")"
f=("$@")
menu_options=(); menu_selects=()
for i in "${!f[@]}"; do menu_options[i]="$(basename "${f[i]}")"; done
if [[ -e "$init_file" ]]; then
# Read cache file if possible
IFS=$'\n' read -d '' -r -a menu_selects < "$init_file"
else
# Otherwise default to all scripts not specifically for other OSes
oses=($(get_os 1))
for opt in "${menu_options[@]}"; do
remove=
for os in "${oses[@]}"; do
[[ "$opt" =~ (^|[^a-z])$os($|[^a-z]) ]] && remove=1 && break
done
[[ "$remove" ]] || menu_selects=("${menu_selects[@]}" "$opt")
done
fi
prompt_menu "Run the following init scripts?" $prompt_delay
# Write out cache file for future reading.
rm "$init_file" 2>/dev/null
for i in "${!menu_selects[@]}"; do
echo "${menu_selects[i]}" >> "$init_file"
echo "$dirname/${menu_selects[i]}"
done
}
function init_do() {
e_header "Sourcing $(basename "$2")"
source "$2"
}
# Copy files.
function copy_header() { e_header "Copying files into home directory"; }
function copy_test() {
if [[ -e "$2" && ! "$(cmp "$1" "$2" 2> /dev/null)" ]]; then
echo "same file"
elif [[ "$1" -ot "$2" ]]; then
echo "destination file newer"
fi
}
function copy_do() {
e_success "Copying ~/$1."
cp "$2" ~/
}
# Link files.
function link_header() { e_header "Linking files into home directory"; }
function link_test() {
[[ "$1" -ef "$2" ]] && echo "same file"
}
function link_do() {
e_success "Linking ~/$1."
ln -sf ${2#$HOME/} ~/
}
# Copy, link, init, etc.
function do_stuff() {
local base dest skip
local files=($DOTFILES/$1/*)
[[ $(declare -f "$1_files") ]] && files=($($1_files "${files[@]}"))
# No files? abort.
if (( ${#files[@]} == 0 )); then return; fi
# Run _header function only if declared.
[[ $(declare -f "$1_header") ]] && "$1_header"
# Iterate over files.
for file in "${files[@]}"; do
base="$(basename $file)"
dest="$HOME/$base"
# Run _test function only if declared.
if [[ $(declare -f "$1_test") ]]; then
# If _test function returns a string, skip file and print that message.
skip="$("$1_test" "$file" "$dest")"
if [[ "$skip" ]]; then
e_error "Skipping ~/$base, $skip."
continue
fi
# Destination file already exists in ~/. Back it up!
if [[ -e "$dest" ]]; then
e_arrow "Backing up ~/$base."
# Set backup flag, so a nice message can be shown at the end.
backup=1
# Create backup dir if it doesn't already exist.
[[ -e "$backup_dir" ]] || mkdir -p "$backup_dir"
# Backup file / link / whatever.
mv "$dest" "$backup_dir"
fi
fi
# Do stuff.
"$1_do" "$base" "$file"
done
}
# Enough with the functions, let's do stuff.
export prompt_delay=5
# Ensure that we can actually, like, compile anything.
if [[ ! "$(type -P gcc)" ]] && is_osx; then
e_error "XCode or the Command Line Tools for XCode must be installed first."
exit 1
fi
# If Git is not installed, install it (Ubuntu only, since Git comes standard
# with recent XCode or CLT)
if [[ ! "$(type -P git)" ]] && is_ubuntu; then
e_header "Installing Git"
sudo apt-get -qq install git-core
fi
# If Git isn't installed by now, something exploded. We gots to quit!
if [[ ! "$(type -P git)" ]]; then
e_error "Git should be installed. It isn't. Aborting."
exit 1
fi
# Initialize.
if [[ ! -d $DOTFILES ]]; then
# $DOTFILES directory doesn't exist? Clone it!
new_dotfiles_install=1
prompt_delay=15
e_header "Downloading dotfiles"
git clone --recursive git://github.com/${github_user:-cowboy}/dotfiles.git $DOTFILES
cd $DOTFILES
elif [[ "$1" != "restart" ]]; then
# Make sure we have the latest files.
e_header "Updating dotfiles"
cd $DOTFILES
prev_head="$(git rev-parse HEAD)"
git pull
git submodule update --init --recursive --quiet
if [[ "$(git rev-parse HEAD)" != "$prev_head" ]]; then
e_header "Changes detected, restarting script"
exec "$0" "restart"
fi
fi
# Add binaries into the path
[[ -d $DOTFILES/bin ]] && PATH=$DOTFILES/bin:$PATH
export PATH
# Tweak file globbing.
shopt -s dotglob
shopt -s nullglob
# Create caches dir and init subdir, if they don't already exist.
mkdir -p "$DOTFILES/caches/init"
# If backups are needed, this is where they'll go.
backup_dir="$DOTFILES/backups/$(date "+%Y_%m_%d-%H_%M_%S")/"
backup=
# Execute code for each file in these subdirectories.
do_stuff "copy"
do_stuff "link"
do_stuff "init"
# Alert if backups were made.
if [[ "$backup" ]]; then
echo -e "\nBackups were moved to ~/${backup_dir#$HOME/}"
fi
# All done!
e_header "All done!"

91
bin/eachdir

@ -0,0 +1,91 @@
#!/usr/bin/env bash
function _eachdir() {
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
eachdir
http://benalman.com/
Usage: eachdir [dirs --] commands
Run one or more commands in one or more dirs.
By default, all subdirs of the current dir will be iterated over, but if --
is specified as an arg, the dirs list will be made up of all args specified
before it. All remaining args are the command(s) to be executed for each dir.
Multiple commands must be specified as a single string argument.
In bash, aliasing like this allows you to specify aliases/functions:
alias eachdir=". eachdir"
Both of these print the working directory of every subdir of the current dir:
eachdir pwd
eachdir * -- pwd
Perform a "git pull" inside all subdirs starting with repo-:
eachdir repo-* -- git pull
Perform a few git-related commands inside all subdirs starting with repo-:
eachdir repo-* -- 'git fetch && git merge'
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
return; fi
if [ ! "$1" ]; then
echo 'You must specify one or more commands to run.'
return 1
fi
# For underlining headers.
local h1="$(tput smul)"
local h2="$(tput rmul)"
# Store any dirs passed before -- in an array.
local dashes d
local dirs=()
for d in "$@"; do
if [[ "$d" == "--" ]]; then
dashes=1
shift $(( ${#dirs[@]} + 1 ))
break
fi
dirs=("${dirs[@]}" "$d")
done
# If -- wasn't specified, default to all subdirs of the current dir.
[[ "$dashes" ]] || dirs=(*/)
local nops=()
# Do stuff for each specified dir, in each dir. Non-dirs are ignored.
for d in "${dirs[@]}"; do
# Skip non-dirs.
[[ ! -d "$d" ]] && continue
# If the dir isn't /, strip the trailing /.
[[ "$d" != "/" ]] && d="${d%/}"
# Execute the command, grabbing all stdout and stderr.
output="$( (cd "$d"; eval "$@") 2>&1 )"
if [[ "$output" ]]; then
# If the command had output, display a header and that output.
echo -e "${h1}${d}${h2}\n$output\n"
else
# Otherwise push it onto an array for later display.
nops=("${nops[@]}" "$d")
fi
done
# List any dirs that had no output.
if [[ ${#nops[@]} > 0 ]]; then
echo "${h1}no output from${h2}"
for d in "${nops[@]}"; do echo "$d"; done
fi
}
# By putting the above code inside a function, if this file is sourced (which
# is required for external aliases/functions to be used as commands), vars
# can be local and return can be used to exit.
_eachdir "$@"

182
bin/git-jump

@ -0,0 +1,182 @@
#!/usr/bin/env bash
function help() {
cat <<HELP
Git Jump (Forward & Back)
http://benalman.com/
Usage: $(basename "$0") [command]
Commands:
next Jump forward to the next commit in this branch
prev Jump backward to the next commit in this branch
clean Remove current unstaged changes/untracked files**
cleanall Remove all saved tags, unstaged changes and untracked files**
** This action is destructive and cannot be undone!
Git config:
git-jump.branch Branch to jump through. If not set, defaults to master
Description:
"Replay" Git commits by moving forward / backward through a branch's
history. Before jumping, any current unstaged changes and untracked
files are saved in a tag for later retrieval, which is restored when
jumped back to.
Copyright (c) 2014 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
}
function usage() {
echo "Usage: $(basename "$0") [next | prev | clean | cleanall]"
}
# Get branch stored in Git config or default to master
git_branch="$(git config git-jump.branch || echo "master")"
# Get some (short) SHAs
function git_branch_sha() {
git rev-parse --short "$git_branch"
}
function git_head_sha() {
git rev-parse --short HEAD
}
function git_prev_sha() {
git log --format='%h' "$git_branch" "$@" | awk "/^$(git_head_sha)/{getline; print}"
}
function git_next_sha() {
git_prev_sha --reverse
}
# Get absolute path to root of Git repo
function git_repo_toplevel() {
git rev-parse --show-toplevel
}
# Get subject of specified commit
function git_commit_subject() {
git log --format='%s' -n 1 $1
}
# Save changes for later retrieval
function save() {
local status=""
local head_sha=$(git_head_sha)
# Checkout current HEAD by SHA to force detached state
git checkout -q $head_sha
# Add all files in repo
git add "$(git_repo_toplevel)"
# Commit changes (if there were any)
git commit --no-verify -m "Git Jump: saved changes for $head_sha" >/dev/null
# If the commit was successful, tag it (overwriting any previous tag)
if [[ $? == 0 ]]; then
status="*"
git tag -f "git-jump-$head_sha" >/dev/null
fi
echo "Previous HEAD was $head_sha$status, $(git_commit_subject $head_sha)"
}
# Restore previously-saved changes
function restore() {
local status=""
# Save current changes before restoring
save
# Attempt to restore saved changes for specified commit
git checkout "git-jump-$1" 2>/dev/null
if [[ $? == 0 ]]; then
# If the restore was successful, figure out exactly what was saved, check
# out the original commit, then restore the saved changes on top of it
status="*"
local patch="$(git format-patch HEAD^ --stdout)"
git checkout HEAD^ 2>/dev/null
echo "$patch" | git apply -
else
# Otherwise, just restore the original commit
git checkout "$1" 2>/dev/null
fi
echo "HEAD is now $1$status, $(git_commit_subject $1)"
}
# Clean (permanently) current changes and remove the current saved tag
function clean() {
local head_sha=$(git_head_sha)
git tag -d "git-jump-$head_sha" &>/dev/null
if [[ $? == 0 ]]; then
echo "Removed stored data for commit $head_sha."
fi
local repo_root="$(git_repo_toplevel)"
git reset HEAD "$repo_root" >/dev/null
git clean -f -d -q -- "$repo_root" >/dev/null
git checkout -- "$repo_root" >/dev/null
echo "Unstaged changes and untracked files removed."
}
# Remove (permanently) all saved tags
function clean_all_tags() {
git for-each-ref refs/tags --format='%(refname:short)' | \
while read tag; do
if [[ "$tag" =~ ^git-jump- ]]; then
git tag -d "$tag"
fi
done
}
# Jump to next commit
function next() {
local next_sha=$(git_next_sha)
if [[ "$next_sha" == "$(git_head_sha)" ]]; then
# Abort if no more commits
echo "Already at last commit in $git_branch. Congratulations!"
else
# Checkout branch by name if at its HEAD
if [[ "$next_sha" == "$(git_branch_sha)" ]]; then
next_sha="$git_branch"
fi
echo "Jumping ahead to next commit."
restore $next_sha
fi
}
# Jump to previous commit
function prev() {
local prev_sha=$(git_prev_sha)
if [[ "$prev_sha" == "$(git_head_sha)" ]]; then
# Abort if no more commits
echo "Already at first commit in $git_branch."
else
echo "Jumping back to previous commit."
restore $prev_sha
fi
}
# Show help if requested
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
help
exit
fi
# Check if branch is valid
git rev-parse "$git_branch" &>/dev/null
if [[ $? != 0 ]]; then
echo "Error: Branch \"$git_branch\" does not appear to be valid."
echo "Try $(basename "$0") --help for more information."
exit 1
fi
# Handle CLI arguments
if [[ "$1" == "next" ]]; then
next
elif [[ "$1" == "prev" ]]; then
prev
elif [[ "$1" == "clean" ]]; then
clean
elif [[ "$1" == "cleanall" ]]; then
clean_all_tags
clean
else
usage
exit 1
fi

280
bin/gpr

@ -0,0 +1,280 @@
#!/usr/bin/env bash
function help() {
pr=123
local_ref=foo
script="$(basename "$0") $pr"
cat <<HELP
-=[ GitHub Pull Request Helper - "Cowboy" Ben Alman - http://benalman.com/ ]=-
Usage: $(basename "$0") pull_request_id [ step ]
-=[ Description ]============================================================-
The "step" argument can be used to force execution of a particular step,
but by default this script will automatically choose the next step, from
STEP 1 to STEP 2 and finally to STEP 3. You'll have to execute STEP 4
manually, once everything is done.
-=[ Detailed workflow example ]==============================================-
For this example, assume PR $pr has been filed against the "$local_ref" branch.
-=[ STEP 1 ]=-
You run "$script" and this executes:
$(help_step1)
-=[ STEP 2 ]=-
You run "$script" and this executes:
$(help_step2)
-=[ STEP 3 ]=-
You run "$script" and this executes:
$(help_step3)
-=[ STEP 4 ]=-
You run "$script 4" (explicitly specifying the 4) and this executes:
$(help_step4)
-=[ Very important notes ]===================================================-
Before running this script, ensure that your local "$local_ref" branch is
up-to-date!
At the beginning of STEP 1, any existing "pr$pr" and "pr$pr-squash"
branches will be deleted.
At the beginning of STEP 2, any existing pr$pr-squash" branch will be
deleted.
If you want to hide per-step explanations, set ENV var GPR_SHH=1. For
example, create an alias like: alias gpr='GPR_SHH=1 gpr'
-=[ License ]================================================================-
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
[[ "$1" ]]; exit
}
function help_step1() {
echo " Fetch and rebase PR $pr into \"pr$pr\" branch"
[[ "$1" ]] && return
cat <<HELP
1. Fetch the repo and branch associated with PR $pr.
2. Checkout a new "pr$pr" branch at the HEAD of the fetched branch.
3. Rebase "$local_ref" branch onto "pr$pr" branch.
4. Display a list of files changed in the PR.
Note that you may need to resolve conflicts. If the rebase is successful,
test the PR and commit fixes. Commit as many times as necessary; It doesn't
matter because all PR-related commits will be squash merged in STEP 2.
HELP
}
function help_step2() {
echo " Perform squash merge into \"pr$pr-squash\" branch"
[[ "$1" ]] && return
cat <<HELP
1. Checkout a new "pr$pr-squash" branch from "$local_ref" branch.
2. Squash merge "pr$pr" branch into "pr$pr-squash" branch. (no commit)
3. Append "Closes gh-$pr." to SQUASH_MSG.
4. Commit using the PR branch's HEAD author name.
Since all the commits in the PR have been squashed into one commit, you will
need to edit the commit message. When done, inspect the commit log, ensuring
everything is perfect; you should see a single, beautiful commit.
HELP
}
function help_step3() {
echo " Perform final merge into \"$local_ref\" branch"
[[ "$1" ]] && return
cat <<HELP
1. Checkout "$local_ref" branch.
2. Merge "$pr-squash" branch into "$local_ref" branch.
If STEP 2 was successful, there should be no conflicts here. If there are,
you're doing it wrong. Just double-check the commit log and push when done.
HELP
}
function help_step4() {
echo " Cleanup temporary branches and tags"
[[ "$1" ]] && return
cat <<HELP
1. Temporary "pr$pr" and "pr$pr-squash" branches are deleted.
2. Temporary "_pr${pr}_author_head" tag is deleted.
HELP
}
function header() {
if [[ "$GPR_SHH" ]]; then
echo "-=[ STEP $1 ]=================================================================-"
else
echo "-=[ STEP $1 Overview ]========================================================-"
help_step$1
echo
echo "-=[ Actual ]=================================================================-"
fi
}
[[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]] && help $1
# Generate and store an OAUTH token.
if [[ "$1" == "auth" ]]; then
read -p 'Enter GitHub username: '
json="$(curl -fsSL --data '{"note":"gpr","scopes":["repo"]}' https://api.github.com/authorizations -u "$REPLY")"
if [[ "$json" ]]; then
token="$(node -pe "($json).token")"
git config --global --remove-section gpr 2>/dev/null
git config --global --add gpr.token $token
echo "Authorization successful, token saved."
exit
else
echo "Error authorizing with GitHub, please try again."
exit 5
fi
fi
pr="$1"; shift
script="$(basename "$0") $pr"
branch="pr$pr"
repo="$(git remote show -n origin | perl -ne '/Fetch URL: .*github\.com[:\/](.*\/.*)\.git/ && print $1')"
# Let's fetch some JSON.
token="$(git config --get gpr.token)"
json="$(curl -fsSL "https://api.github.com/repos/$repo/pulls/$pr?access_token=$token" 2>/dev/null)"
if [[ $? != 0 || ! "$json" ]]; then
echo "Error fetching GitHub API data for $repo PR $pr!"
echo "If you're trying to access a private repo and haven't yet done so, please run"
echo "the \"$(basename "$0") auth\" command to generate a GitHub auth token."
exit 2
fi
# Let's parse some JSON.
remote_url="$(node -pe "($json).head.repo.git_url")"
remote_ref="$(node -pe "($json).head.ref")"
local_url="$(node -pe "($json).base.repo.git_url")"
local_ref="$(node -pe "($json).base.ref")"
num_commits="$(node -pe "($json).commits")"
# Let's get the project's .git folder.
git_dir="$(git rev-parse --show-toplevel)/.git"
function del_branch() {
if [[ "$(git branch | grep " $1\$")" ]]; then
git checkout "$local_ref" 2>/dev/null
git branch -D "$1" 2>/dev/null
fi
}
# Use the specified step, otherwise attempt to auto-detect it.
if [[ "$1" ]]; then
step=$1
elif [[ "$(git branch | grep " $branch-squash\$")" ]]; then
# STEP 3 should never auto-execute twice.
if [[ "$(git branch --contains "$(git rev-parse $branch-squash)" | grep " $local_ref\$")" ]]; then
echo "Error merging branch \"$branch-squash\" into \"$local_ref\" branch! (already done)"
echo
echo "Redo the last step with: $script 3"
exit 4
fi
step=3
elif [[ "$(git branch | grep " $branch\$")" ]]; then
step=2
else
step=1
fi
# Let's do some stuff.
if [[ $step == 1 ]]; then
header 1
# Clean up any prior work on this PR.
del_branch "$branch"
del_branch "$branch-squash"
# Fetch remote, create a branch, etc.
if [[ "$remote_url" == "$local_url" ]]; then
git fetch origin "$remote_ref"
else
git fetch "$remote_url" "$remote_ref"
fi
git checkout -b "$branch" FETCH_HEAD
# Save ref to last PR author commit for later use
git tag --force "_${branch}_author_head" FETCH_HEAD
# Rebase!
git rebase "$local_ref"
if [[ $? != 0 ]]; then
echo "Error while attempting rebase!"
exit 3
fi
echo
echo "Changed files in HEAD~$num_commits:"
git --no-pager diff --name-only HEAD~"$num_commits"
echo
echo "-=[ Next Steps ]=============================================================-"
echo "$(help_step2 1) with: $script"
echo " Or redo the current step with: $script 1"
elif [[ $step == 2 ]]; then
header 2
# Clean up any prior squashes for this PR.
del_branch "$branch-squash"
# Create branch and squash merge all commits.
git checkout -b "$branch-squash" "$local_ref"
git merge --squash "$branch"
# Append useful information to commit message.
squash_msg_file="$git_dir/SQUASH_MSG"
echo -e "\nCloses gh-$pr." >> "$squash_msg_file"
# Retrieve author name and email from stored commit, and commit.
author="$(git log "_${branch}_author_head" -n1 --format="%an <%ae>")"
git commit --author="$author"
echo
echo "-=[ Next Steps ]=============================================================-"
echo "$(help_step3 1) with: $script"
echo " Or redo the current step with: $script 2"
elif [[ $step == 3 ]]; then
header 3
# Actually merge squashed commits into branch.
git checkout "$local_ref"
git merge "$branch-squash"
echo
echo "-=[ Next Steps ]=============================================================-"
echo "$(help_step4 1) with: $script 4"
echo " Or redo the current step with: $script 3"
elif [[ $step == 4 ]]; then
header 4
del_branch "$branch"
del_branch "$branch-squash"
git tag -d "_${branch}_author_head" 2>/dev/null
echo
echo "All done."
fi

26
bin/isip

@ -0,0 +1,26 @@
#!/usr/bin/env bash
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Get all bound IPs
http://benalman.com/
Usage: $(basename "$0") [IP]
If an IP is specified and it is bound to a network interface, echo it,
otherwise echo nothing.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
iplist=$(ifconfig -a | perl -nle'/inet (?:addr:)?(\d+\.\d+\.\d+\.\d+)/ && print $1')
if [ "$1" ]; then
if [ "$(echo $iplist | grep -w $1)" ]; then
echo $1
fi
else
echo $iplist
fi

43
bin/manh

@ -0,0 +1,43 @@
#!/usr/bin/env bash
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Manpage-as-HTML Viewer
http://benalman.com/
Usage: $(basename "$0") [section] name
View a manpage as HTML in the default viewer. Because sometimes
you don't want to view manpages in the terminal.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
if [ ! "$1" ]; then
echo 'What manual page do you want?!'
exit
fi
cache_dir=$DOTFILES/caches/manh
# Figure out what the filename should be.
file="$cache_dir/${2:+$2.}$1.html"
# Create directory if it doesn't exist.
[[ -e "$cache_dir" ]] || mkdir -p "$cache_dir"
# Create HTML if it doesn't exist.
[[ ! -e "$file" ]] && man "$@" >/dev/null && cat > "$file" <<EOF
<!doctype html>
<html>
<link rel="stylesheet" href="../../conf/manh/styles.css">
<body>
$(man "$@" 2>/dev/null | man2html -bare -nodepage)
</body>
</html>
EOF
# Open HTML (if it does exist).
[[ -e "$file" ]] && open "$file"

35
bin/manp

@ -0,0 +1,35 @@
#!/usr/bin/env bash
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Manpage-as-PDF Viewer
http://benalman.com/
Usage: $(basename "$0") [section] name
View a manpage as PDF in the default viewer (Preview.app). Because sometimes
you don't want to view manpages in the terminal.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
if [ ! "$1" ]; then
echo 'What manual page do you want?!'
exit
fi
cache_dir=$DOTFILES/caches/manpdf
# Figure out what the filename should be.
file="$cache_dir/${2:+$2.}$1.pdf"
# Create directory if it doesn't exist.
[[ -e "$cache_dir" ]] || mkdir -p "$cache_dir"
# Create PDF if it doesn't exist.
[[ -e "$file" ]] || man -t "$@" | pstopdf -i -o "$file" >/dev/null 2>&1
# Open PDF (if it does exist).
[[ -e "$file" ]] && open "$file"

4
bin/org_convert

@ -0,0 +1,4 @@
#!/bin/sh
# Export all .org to GFM and dokuwiki via pandoc
find ~/Org/ -iname "*.org" -type f -exec sh -c 'pandoc "${0}" -t "markdown_github" --atx-headers -o "${0%.org}.md"' {} \;
find ~/Org/ -iname "*.org" -type f -exec sh -c 'pandoc "${0}" -t "dokuwiki" -o "${0%.org}.dokuwiki"' {} \;

23
bin/pid

@ -0,0 +1,23 @@
#!/usr/bin/env bash
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Get PIDs
http://benalman.com/
Usage: $(basename "$0") [processname [processname ...]]
Get the PIDs of all matching processes for all specified processnames.
If no arguments are passed, list processes by PID, TTY, USER, COMMAND.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
if [ ! "$1" ]; then
ps axo pid,tty,user,command
else
args="$1"; shift; for arg in "$@"; do args="${args}|${arg}"; done
echo $(ps axo pid,tty,user,command | perl -nle"m#^\s*(\d+).*(?:$args)# && !m#.dotfiles/bin/pid# && print \$1")
fi

310
bin/rename

@ -0,0 +1,310 @@
#!/usr/bin/perl
use strict;
use warnings;
=head1 NAME
rename - renames multiple files
=head1 SYNOPSIS
F<rename>
S<B<-h>>
F<rename>
S<B<--man>>
F<rename>
S<B<[ -0 ]>>
S<B<[ -c ]>>
S<B<[ -C ]>>
S<B<[ -e code ]>>
S<B<[ -f ]>>
S<B<[ -i ]>>
S<B<[ -l | -L ]>>
S<B<[ -n ]>>
S<B<[ -s from to ]>>
S<B<[ -v ]>>
S<B<[ files ]>>
=head1 DESCRIPTION
C<rename> renames the filenames supplied according to the rules specified. If a given filename is not modified, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input.
For example, to rename all files matching C<*.bak> to strip the extension, you might say
rename 's/\.bak$//' *.bak
If are confident that none of the filenames has C<.bak> anywhere else than at the end, you can also use the much easier typed
rename -s .bak '' *.bak
You can always do multiple changes in one ago:
rename -s .tgz .tar.gz -s .tbz2 .tar.bz2 *.tar.*
Note however that expressive options are order sensitive. The following would probably surprise you:
rename -s foo bar -s bar baz *
Since operations are cumulative, this would end up substituting (some of) the F<foo> matches in filenames with F<baz>! So pay attention to order. You may want to request a verbose dry run with C<-nv> for the first stab at a complex rename operation.
rename -nv -s bar baz -s foo bar *
You can combine the various expressive options to suit your needs. F.ex files from Microsoft(tm) Windows systems often have blanks and (sometimes nothing but) capital letters in their names. Let's say you have a bunch of such files to clean up, and you also want to move them to subdirectories based on extension. The following command should help, provided all directories already exist:
rename -cz -e '$_ = "$1/$_" if /(\..*)\z/' *
Again you need to pay attention to order sensitivity for expressive options. If you placed the C<-c> after the C<-e> in the above example, files with F<.zip> and F<.ZIP> extensions would be (attempted to be) moved to different directories because the directory name prefix would be added before the filenames were normalized. Once again, use verbose dry run requested using C<-nv> to get an idea of what exactly a complex rename operation is going to do.
=head1 ARGUMENTS
=over 4
=item B<-h>, B<--help>
See a synopsis.
=item B<--man>
Browse the manpage.
=back
=head1 OPTIONS
=over 4
=item B<-0>, B<--null>
When reading file names from C<STDIN>, split on NUL bytes instead of newlines. This is useful in combination with GNU find's C<-print0> option, GNU grep's C<-Z> option, and GNU sort's C<-z> option, to name just a few. B<Only valid if no filenames have been given on the commandline.>
=item B<-c>, B<--lower-case>
Converts file names to all lower case.
=item B<-C>, B<--upper-case>
Converts file names to all upper case.
=item B<-e>, B<--expr>
The C<code> argument to this option should be a Perl expression that assumes the filename in the C<$_> variable and modifies it for the filenames to be renamed. When no other C<-c>, C<-C>, C<-e>, C<-s>, or C<-z> options are given, you can omit the C<-e> from infront of the code.
=item B<-g>, B<--glob>
Glob filename arguments. This is useful if you're using a braindead shell such as F<cmd.exe> which won't expand wildcards on behalf of the user.
=item B<-f>, B<--force>
Rename even when a file with the destination name already exists.
=item B<-i>, B<--interactive>
Ask the user to confirm every action before it is taken.
=item B<-k>, B<--backwards>, B<--reverse-order>
Process the list of files in reverse order, last file first. This prevents conflicts when renaming files to names which are currently taken but would be freed later during the process of renaming.
=item B<-l>, B<--symlink>
Create symlinks from the new names to the existing ones, instead of renaming the files. B<Cannot be used in conjunction with C<-L>.>
=item B<-L>, B<--hardlink>
Create hard links from the new names to the existing ones, instead of renaming the files. B<Cannot be used in conjunction with C<-l>.>
=item B<-n>, B<--dry-run>, B<--just-print>
Show how the files would be renamed, but don't actually do anything.
=item B<-s>, B<--subst>, B<--simple>
Perform a simple textual substitution of C<from> to C<to>. The C<from> and C<to> parameters must immediately follow the argument.
Quoting issues aside, this is equivalent to supplying a C<-e 's/\Qfrom/to/'>.
=item B<-v>, B<--verbose>
Print additional information about the operations (not) executed.
=item B<-z>, B<--sanitize>
Replaces consecutive blanks, shell meta characters, and control characters in filenames with underscores.
=back
=head1 SEE ALSO
mv(1), perl(1), find(1), grep(1), sort(1)
=head1 BUGS
None currently known.
=head1 AUTHORS
Aristotle Pagaltzis
Idea, inspiration and original code from Larry Wall and Robin Barker.
=head1 COPYRIGHT
This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
=cut
use Pod::Usage;
use Getopt::Long 2.24, qw(:config bundling no_ignore_case no_auto_abbrev);
use constant ERROR => do { bless \(my $l = 0), 'LOGLEVEL' };
use constant INFO => do { bless \(my $l = 1), 'LOGLEVEL' };
use constant DEBUG => do { bless \(my $l = 2), 'LOGLEVEL' };
use constant VERB_FOR => {
link => {
inf => 'link',
pastp => 'linked',
exec => sub { link shift, shift or die },
},
symlink => {
inf => 'symlink',
pastp => 'symlinked',
exec => sub { symlink shift, shift or die },
},
rename => {
inf => 'rename',
pastp => 'renamed',
exec => sub { rename shift, shift or die },
},
};
sub argv_to_subst_expr {
my $modifier = shift || '';
pod2usage( -verbose => 1 ) if @ARGV < 2;
my ($from, $to) = map quotemeta, splice @ARGV, 0, 2;
# the ugly \${\""} construct is necessary because unknown backslash escapes are
# not treated the same in pattern- vs doublequote-quoting context; only the
# latter lets us do the right thing with problematic input like
# ']{ool(haracter$' or maybe '>><//((/>'
sprintf 's/\Q${\"%s"}/%s/%s', $from, $to, $modifier;
}
my @EXPR;
GetOptions(
'h|help' => sub { pod2usage( -verbose => 1 ) },
'man' => sub { pod2usage( -verbose => 2 ) },
'0|null' => \my $opt_null,
'c|lower-case' => sub { push @EXPR, 's/([[:upper:]]+)/\L$1/g' },
'C|upper-case' => sub { push @EXPR, 's/([[:lower:]]+)/\U$1/g' },
'e|expr=s' => \@EXPR,
'f|force' => \my $opt_force,
'g|glob' => \my $opt_glob,
'i|interactive' => \my $opt_interactive,
'k|backwards|reverse-order' => \my $opt_backwards,
'l|symlink' => \my $opt_symlink,
'L|hardlink' => \my $opt_hardlink,
'n|just-print|dry-run' => \my $opt_dryrun,
'p|mkpath|make-dirs' => \my $opt_mkpath,
'v|verbose+' => \(my $opt_verbose = 0),
'z|sanitize' => sub { push @EXPR, 's/[!"\$&()=?`*\';<>|_[:cntrl:][:blank:]]+/_/g' },
's|subst|simple' => sub { push @EXPR, argv_to_subst_expr },
'S|subst-global' => sub { push @EXPR, argv_to_subst_expr('g') },
) or pod2usage( -verbose => 1 );
die "TODO" if $opt_mkpath;
if(not @EXPR) {
pod2usage( -verbose => 1 ) if not @ARGV or -e $ARGV[0];
push @EXPR, shift;
}
pod2usage( -verbose => 1 )
if ($opt_hardlink and $opt_symlink)
or ($opt_null and @ARGV);
++$opt_verbose if $opt_dryrun;
BEGIN {
*CORE::GLOBAL::warn = sub {
if(ref $_[0] eq 'LOGLEVEL') {
my $msglevel = ${(shift)};
print "@_\n" if $opt_verbose >= $msglevel;
return;
}
warn @_;
};
}
my $code = do {
my $cat = "sub { ".join('; ', @EXPR)." }";
warn DEBUG, "Using expression: $cat";
my $evaled = eval $cat;
die $@ if $@;
die "Evaluation to subref failed. Check expression using -vn\n"
unless 'CODE' eq ref $evaled;
$evaled;
};
my $verb = VERB_FOR->{
$opt_hardlink ? 'link' :
$opt_symlink ? 'symlink' :
do { 'rename' }
};
if (!@ARGV) {
warn INFO, "Reading filenames from STDIN";
@ARGV = do {
if($opt_null) {
warn INFO, "Splitting on NUL bytes";
local $/ = "\0";
}
<STDIN>;
};
chomp @ARGV;
}
@ARGV = map glob, @ARGV if $opt_glob;
@ARGV = reverse @ARGV if $opt_backwards;
for (@ARGV) {
my $old = $_;
$code->();
if($old eq $_) {
warn DEBUG, "'$old' unchanged";
next;
}
if(!$opt_force and -e) {
warn ERROR, "'$old' not $verb->{pastp}: '$_' already exists";
next;
}
if($opt_dryrun) {
warn INFO, "'$old' would be $verb->{pastp} to '$_'";
next;
}
if($opt_interactive) {
print "\u$verb->{inf} '$old' to '$_'? [n] ";
if(<STDIN> !~ /^y(?:es)?$/i) {
warn DEBUG, "Skipping '$old'.";
next;
}
}
eval { $verb->{exec}($old, $_) };
if($@) {
warn ERROR, "Can't $verb->{inf} '$old' to '$_': $!";
next;
}
warn INFO, "'$old' $verb->{pastp} to '$_'";
}

38
bin/resample-dpi

@ -0,0 +1,38 @@
#!/usr/bin/env bash
if [[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Resample specified images to 72 DPI
http://benalman.com/
Usage: $(basename "$0") [img [img ...]]
The new MacBook Pro retina display is amazing, but screengrabs taken on
one using the screencapture utility aren't scaled to 72 DPI by default.
This script scales those images to 72 DPI, making them viewable at a sane
resolution in web browsers.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
[[ "$1" ]]; exit; fi
while [[ "$1" ]]; do
file="$1"; shift
dpiWidth=$(sips "$file" -g dpiWidth | awk '/:/ {print $2}')
dpiHeight=$(sips "$file" -g dpiHeight | awk '/:/ {print $2}')
pixelWidth=$(sips "$file" -g pixelWidth | awk '/:/ {print $2}')
pixelHeight=$(sips "$file" -g pixelHeight | awk '/:/ {print $2}')
if [[ "$(echo "$dpiWidth - 72" | bc)" == "0" || "$(echo "$dpiHeight - 72" | bc)" == "0" ]]; then
echo "File $(basename "$file") already ${pixelWidth}x${pixelHeight} pixels @ 72 DPI."
continue
fi
w=$(echo "$pixelWidth * 72 / $dpiWidth" | bc)
h=$(echo "$pixelHeight * 72 / $dpiHeight" | bc)
echo "Resampling $(basename "$file") to ${w}x${h} pixels @ 72 DPI."
sips "$file" -s dpiWidth 72 -s dpiHeight 72 -z $h $w >/dev/null 2>&1
done

26
bin/ssid

@ -0,0 +1,26 @@
#!/usr/bin/env bash
if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <<HELP
Get WiFi SSID
http://benalman.com/
Usage: $(basename "$0")
If an SSID is specified and it is the current WiFi network's SSID, echo it,
otherwise echo nothing.
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
http://benalman.com/about/license/
HELP
exit; fi
ssid=$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep " SSID" | sed "s/.*: //")
if [ "$1" ]; then
if [ "$(echo $ssid | grep -w $1)" ]; then
echo $1
fi
else
echo $ssid
fi

37
conf/manh/styles.css

@ -0,0 +1,37 @@
/* Colors from http://ethanschoonover.com/solarized */
/* Fonts from http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/design/index-en.html */
body {
color: #839496;
background: #002b36;
padding: 0;
margin: 0 0 3em 1.5em;
}
h2 {
color: #2aa198;
}
b {
color: #93a1a1;
}
i {
font-style: normal;
text-decoration: underline;
color: #b58900;
}
h2,
pre {
font-family: mplus-2m-regular, Monaco, monospace;
}
pre {
margin: -0.5em 0 -1.5em;
}
body > hr,
body > address {
display: none;
}

20
copy/.gitconfig

@ -0,0 +1,20 @@
[user]
name = David Trudgian
email = EMAIL
[core]
excludesfile = ~/.gitignore_global
[color]
ui = auto
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan

205
copy/.muttrc

@ -0,0 +1,205 @@
# Server Options
# --------------
set spoolfile="~/Maildir/INBOX"
set folder="~/Maildir"
set smtp_url=""
set from=""
set realname=""
# Paths
# -----
#set header_cache=~/.mutt/cache/headers
set message_cachedir=~/.mutt/cache/bodies
# Mailboxes
# ---------
set record="=Sent Items"
set postponed="=Drafts"
set trash="=Trash"
mailboxes =INBOX =INBOX.Tickets =INBOX.Lists
# Signatures
# ----------
set sig_dashes
set signature="~/.signature"
# EMACS
# -----
set editor = emacsclient
# Status Bar
# ----------
set status_chars=" *%A"
set status_format="───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
# Message Index
# -------------
set sort='threads'
set sort_aux = reverse-last-date-received
set uncollapse_jump
set date_format="%e %b %Y %H:%M"
set index_format="%3C|%Z|%d| %-20.20F (%-4.4c) %s"
# Message Viewing
# ---------------
set pipe_decode
set thorough_search
auto_view text/html
alternative_order text/plain text/enriched text/html
ignore *
unignore from: to: cc: date: subject:
unhdr_order *
hdr_order from: to: cc: date: subject:
# Composing
# ---------
set edit_headers
set fast_reply
set askcc
set fcc_attach
unset mime_forward
set forward_format="Fwd: %s"
set forward_decode
set attribution="On %d, %n wrote:"
set reply_to
set reverse_name
set include
set forward_quote
set pager_index_lines=10
set pager_context=3
set pager_stop
set menu_scroll
set tilde
unset markers
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
macro pager \Cu "|urlview<enter>" "call urlview to open links"
# Don't ask for everything
# ------------------------
set delete
unset confirmappend
set quit
# Sidebar Patch
# -------------
set sidebar_visible = yes
set sidebar_width = 20
bind index,pager CP sidebar-next
bind index,pager CN sidebar-prev
bind index,pager CO sidebar-open
set sidebar_short_path = yes
set sidebar_delim_chars = '/.'
set sidebar_folder_indent = yes
set sidebar_indent_string = ' '
set sidebar_divider_char = '|'
set mail_check_stats
set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S'
# Notifications for new mail
set new_mail_command="notify-send 'New Email in %f' '%n new messages, %u unread.' &"
# Compose a new email (not a reply) to the sender
bind index,pager @ compose-to-sender
# for background in 16 color terminal, valid background colors include:
# base03, bg, black, any of the non brights
# basic colors ---------------------------------------------------------
color normal brightyellow default
color error red default
color tilde black default
color message cyan default
color markers red white
color attachment white default
color search brightmagenta default
#color status J_black J_status
color status brightyellow black
color indicator brightblack yellow
color tree yellow default # arrow in threads
# basic monocolor screen
mono bold bold
mono underline underline
mono indicator reverse
mono error bold
# index ----------------------------------------------------------------
color index red default "~A" # all messages
color index brightred default "~E" # expired messages
color index blue default "~N" # new messages
color index blue default "~O" # old messages
color index brightmagenta default "~Q" # messages that have been replied to
color index brightgreen default "~R" # read messages
color index blue default "~U" # unread messages
color index blue default "~U~$" # unread, unreferenced messages
color index brightyellow default "~v" # messages part of a collapsed thread
color index brightyellow default "~P" # messages from me
color index cyan default "~p!~F" # messages to me
color index cyan default "~N~p!~F" # new messages to me
color index cyan default "~U~p!~F" # unread messages to me
color index brightgreen default "~R~p!~F" # messages to me
color index red default "~F" # flagged messages
color index red default "~F~p" # flagged messages to me
color index red default "~N~F" # new flagged messages
color index red default "~N~F~p" # new flagged messages to me
color index red default "~U~F~p" # new flagged messages to me
color index black red "~D" # deleted messages
color index brightcyan default "~v~(!~N)" # collapsed thread with no unread
color index yellow default "~v~(~N)" # collapsed thread with some unread
color index green default "~N~v~(~N)" # collapsed thread with unread parent
# statusbg used to indicated flagged when foreground color shows other status
# for collapsed thread
color index red black "~v~(~F)!~N" # collapsed thread with flagged, no unread
color index yellow black "~v~(~F~N)" # collapsed thread with some unread & flagged
color index green black "~N~v~(~F~N)" # collapsed thread with unread parent & flagged
color index green black "~N~v~(~F)" # collapsed thread with unread parent, no unread inside, but some flagged
color index cyan black "~v~(~p)" # collapsed thread with unread parent, no unread inside, some to me directly
color index yellow red "~v~(~D)" # thread with deleted (doesn't differentiate between all or partial)
# message headers ------------------------------------------------------
#color header brightgreen default "^"
color hdrdefault brightgreen default
color header brightyellow default "^(From)"
color header blue default "^(Subject)"
# body -----------------------------------------------------------------
color quoted blue default
color quoted1 cyan default
color quoted2 yellow default
color quoted3 red default
color quoted4 brightred default
color signature brightgreen default
color bold black default
color underline black default
color normal default default
#
color body brightcyan default "[;:][-o][)/(|]" # emoticons
color body brightcyan default "[;:][)(|]" # emoticons
color body brightcyan default "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
|FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
|IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
## pgp
color body red default "(BAD signature)"
color body cyan default "(Good signature)"
color body brightblack default "^gpg: Good signature .*"
color body brightyellow default "^gpg: "
color body brightyellow red "^gpg: BAD signature from.*"
mono body bold "^gpg: Good signature"
mono body bold "^gpg: BAD signature from.*"
# yes, an insance URL regex
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
# and a heavy handed email regex
color body red default "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])"
# Border lines.
color body blue default "( *[-+=#*~_]){6,}"

7
copy/.ssh/config

@ -0,0 +1,7 @@
Host *
# Forward ssh agent to the remote machine.
ForwardAgent yes
# Automatically add all common hosts to the host file as they are connected to.
StrictHostKeyChecking no

9
init/10_osx_xcode.sh

@ -0,0 +1,9 @@
# OSX-only stuff. Abort if not OSX.
is_osx || return 1
# Some tools look for XCode, even though they don't need it.
# https://github.com/joyent/node/issues/3681
# https://github.com/mxcl/homebrew/issues/10245
if [[ ! -d "$('xcode-select' -print-path 2>/dev/null)" ]]; then
sudo xcode-select -switch /usr/bin
fi

39
init/20_osx_homebrew.sh

@ -0,0 +1,39 @@
# OSX-only stuff. Abort if not OSX.
is_osx || return 1
# Install Homebrew.
if [[ ! "$(type -P brew)" ]]; then
e_header "Installing Homebrew"
true | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi
# Exit if, for some reason, Homebrew is not installed.
[[ ! "$(type -P brew)" ]] && e_error "Homebrew failed to install." && return 1
e_header "Updating Homebrew"
brew doctor
brew update
# Functions used in subsequent init scripts.
# Tap Homebrew kegs.
function brew_tap_kegs() {
kegs=($(setdiff "${kegs[*]}" "$(brew tap)"))
if (( ${#kegs[@]} > 0 )); then
e_header "Tapping Homebrew kegs: ${kegs[*]}"
for keg in "${kegs[@]}"; do
brew tap $keg
done
fi
}
# Install Homebrew recipes.
function brew_install_recipes() {
recipes=($(setdiff "${recipes[*]}" "$(brew list)"))
if (( ${#recipes[@]} > 0 )); then
e_header "Installing Homebrew recipes: ${recipes[*]}"
for recipe in "${recipes[@]}"; do
brew install $recipe
done
fi
}

59
init/30_osx_homebrew_casks.sh

@ -0,0 +1,59 @@
# OSX-only stuff. Abort if not OSX.
is_osx || return 1
# Exit if Homebrew is not installed.
[[ ! "$(type -P brew)" ]] && e_error "Brew casks need Homebrew to install." && return 1
# Ensure the cask keg and recipe are installed.
kegs=(caskroom/cask)
brew_tap_kegs
recipes=(brew-cask)
brew_install_recipes
# Exit if, for some reason, cask is not installed.
[[ ! "$(brew ls --versions brew-cask)" ]] && e_error "Brew-cask failed to install." && return 1
# Hack to show the first-run brew-cask password prompt immediately.
brew cask info this-is-somewhat-annoying 2>/dev/null
# Homebrew casks
casks=(
# Applications
adobe-reader
boot2docker
firefox
google-chrome
iterm2
macvim
remote-desktop-connection
spotify
vagrant
virtualbox
)
# Install Homebrew casks.
casks=($(setdiff "${casks[*]}" "$(brew cask list 2>/dev/null)"))
if (( ${#casks[@]} > 0 )); then
e_header "Installing Homebrew casks: ${casks[*]}"
for cask in "${casks[@]}"; do
brew cask install $cask
done
brew cask cleanup
fi
# Work around colorPicker symlink issue.
# https://github.com/caskroom/homebrew-cask/issues/7004
cps=()
for f in ~/Library/ColorPickers/*.colorPicker; do
[[ -L "$f" ]] && cps=("${cps[@]}" "$f")
done
if (( ${#cps[@]} > 0 )); then
e_header "Fixing colorPicker symlinks"
for f in "${cps[@]}"; do
target="$(readlink "$f")"
e_arrow "$(basename "$f")"
rm "$f"
cp -R "$target" ~/Library/ColorPickers/
done
fi

41
init/30_osx_homebrew_recipes.sh

@ -0,0 +1,41 @@
# OSX-only stuff. Abort if not OSX.
is_osx || return 1
# Exit if Homebrew is not installed.
[[ ! "$(type -P brew)" ]] && e_error "Brew recipes need Homebrew to install." && return 1
# Homebrew recipes
recipes=(
ansible
bash
git
htop-osx
man2html
mercurial
ssh-copy-id
)
brew_install_recipes
# Misc cleanup!
# This is where brew stores its binary symlinks
local binroot="$(brew --config | awk '/HOMEBREW_PREFIX/ {print $2}')"/bin