changeset 208:3f290bcae11a

wtf
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 13 Feb 2012 16:24:06 -0800
parents 7bad4b7281f2 (diff) beca399c3a16 (current diff)
children e39d514d0eff
files
diffstat 88 files changed, 3910 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.Xresources	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,7 @@
+*background: black
+*foreground: white
+
+Emacs.menu.attributeBackground: rgb:00/00/00
+Emacs.menu.attributeForeground: rgb:BB/BB/BB
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.bash_overrides	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+function unlink {	
+    command unlink `echo $@ | sed 's/\/$//g'`
+}
+
+function find {
+
+    if (( ! $# ))
+    then
+	return
+    fi
+    
+    if [ -d $1 ]
+    then
+	DIR="$1"
+	shift
+    else
+	DIR="$PWD"
+    fi
+    
+    if [ "$#" == "1" ]
+    then
+	`which find` -L "$PWD" -not -path '*.svn*' -iname "$1"
+	return 0
+    fi
+
+    COMMAND="`which find` -L \"$DIR\" -not -path '*.svn*' $@"
+#echo $COMMAND # for debugging
+    `which find` -L "$DIR" -not -path '*.svn*' "$@"
+}
+
+cd() {
+    
+    ENV=""
+    # find if you're in a
+    if [ -n "${WORKING_ENV}" ]
+    then
+	ENV="${WORKING_ENV}"
+    fi
+    if [ -n "${VIRTUAL_ENV}" ]
+    then
+	ENV="${VIRTUAL_ENV}"
+    fi
+
+
+    if [ -d "$@" ]
+    then		
+	command cd "$@"
+    else
+	if [ -e "$@" ]
+	then
+	    command cd `dirname "$@"`
+	else
+	    if [[ "$@" == "^"  &&  -n "${ENV}" ]]
+	    then
+		command cd "${ENV}"
+	    else
+		command cd "$@"
+	    fi
+	fi
+    fi
+
+    # handle ENVs
+    if [ -e "bin/activate" ]
+    then
+	if [ -n "${ENV}" ]
+        then
+	    if [ "${ENV}" != "${PWD}" ]
+	    then
+		if [[ -n "`type -t deactivate`" ]]
+		then
+		    deactivate
+		fi
+	    else
+		return 
+	    fi
+	fi
+	source "bin/activate"
+    fi
+
+    ENV=""
+    # find if you're in a
+    if [ -n "${WORKING_ENV}" ]
+    then
+	ENV="${WORKING_ENV}"
+    fi
+    if [ -n "${VIRTUAL_ENV}" ]
+    then
+	ENV="${VIRTUAL_ENV}"
+    fi
+
+    if [ -n "${ENV}" ]
+    then
+	FULLPWD=$(python -c 'import os; print os.getcwd()')
+	if (( ! `expr match "${FULLPWD}" "${ENV}"` ))
+	then 
+	    if [[ -n "`type -t deactivate`" ]]
+	    then
+		deactivate
+	    fi
+	fi
+    fi
+    unset ENV
+}
+
+emacsclient() {
+    command emacsclient $@ > /dev/null &
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.bash_profile	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,5 @@
+# /etc/skel/.bash_profile
+
+# This file is sourced by bash for login shells.  The following line
+# runs your .bashrc and is recommended by the bash info pages.
+[[ -f ~/.bashrc ]] && . ~/.bashrc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.bashrc	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,363 @@
+source /etc/profile
+
+# Test for an interactive shell.  There is no need to set anything
+# past this point for scp and rcp, and it's important to refrain from
+# outputting anything in those cases.
+if [[ $- != *i* ]] ; then
+	# Shell is non-interactive.  Be done now!
+	return
+fi
+
+# Enable colors for ls, etc.  Prefer ~/.dir_colors #64489
+if [[ -f ~/.dir_colors ]] ; then
+	eval $(dircolors -b ~/.dir_colors)
+elif [[ -f /etc/DIR_COLORS ]] ; then
+	eval $(dircolors -b /etc/DIR_COLORS)
+fi
+
+# variables
+export CLICOLOR=1
+export EDITOR='emacs -nw'
+export MOZCONFIG=~/mozilla/mozconfigs/mozconfig
+export MOZSOURCE=~/mozilla/src/mozilla-central
+export MOZOBJ=~/mozilla/src/obj-browser
+export JS_EDITLINE=1
+
+# aliases
+alias ls='ls --color=auto'
+alias grep='grep --colour=auto'
+alias wget='wget --no-check-certificate'
+alias datestamp='date +%Y%m%d%H%M%S'
+alias svnst='svn st | grep -v "^\?"'
+alias awd="python -c 'import os;  print os.path.realpath(\".\")'"
+alias distribute='python setup.py egg_info -RDb "" sdist register upload'
+alias random="python -c 'import sys, random; foo = sys.argv[1:]; random.shuffle(foo); print \" \".join(foo)'"
+alias xpcshell="LD_LIBRARY_PATH=${MOZOBJ}/dist/bin ${MOZOBJ}/dist/bin/xpcshell"
+
+# PROMPT
+PS1='│'
+PS2='.'
+PROMPT_COMMAND='echo -ne "\033]0;${SSH_CLIENT/*/$HOSTNAME:}${PWD/~/~}\007"'
+
+# PATHs
+export PATH=~/firefox:~/bin:~/python:$PATH:/usr/sbin:/usr/games/bin
+export PYTHONPATH=~/python:$PYTHONPATH:~/virtualenv
+
+
+### functions
+
+cdwin() {
+# change directory to a window's location using its title
+    DIR=$(xwininfo | dictify.py xwininfo | awk '{ print $NF }' | sed 's/"//g')
+    DIR=${DIR/\~/$HOME}
+    cd $DIR
+}
+
+eend() {
+# edit the end of a file with emacs
+    FILE=$1
+    shift
+    emacs +`wc -l "$FILE"` $@
+}
+
+git-diff-master() {
+git diff $(git merge-base HEAD master)
+}
+
+function colors() {
+
+    CLR_WHITE="\033[0;37m"
+    CLR_WHITEBOLD="\033[1;37m"
+    CLR_BLACK="\033[0;30m"
+    CLR_GRAY="\033[1;30m"
+    CLR_BLUE="\033[1;34m"
+    CLR_BLUEBOLD="\033[0;34m"
+    CLR_GREEN="\033[0;32m"
+    CLR_GREENBOLD="\033[1;32m"
+    CLR_CYAN="\033[0;36m"
+    CLR_CYANBOLD="\033[1;36m"
+    CLR_RED="\033[0;31m"
+    CLR_REDBOLD="\033[1;31m"
+    CLR_PURPLE="\033[0;35m"
+    CLR_PURPLEBOLD="\033[1;35m"
+    CLR_YELLOW="\033[0;33m"
+    CLR_YELLOWBOLD="\033[1;33m"
+    CLR_NOTHING="\033[0m"
+}
+colors
+
+# nice fast find function
+EXCLUDES="(\.svn)|(\.mo$)|(\.po$)|(\.pyc$)"
+ff() {
+
+    if (( $# < 2 ))
+    then
+	FILENAME='*' # default -- look in all files
+    else
+	FILENAME=$2
+    fi
+    CMD='command find -L $PWD -iname "${FILENAME}" -print0 2> /dev/null | xargs -r0 grep -il "$1" 2> /dev/null | egrep -v "${EXCLUDES}" 2> /dev/null'
+#    echo $CMD
+    eval $CMD
+
+}
+
+chainff() {
+    if (( $# < 2 ))
+    then
+	return 0
+    fi
+
+    RESULTS=`ff "$2" "$1"`
+    shift 2
+
+    for i in $RESULTS
+    do
+	for arg in $@
+	do
+	    if grep -il "$arg" "$i" &> /dev/null
+	    then
+		touch /dev/null
+	    else
+		i=""		
+		break
+	    fi
+	done
+	if [ -n "$i" ]
+	then
+	    echo $i
+	fi
+    done
+}
+
+# contextual fastfind
+cff () {
+
+    if (( $# < 2 )); then
+        local FILENAME='*' # default -- look in all files
+    else
+        local FILENAME=$2
+    fi
+
+    for i in `ff "$1" "$FILENAME"`; do
+        echo -e "$CLR_GREEN--->>> ""$CLR_YELLOWBOLD""$i""$CLR_NOTHING" :
+        grep --color=auto -i -n -C 3 "$1" $i
+    done
+
+} 
+
+# make a temporary file
+tmpfile() {
+
+if [ "$#" == "0" ]
+then
+    args="tmp"
+else
+    args=$@
+fi
+
+for i in $args
+do
+    NEWNAME=${i}.$RANDOM
+
+    while [ -e $NEWNAME ]
+    do
+	NEWNAME=${NEWNAME}.tmp
+    done
+    echo "$NEWNAME"
+done
+}
+
+edpe() {
+# edit and pipe the buffer to stdout
+FILE=`tmpfile`
+$EDITOR $FILE
+cat $FILE
+rm $FILE
+}
+
+swap() {
+# swap two files
+    if [ "$#" != "2" ]
+    then
+	echo "Usage: $FUNCNAME <first_arg> <second_arg>"
+	return
+    fi
+    for i in "$1" "$2"
+    do
+	if [ ! -w "$i" ]
+	then
+	    echo "$FUNCNAME: Can't move $i"
+	    return 1
+	fi
+    done
+
+    NEWNAME=`basename $1`.$RANDOM
+
+    while [ -e $NEWNAME ]
+    do
+	NEWNAME=${NEWNAME}.tmp
+	echo "$NEWNAME"
+    done
+
+    mv `basename $1` $NEWNAME
+    mv `basename $2` `basename $1`
+    mv $NEWNAME `basename $2`
+}
+
+isrunning() {
+# is a process running? (by name)
+    for i in "$@"
+    do
+	ps axwww  | grep "$i" | grep -v 'grep'
+    done | sort | uniq
+
+}
+
+killbyname() {
+# kill a process by name
+    kill `isrunning "$@" | awk '{ print $1 }' | onelineit.py`
+}
+
+
+tf() {
+    if [[ $@ ]]
+    then
+	echo "true"
+    else
+	echo "false"
+    fi
+}
+
+# full name
+fn() {
+    python -c "import os; print os.path.realpath('$*')"
+}
+
+# which view
+whview() {
+    less `which $@`
+}
+
+# which emacs
+whemacs() {
+    emacs -nw `which $@`
+}
+
+pyfile() {
+# python file name
+python -c "import $1; print $1.__file__"
+}
+
+svndance(){
+# do the svn import dance!
+if (( $# ))
+then
+    svn import $1
+    cd ..
+    rm -rf $OLDPWD
+    svn co $1 $OLDPWD
+    cd $OLDPWD
+else
+    return 1
+fi
+}
+
+difffiles() {
+grep '^+++ ' $@ | sed 's/+++ b\///'
+}
+
+hg-update-all() { 
+for i in *; 
+do
+    if [ -e $i/.hg ]
+    then
+        cd $i
+        hg pull
+        hg update
+        cd -
+    fi
+done
+}
+
+hg-qcommit() {
+message=$1
+hg qrefresh
+if [ -z "${message}" ]
+then
+    hg qcommit
+else
+    hg qcommit -m "${message}"
+fi
+hgroot=$(hg root)
+patches=${hgroot}/.hg/patches/ 
+if [ -e ${patches}.hg ]
+then
+    cd ${patches}
+    hg push
+fi
+cd -
+}
+
+blog-file() {
+echo "$HOME/web/blog/k0s/entries/public/$1"
+}
+
+hgrc() {
+ROOT="${1}"
+echo "[paths]"
+echo "default = ${ROOT}"
+echo "default-push = ssh://${ROOT#http*://}"
+}
+
+flatten() {
+  directory=$PWD
+  if [ "$#" == "1" ]
+  then
+      directory=$1
+  fi
+  cd $directory
+  unset find # don't use the alias
+  find . -name '*' -type f | sed 's/.\///' | while read line
+  do
+      filename=$(echo $line | sed 's/\//-/g')
+      mv "${line}" "${filename}"
+  done
+  for i in *
+  do
+      if [ -d $i ]
+      then
+          rm -rf "${i}"
+      fi
+  done
+}
+
+filehandles() {
+    TMPFILE=$(tmpfile)
+    ps -e|grep -v TTY|awk {'print "echo -n \"Process: "$4"\tPID: "$1"\tNumber of FH: \"; lsof -p "$1"|wc -l"'} > ${TMPFILE}
+    . ${TMPFILE} | sort
+    rm ${TMPFILE}
+}
+
+quotemail() {
+
+command='s/^/> /'
+inplace=""
+if [ "$#" == "2" ]
+then
+    inplace="-i"
+fi
+
+sed ${inplace} "${command}" "$1"
+
+}
+
+### include overrides for commands
+source ~/.bash_overrides
+
+### regenerate fluxbox menus here for convenience
+MENU=~/web/site/programs.html
+if [ -e $MENU ]
+then
+    html2flux.py $MENU > ~/.fluxbox/applications
+fi
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.emacs	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,97 @@
+(server-start)
+(if (boundp 'tool-bar-mode) (tool-bar-mode 0))
+(setq inhibit-startup-message t)
+(setq make-backup-files nil)
+(put 'downcase-region 'disabled nil)
+(setq truncate-lines nil)
+(setq truncate-partial-width-windows nil) 
+(setq use-file-dialog nil)
+
+;; indentation
+
+;; python indentation
+(setq python-indent 4)
+(setq-default py-indent-offset 4)
+(setq python-guess-indent nil)
+
+;; javascript indentation: http://www.brgeight.se/downloads/emacs/javascript.el
+(setq javascript-indent-level 2)
+(setq js-indent-level 2)
+
+(setq-default indent-tabs-mode nil)
+(defface extra-whitespace-face '((t (:background "pale green"))) "Used for tabs and such.")
+
+(autoload 'doctest-mode "doctest-mode" "doctest editing mode." t)
+
+(transient-mark-mode 1)
+
+(put 'upcase-region 'disabled nil)
+;; Show line-number in the mode line
+(line-number-mode 1)
+
+;; Show column-number in the mode line
+(column-number-mode 1)
+
+;; Bind major editing modes to certain file extensions 
+(setq auto-mode-alist (cons '("\\.zcml$" . sgml-mode) auto-mode-alist))
+(setq auto-mode-alist (cons '("\\.pt$" . sgml-mode) auto-mode-alist))
+(setq auto-mode-alist (cons '("\\.cpt$" . sgml-mode) auto-mode-alist))
+(setq auto-mode-alist (cons '("\\.cpy$" . python-mode) auto-mode-alist))
+(setq auto-mode-alist (cons '("\\.vpy$" . python-mode) auto-mode-alist))
+
+;; Turn off the status bar and on the mouse if we're not in a window system
+(menu-bar-mode (if window-system 1 -1))
+(add-hook 'text-mode-hook 'turn-on-auto-fill)
+
+(add-hook 'sgml-mode-hook 'turn-off-auto-fill)
+
+(setq grep-command "grep -liE")
+
+;; recentf stuff
+(require 'recentf)
+(recentf-mode 1)
+(setq recentf-max-menu-items 25)
+(global-set-key "\C-x\ \C-r" 'recentf-open-files)
+
+;; full-steam-ahead-and-damn-the-torpedoes
+(defun
+  full-steam-ahead-and-damn-the-torpedoes
+  (prompt) t)
+(defalias 'y-or-n-p
+  'full-steam-ahead-and-damn-the-torpedoes)
+(defalias 'yes-or-no-p
+  'full-steam-ahead-and-damn-the-torpedoes)
+
+(require 'uniquify)
+(setq uniquify-buffer-name-style 'post-forward)
+
+;; wheel mouse
+(global-set-key [mouse-4] 'scroll-down)
+(global-set-key [mouse-5] 'scroll-up)
+
+;; substring buffer switching mode
+(iswitchb-mode 1)
+
+(global-set-key "\M-g" 'goto-line)
+
+;; (when (load "flymake" t)
+;;   (defun flymake-pyflakes-init ()
+;;     (let* ((temp-file (flymake-init-create-temp-buffer-copy
+;; 		       'flymake-create-temp-inplace))
+;; 	   (local-file (file-relative-name
+;; 			temp-file
+;; 			(file-name-directory buffer-file-name))))
+;;       (list "pyflakes" (list local-file))))
+  
+;;   (add-to-list 'flymake-allowed-file-name-masks
+;; 	       '("\\.py\\'" flymake-pyflakes-init)))
+
+;; (add-hook 'find-file-hook 'flymake-find-file-hook)
+(server-start)
+
+(fset 'break "import pdb; pdb.set_trace();\C-a\C-i")
+(add-hook 'python-mode-hook
+          '(lambda ()
+             (local-set-key  [(meta ?p) (meta ?p)] 'break)))
+
+(setq-default show-trailing-whitespace t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.fluxbox/init	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,111 @@
+-session.screen0.rootCommand:	fbsetbg ~/image/wallpaper
+session.screen0.window.focus.alpha:	122
+session.screen0.window.unfocus.alpha:	47
+session.screen0.iconbar.wheelMode:	Screen
+session.screen0.iconbar.alignment:	Relative
+session.screen0.iconbar.usePixmap:	true
+session.screen0.iconbar.iconWidth:	70
+session.screen0.iconbar.mode:	{static groups} (workspace)
+session.screen0.iconbar.deiconifyMode:	Follow
+session.screen0.iconbar.iconTextPadding:	10l
+session.screen0.tab.width:	0
+session.screen0.tab.alignment:	Left
+session.screen0.tab.placement:	TopLeft
+session.screen0.tab.height:	0
+session.screen0.tab.rotatevertical:	True
+session.screen0.clientMenu.usePixmap:	true
+session.screen0.slit.direction:	Vertical
+session.screen0.slit.onhead:	0
+session.screen0.slit.maxOver:	false
+session.screen0.slit.onTop:	False
+session.screen0.slit.layer:	Dock
+session.screen0.slit.autoHide:	false
+session.screen0.slit.alpha:	255
+session.screen0.slit.acceptKdeDockapps:	true
+session.screen0.slit.placement:	RightBottom
+session.screen0.menu.alpha:	82
+session.screen0.tabs.intitlebar:	true
+session.screen0.tabs.maxOver:	false
+session.screen0.tabs.usePixmap:	false
+session.screen0.titlebar.left:	Stick 
+session.screen0.titlebar.right:	Minimize Maximize Close 
+session.screen0.toolbar.visible:	true
+session.screen0.toolbar.onhead:	0
+session.screen0.toolbar.widthPercent:	44
+session.screen0.toolbar.maxOver:	true
+session.screen0.toolbar.tools:	workspacename, iconbar, systemtray, clock
+session.screen0.toolbar.height:	0
+session.screen0.toolbar.layer:	Desktop
+session.screen0.toolbar.onTop:	False
+session.screen0.toolbar.autoHide:	false
+session.screen0.toolbar.placement:	BottomCenter
+session.screen0.toolbar.alpha:	50
+session.screen0.overlay.lineWidth:	1
+session.screen0.overlay.lineStyle:	LineSolid
+session.screen0.overlay.joinStyle:	JoinMiter
+session.screen0.overlay.capStyle:	CapNotLast
+session.screen0.strftimeFormat:	%k:%M
+session.screen0.reversewheeling:	false
+session.screen0.maxDisableResize:	false
+session.screen0.desktopwheeling:	true
+session.screen0.maxDisableMove:	false
+session.screen0.userFollowModel:	Follow
+session.screen0.windowMenu:	
+session.screen0.demandsAttentionTimeout:	500
+session.screen0.sloppywindowgrouping:	true
+session.screen0.resizeMode:	Bottom
+session.screen0.edgeSnapThreshold:	0
+session.screen0.noFocusWhileTypingDelay:	0l
+session.screen0.maxIgnoreIncrement:	true
+session.screen0.tabFocusModel:	ClickToTabFocus
+session.screen0.tooltipDelay:	500
+session.screen0.workspaceNames:	one,two,three,four,five,six,
+session.screen0.imageDither:	false
+session.screen0.menuMode:	Delay
+session.screen0.focusNewWindows:	true
+session.screen0.windowScrollAction:	
+session.screen0.clickRaises:	true
+session.screen0.windowPlacement:	RowSmartPlacement
+session.screen0.workspacewarping:	true
+session.screen0.opaqueMove:	false
+session.screen0.menuDelay:	0
+session.screen0.autoRaise:	false
+session.screen0.followModel:	Ignore
+session.screen0.decorateTransient:	true
+session.screen0.fullMaximization:	true
+session.screen0.allowRemoteActions:	false
+session.screen0.defaultDeco:	NORMAL
+session.screen0.focusModel:	MouseFocus
+session.screen0.rootCommand:	fbsetbg ~/image/wallpaper
+session.screen0.windowScrollReverse:	false
+session.screen0.rowPlacementDirection:	LeftToRight
+session.screen0.showwindowposition:	true
+session.screen0.colPlacementDirection:	TopToBottom
+session.screen0.focusLastWindow:	true
+session.screen0.workspaces:	6
+session.screen0.antialias:	true
+session.screen0.menuDelayClose:	0
+session.configVersion:	13
+session.imageDither:	True
+session.focusTabMinWidth:	0
+session.numLayers:	13
+session.forcePseudoTransparency:	true
+session.cacheMax:	200l
+session.useMod1:	true
+session.ignoreBorder:	false
+session.styleFile:	~/.fluxbox/styles/Black
+session.opaqueMove:	False
+session.styleOverlay:	~/.fluxbox/overlay
+session.menuFile:	~/.fluxbox/menu
+session.groupFile:	~/.fluxbox/groups
+session.appsFile:	~/.fluxbox/apps
+session.modKey:	Mod1
+session.slitlistFile:	~/.fluxbox/slitlist
+session.keyFile:	~/.fluxbox/keys
+session.tabsAttachArea:	Window
+session.cacheLife:	5l
+session.doubleClickInterval:	250
+session.colorsPerChannel:	4
+session.tabs:	false
+session.autoRaiseDelay:	250
+session.tabPadding:	0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.fluxbox/keys	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,76 @@
+! fluxbox-update_configs added '(workspace=[current])' to (Next|Prev)(Window|Group)
+! check lines marked by 'FBCV13' if they are correctly updated
+!mouse actions added by fluxbox-update_configs
+OnTitlebar Mouse1 :MacroCmd {Focus} {Raise} {ActivateTab}
+!mouse actions added by fluxbox-update_configs
+OnTitlebar Move1 :StartMoving
+OnLeftGrip Move1 :StartResizing bottomleft
+OnRightGrip Move1 :StartResizing bottomright
+OnWindowBorder Move1 :StartMoving
+
+!mouse actions added by fluxbox-update_configs
+OnTitlebar Mouse2 :StartTabbing
+
+!mouse actions added by fluxbox-update_configs
+OnTitlebar Double Mouse1 :Shade
+OnTitlebar Mouse3 :WindowMenu
+
+!mouse actions added by fluxbox-update_configs
+OnWindow Mod1 Mouse1 :MacroCmd {Raise} {Focus} {StartMoving}
+OnWindow Mod1 Mouse3 :MacroCmd {Raise} {Focus} {StartResizing BottomRight}
+
+!mouse actions added by fluxbox-update_configs
+OnToolbar Mouse4 :NextWorkspace
+OnToolbar Mouse5 :PrevWorkspace
+
+!mouse actions added by fluxbox-update_configs
+OnDesktop Mouse1 :hideMenus
+OnDesktop Mouse2 :workspaceMenu
+OnDesktop Mouse3 :rootMenu
+OnDesktop Mouse4 :nextWorkspace
+OnDesktop Mouse5 :prevWorkspace
+
+# File generated by FluxConf
+Mod1 Tab :nextwindow (workspace=[current]) !! FBCV13 !!
+Mod1 Shift Tab :prevwindow (workspace=[current]) !! FBCV13 !!
+Control Mod1 Left :prevworkspace
+Control Mod1 Right :nextworkspace
+Mod1 F1 :Workspace 1
+Mod1 F2 :Workspace 2
+Mod1 F3 :Workspace 3
+Mod1 F4 :Workspace 4
+Mod1 F5 :Workspace 5
+Mod1 F6 :Workspace 6
+Mod1 F7 :Workspace 7
+Mod1 F8 :Workspace 8
+Mod1 F9 :Workspace 9
+Mod1 F10 :Workspace 10
+
+Shift Right :MaximizeHorizontal
+Shift Up :MaximizeVertical
+F11 :Fullscreen
+Menu :RootMenu
+
+# commands
+Control Mod1 a :ExecCommand xclip -o | python /home/jhammel/python/window_path.py | xclip -i
+Control Mod1 b :ExecCommand sleep 1; xset dpms force off # blank screen
+Control Mod1 c :ExecCommand xterm -geometry 22x9 -T "`date +'%b %-d'`" -e 'cal; sleep 10' # calender
+Control Mod1 d :ExecCommand date | xclip -i # put now's date on the X clipboard
+Control Mod1 e :ExecCommand emacs $(test -f "$(xclip -o)" && xclip -o) # emacs
+Control Mod1 f :ExecCommand firefox
+Control Mod1 g :ExecCommand gkrellm
+Control Mod1 h :ExecCommand /home/jhammel/bin/keyshelp.sh # hotkeys help
+Control Mod1 i :ExecCommand import /home/jhammel/screenshot.png
+Control Mod1 k :ExecCommand echo $(curl $(xclip -o)?format=text) - $(xclip -o) | xclip -i # bitsyblog entry
+Control Mod1 l :ExecCommand echo http://letmegooglethatforyou.com/?q=$(xclip -o) | xclip -i
+Control Mod1 m :ExecCommand  xterm -e alsamixer # mixer
+Control Mod1 o :ExecCommand xclip -o | /home/jhammel/python/onelineit.py | xclip -i # put the clipboard contents on one line
+Control Mod1 p :ExecCommand xclip -o | /home/jhammel/python/pbmoz.py | xclip -i 
+Control Mod1 r :ExecCommand import -window root -silent /home/jhammel/screenshot.png
+Control Mod1 q :ExecCommand xclip -o | sed 's/^/> /' | xclip -i # quote using >'s
+Control Mod1 s :ExecCommand /home/jhammel/bin/smartopen "$(xclip -o)" # smartopen
+Control Mod1 t :ExecCommand gnome-terminal # terminal
+Control Mod1 x :ExecCommand xkill
+Control Mod1 0 :ExecCommand xclip -o | sed 's/^[-+]//' | xclip -i # strip leading +s
+
+Mod4 t :ToggleDecor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.fluxbox/menu	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,22 @@
+[begin] (Fluxbox)
+
+[include] (~/.fluxbox/applications)
+
+[submenu] (fluxbox)
+[exec] (edit menu) { emacs ~/web/site/programs.html ~/.fluxbox/menu && ~/python/html2flux.py ~/web/site/programs.html > ~/.fluxbox/applications }
+[exec] (edit init) { emacs ~/.fluxbox/init }
+[exec] (edit keys) { emacs ~/.fluxbox/keys }
+[config] (Configure) 
+[submenu] (Styles)
+ [stylesdir] (~/.fluxbox/styles)
+[end]
+[workspaces] (Workspace List) 
+[restart] (gnome-session) {gnome-session}
+[commanddialog] (Fluxbox Command) 
+[reconfig] (Reload config) 
+[restart] (Restart) 
+[exec] (About) {(fluxbox -v; fluxbox -info | sed 1d) 2> /dev/null | xmessage -file - -center} 
+[separator] 
+[exit] (Exit) 
+[end]
+[end]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.fluxbox/startup	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,11 @@
+# fluxbox startup-script:
+
+/usr/bin/fbsetroot -solid black
+
+xrdb ~/.Xresources
+xset b off
+xset s off
+xset dpms 1200 2400 3600
+
+exec /usr/bin/fluxbox
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.fluxbox/styles/Black	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,138 @@
+menu.title:                     solid
+  menu.title.color:             black
+  menu.title.textColor:         grey
+  menu.title.textShadowColor:   #000000
+  menu.title.textShadowXOffset: 1
+  menu.title.textShadowYOffset: 1
+  menu.title.opacity:           60
+
+menu.frame:             solid
+  menu.roundCorners: TopRight TopLeft BottomLeft BottomRight
+  menu.frame.color:     black
+  menu.frame.textColor: white 
+  menu.frame.opacity:   80
+
+menu.hilite:                     solid
+  menu.hilite.color:             black
+  menu.hilite.textColor:         grey
+  menu.hilite.textShadowColor:   #000000
+  menu.hilite.textShadowXOffset: 1
+  menu.hilite.textShadowYOffset: 1
+  menu.hilite.opacity:           50
+
+menu.bullet:              triangle 
+menu.justify:             right
+
+
+dockappholder.*.frame:           flat gradient crossdiagonal
+  dockappholder.*.frame.color:   snow
+  dockappholder.*.frame.colorTo: black
+  dockappholder.*.frame.opacity: 65
+
+dockappholder.*.borderWidth: 1
+dockappholder.*.borderColor: #000000
+
+borderColor: black
+borderWidth: 1
+handleWidth: 3
+
+ outlineColor:      
+ menu.borderWidth:  1
+ menu.title.height: 15
+ menu.item.height:  15
+
+ *.font: smoothansi:pixelsize=14 [vga]
+
+
+toolbar: Solid
+toolbar.color: black
+toolbar.*.opacity: 80
+toolbar.alpha: 255
+
+toolbar.roundCorners: TopRight TopLeft 
+toolbar.label: parentrelative
+toolbar.clock: parentrelative
+toolbar.iconbar.unfocused: parentrelative
+toolbar.iconbar.focused: parentrelative
+toolbar.iconbar.empty: parentrelative
+
+toolbar.iconbar.focused.textColor: white
+toolbar.iconbar.unfocused.textColor: grey
+toolbar.color: black
+toolbar.button:	Raised Bevel1 Gradient Horizontal
+toolbar.button.picColor: black
+
+toolbar.button.pressed: Sunken Bevel1 Gradient Horizontal
+
+toolbar.button.pressed.picColor: grey
+
+toolbar.label.textColor: grey
+toolbar.windowLabel.textColor: grey  
+toolbar.clock.textColor: grey
+toolbar.textColor: grey
+
+toolbar.borderWidth: 2
+toolbar.bevelWidth: 1
+toolbar.borderColor:  black
+toolbar.clock.font: Sans Serif-9:shadow
+toolbar.clock.justify: Center
+toolbar.clock.opacity: 255
+toolbar.clock.alpha: 255
+toolbar.iconbar.focused.font: Sans Serif-9:shadow
+toolbar.iconbar.unfocused.font: Sans Serif-9:shadow
+toolbar.workspace.font: Sans Serif-9:shadow
+
+window.alpha: 180
+
+window.label.focus: parentrelative
+window.label.focus.color: black
+window.label.focus.colorTo: black
+window.label.focus.textColor: white
+
+window.*.opacity:  50
+window.label.unfocus: parentrelative
+window.label.unfocus.color: black
+window.label.unfocus.colorTo: black
+window.label.unfocus.textColor:  dark grey
+
+window.title.focus: flat
+window.title.unfocus: flat
+
+window.handle.focus: parentrelative
+window.handle.focus.color: black
+window.handle.focus.colorTo: black
+
+window.handle.unfocus: parentrelative
+window.handle.unfocus.color: black
+window.handle.unfocus.colorTo: black 
+
+window.button.focus: Raised Bevel1 Gradient Horizontal
+window.button.focus.color: black      
+window.button.focus.colorTo: black
+window.button.focus.picColor: grey     
+
+window.button.unfocus: Raised Bevel1 Gradient Horizontal
+window.button.unfocus.color:	black
+window.button.unfocus.colorTo: black
+window.button.unfocus.picColor: #ffffff
+
+window.frame.focusColor: black
+window.frame.unfocusColor: black
+
+window.grip.focus: parentrelative
+window.grip.focus.color: black
+window.grip.focus.colorTo: black
+
+window.grip.unfocus: parentrelative
+window.grip.unfocus.color: black 
+window.grip.unfocus.colorTo: blackf
+
+window.borderWidth: 2
+window.handleWidth: 3
+window.bevelWidth: 1
+window.borderColor: black
+window.font: Sans Serif-8:shadow
+window.justify: center
+
+background: fullscreen
+background.pixmap: ~/image/wallpaper
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,8 @@
+*.pyc
+*.pyo
+*.egg-info
+*.swp
+*~
+build
+dist
+#*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gtkrc-2.0	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,2 @@
+include "/usr/share/themes/Tenebrific/gtk-2.0/gtkrc"
+gtk-key-theme-name = "Emacs"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,11 @@
+syntax: glob
+.hgignore
+*.pyc
+*.pyo
+*.egg-info
+*.swp
+*~
+build
+dist
+#*
+._*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgrc	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,31 @@
+[ui]
+username = Jeff Hammel <jhammel@mozilla.com>
+ignore = /home/jhammel/.hgignore
+merge = meld
+
+[defaults]
+commit = -v
+diff = -p -U 8
+qdiff = -p -U 8
+qnew = -U
+repository_host = k0s.org/hg
+pull = --rebase
+revert = --no-backup
+
+[diff]
+git = 1
+showfunc = 1
+unified = 8
+
+[extensions]
+hgext.mq = 
+rebase =
+convert = 
+
+[trusted]
+users = jhammel
+groups = jhammel
+
+[web]
+allow_archive = rss, zip, bz2
+contact = jhammel at mozilla dot com
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.irssi/config	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,206 @@
+servers = (
+  {
+    address = "irc.freenode.net";
+    chatnet = "freenode";
+    autoconnect = "Yes";
+  },
+  {
+    address = "irc.mozilla.org";
+    chatnet = "mozilla";
+    autoconnect = "Yes";
+  }
+);
+
+chatnets = {
+  freenode = { type = "IRC"; };
+  IRCnet = {
+    type = "IRC";
+    max_kicks = "4";
+    max_msgs = "5";
+    max_whois = "4";
+    max_query_chans = "5";
+  };
+  SILC = { type = "SILC"; };
+  mozilla = { type = "IRC"; };
+};
+
+channels = (
+  { name = "#socialplanning"; chatnet = "freenode"; autojoin = "Yes"; },
+
+  { name = "#developers"; chatnet = "mozilla"; autojoin = "Yes"; },
+  { name = "#ateam"; chatnet = "mozilla"; autojoin = "Yes"; },
+  { name = "#build"; chatnet = "mozilla"; autojoin = "Yes"; }
+  { name = "#sf"; chatnet = "mozilla"; autojoin = "Yes"; }
+  { name = "#jetpack"; chatnet = "mozilla"; autojoin = "Yes"; }
+);
+
+aliases = {
+  J = "join";
+  WJOIN = "join -window";
+  WQUERY = "query -window";
+  LEAVE = "part";
+  BYE = "quit";
+  EXIT = "quit";
+  SIGNOFF = "quit";
+  DESCRIBE = "action";
+  DATE = "time";
+  HOST = "userhost";
+  LAST = "lastlog";
+  SAY = "msg *";
+  WI = "whois";
+  WII = "whois $0 $0";
+  WW = "whowas";
+  W = "who";
+  N = "names";
+  M = "msg";
+  T = "topic";
+  C = "clear";
+  CL = "clear";
+  K = "kick";
+  KB = "kickban";
+  KN = "knockout";
+  BANS = "ban";
+  B = "ban";
+  MUB = "unban *";
+  UB = "unban";
+  IG = "ignore";
+  UNIG = "unignore";
+  SB = "scrollback";
+  UMODE = "mode $N";
+  WC = "window close";
+  WN = "window new hide";
+  SV = "say Irssi $J ($V) - http://irssi.org/";
+  GOTO = "sb goto";
+  CHAT = "dcc chat";
+  RUN = "SCRIPT LOAD";
+  UPTIME = "eval exec - expr `date +%s` - \\$F | awk '{print \"Irssi uptime: \"int(\\\\\\$1/3600/24)\"d \"int(\\\\\\$1/3600%24)\"h \"int(\\\\\\$1/60%60)\"m \"int(\\\\\\$1%60)\"s\" }'";
+  CALC = "exec - if which bc &>/dev/null\\; then echo '$*' | bc | awk '{print \"$*=\"$$1}'\\; else echo bc was not found\\; fi";
+  SBAR = "STATUSBAR";
+  INVITELIST = "mode $C +I";
+  Q = "QUERY";
+  "MANUAL-WINDOWS" = "set use_status_window off;set autocreate_windows off;set autocreate_query_level none;set autoclose_windows off;set reuse_unused_windows on;save";
+  EXEMPTLIST = "mode $C +e";
+  ATAG = "WINDOW SERVER";
+};
+
+statusbar = {
+  # formats:
+  # when using {templates}, the template is shown only if it's argument isn't
+  # empty unless no argument is given. for example {sb} is printed always,
+  # but {sb $T} is printed only if $T isn't empty.
+
+  items = {
+    # start/end text in statusbars
+    barstart = "{sbstart}";
+    barend = "{sbend}";
+
+    topicbarstart = "{topicsbstart}";
+    topicbarend = "{topicsbend}";
+
+    # treated "normally", you could change the time/user name to whatever
+    time = "{sb $Z}";
+    user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}";
+
+    # treated specially .. window is printed with non-empty windows,
+    # window_empty is printed with empty windows
+    window = "{sb $winref:$itemname{sbmode $M}}";
+    window_empty = "{sb $winref{sbservertag $tag}}";
+    prompt = "{prompt $[.15]itemname}";
+    prompt_empty = "{prompt $winname}";
+    topic = " $topic";
+    topic_empty = " Irssi v$J - http://irssi.org/help/";
+
+    # all of these treated specially, they're only displayed when needed
+    lag = "{sb Lag: $0-}";
+    act = "{sb Act: $0-}";
+    more = "-- more --";
+  };
+
+  # there's two type of statusbars. root statusbars are either at the top
+  # of the screen or at the bottom of the screen. window statusbars are at
+  # the top/bottom of each split window in screen.
+  default = {
+    # the "default statusbar" to be displayed at the bottom of the window.
+    # contains all the normal items.
+    window = {
+      disabled = "no";
+
+      # window, root
+      type = "window";
+      # top, bottom
+      placement = "bottom";
+      # number
+      position = "1";
+      # active, inactive, always
+      visible = "active";
+
+      # list of items in statusbar in the display order
+      items = {
+        barstart = { priority = "100"; };
+
+        user = { };
+        window = { };
+        window_empty = { };
+        lag = { priority = "-1"; };
+        act = { priority = "10"; };
+        more = { priority = "-1"; alignment = "right"; };
+        barend = { priority = "100"; alignment = "right"; };
+      };
+    };
+
+    # statusbar to use in inactive split windows
+    window_inact = {
+      type = "window";
+      placement = "bottom";
+      position = "1";
+      visible = "inactive";
+      items = {
+        barstart = { priority = "100"; };
+        window = { };
+        window_empty = { };
+        more = { priority = "-1"; alignment = "right"; };
+        barend = { priority = "100"; alignment = "right"; };
+      };
+    };
+
+    # we treat input line as yet another statusbar :) It's possible to
+    # add other items before or after the input line item.
+    prompt = {
+      type = "root";
+      placement = "bottom";
+      # we want to be at the bottom always
+      position = "100";
+      visible = "always";
+      items = {
+        prompt = { priority = "-1"; };
+        prompt_empty = { priority = "-1"; };
+        # treated specially, this is the real input line.
+        input = { priority = "10"; };
+      };
+    };
+
+    # topicbar
+    topic = {
+      type = "root";
+      placement = "top";
+      position = "1";
+      visible = "always";
+      items = {
+        topicbarstart = { priority = "100"; };
+        topic = { };
+        topic_empty = { };
+        topicbarend = { priority = "100"; alignment = "right"; };
+      };
+    };
+  };
+};
+settings = {
+  core = {
+    real_name = "Jeff Hammel";
+    user_name = "jhammel";
+    nick = "jhammel";
+  };
+  "fe-text" = { actlist_sort = "refnum"; };
+};
+hilights = ( { text = "jhammel"; } );
+ignores = ( { mask = "JOINS"; level = "QUITS"; } );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.mailcap	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,89 @@
+text/html; elinks -dump -dump-charset iso-8859-15 -default-mime-type text/html %s; needsterminal; copiousoutput;
+application/msword; antiword %s; copiousoutput;
+application/pdf; pdftotext -layout -enc ASCII7 %s -; copiousoutput;
+application/vnd.ms-excel; /home/jhammel/bin/antixls.sh %s; copiousoutput;
+application/x-annodex;/usr/bin/gxine %s
+video/quicktime;/usr/bin/gxine %s
+video/x-quicktime;/usr/bin/gxine %s
+audio/x-m4a;/usr/bin/gxine %s
+application/x-quicktimeplayer;/usr/bin/gxine %s
+video/mkv;/usr/bin/gxine %s
+video/x-ms-asf;/usr/bin/gxine %s
+video/x-ms-wmv;/usr/bin/gxine %s
+video/x-ms-wma;/usr/bin/gxine %s
+application/vnd.ms-asf;/usr/bin/gxine %s
+application/x-mplayer2;/usr/bin/gxine %s
+video/x-ms-asf-plugin;/usr/bin/gxine %s
+video/x-ms-wvx;/usr/bin/gxine %s
+video/x-ms-wax;/usr/bin/gxine %s
+video/msvideo;/usr/bin/gxine %s
+video/x-msvideo;/usr/bin/gxine %s
+video/x-flic;/usr/bin/gxine %s
+audio/x-basic;/usr/bin/gxine %s
+audio/x-8svx;/usr/bin/gxine %s
+audio/8svx;/usr/bin/gxine %s
+audio/x-16sv;/usr/bin/gxine %s
+audio/168sv;/usr/bin/gxine %s
+image/x-ilbm;/usr/bin/gxine %s
+image/ilbm;/usr/bin/gxine %s
+video/x-anim;/usr/bin/gxine %s
+video/anim;/usr/bin/gxine %s
+image/jpeg;/usr/bin/feh %s
+image/png;/usr/bin/feh %s
+image/x-png;/usr/bin/feh %s
+video/mng;/usr/bin/gxine %s
+video/x-mng;/usr/bin/gxine %s
+audio/x-ogg;/usr/bin/gxine %s
+audio/x-speex;/usr/bin/gxine %s
+audio/x-real-audio;/usr/bin/gxine %s
+video/mpeg;/usr/bin/gxine %s
+video/x-mpeg;/usr/bin/gxine %s
+x-mpegurl;/usr/bin/gxine %s
+application/x-flac;/usr/bin/gxine %s
+
+application/x-ogg;/usr/RealPlayer/realplay %s
+application/ogg;/usr/RealPlayer/realplay %s
+text/vnd.rn-realtext;/usr/RealPlayer/realplay %s
+image/vnd.rn-realpix;/usr/RealPlayer/realplay %s
+application/smil;/usr/RealPlayer/realplay %s
+audio/mp3;/usr/RealPlayer/realplay %s
+audio/x-mp3;/usr/RealPlayer/realplay %s
+audio/mpeg;/usr/RealPlayer/realplay %s
+audio/mpg;/usr/RealPlayer/realplay %s
+audio/x-mpeg;/usr/RealPlayer/realplay %s
+audio/x-mpg;/usr/RealPlayer/realplay %s
+audio/mpegurl;/usr/RealPlayer/realplay %s
+audio/x-mpegurl;/usr/RealPlayer/realplay %s
+audio/wav;/usr/RealPlayer/realplay %s
+audio/x-wav;/usr/RealPlayer/realplay %s
+audio/x-pn-wav;/usr/RealPlayer/realplay %s
+audio/x-pn-windows-acm;/usr/RealPlayer/realplay %s
+audio/x-pn-windows-pcm;/usr/RealPlayer/realplay %s
+application/vnd.rn-realmedia-secure;/usr/RealPlayer/realplay %s
+application/vnd.rn-realaudio-secure;/usr/RealPlayer/realplay %s
+audio/x-realaudio-secure;/usr/RealPlayer/realplay %s
+video/vnd.rn-realvideo-secure;/usr/RealPlayer/realplay %s
+audio/vnd.rn-realaudio;/usr/RealPlayer/realplay %s
+audio/x-realaudio;/usr/RealPlayer/realplay %s
+application/vnd.rn-realmedia;/usr/RealPlayer/realplay %s
+application/vnd.rn-realmedia-vbr;/usr/RealPlayer/realplay %s
+image/vnd.rn-realpix;/usr/RealPlayer/realplay %s
+audio/x-pn-realaudio;/usr/RealPlayer/realplay %s
+video/vnd.rn-realvideo;/usr/RealPlayer/realplay %s
+application/vnd.rn-realsystem-rmj;/usr/RealPlayer/realplay %s
+application/vnd.rn-realsystem-rmx;/usr/RealPlayer/realplay %s
+audio/aac;/usr/RealPlayer/realplay %s
+audio/m4a;/usr/RealPlayer/realplay %s
+audio/mp2;/usr/RealPlayer/realplay %s
+audio/mp1;/usr/RealPlayer/realplay %s
+audio/rn-mpeg;/usr/RealPlayer/realplay %s
+audio/scpls;/usr/RealPlayer/realplay %s
+audio/x-scpls;/usr/RealPlayer/realplay %s
+application/streamingmedia;/usr/RealPlayer/realplay %s
+application/sdp;/usr/RealPlayer/realplay %s
+application/x-sdp;/usr/RealPlayer/realplay %s
+audio/basic;/usr/RealPlayer/realplay %s
+audio/x-pn-au;/usr/RealPlayer/realplay %s
+audio/aiff;/usr/RealPlayer/realplay %s
+audio/x-aiff;/usr/RealPlayer/realplay %s
+audio/x-pn-aiff;/usr/RealPlayer/realplay %s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.mozilla/userContent.css	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,24 @@
+/*
+ * Edit this file and copy it as userContent.css into your
+ * profile-directory/chrome/
+  
+ * XXX this file is deprecated and unused ATM and can probably be removed
+ */
+
+@-moz-document url-prefix(https://mail.google.com),
+               url-prefix(http://mail.google.com)
+{
+  #ds_spam b {
+      visibility: hidden;
+  }
+  
+  #ds_spam b::before {
+      content: "Spam";
+      visibility: visible;
+      font-weight: normal;
+  }
+}
+
+input {
+  background: white;
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.mutt/aliases	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,8 @@
+alias design topp-design-discussion@lists.openplans.org
+alias dev opencore-dev@lists.openplans.org
+alias it xavier@openplans.org, ladorval@gmail.com, rmarianski@openplans.org
+alias ops operations-discussion@lists.openplans.org
+alias ra Rob Miller <robm@openplans.org>
+alias rm Rob Marianski <rmarianski@openplans.org>
+alias ui opencore-ui@lists.openplans.org
+alias wfh wfh@lists.openplans.org
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.muttrc	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,49 @@
+set allow_ansi		# allow ANSI color codes in messages.
+set attach_split	# handle every single attachment instead of concat
+set check_new		  # search for new messages in maildir/MH folders.
+set smtp_url="smtp://jhammel@mail.openplans.org"
+set spoolfile=imaps://mail.openplans.org/INBOX
+set folder=imaps://mail.openplans.org
+set editor="emacs -nw"
+set nomove
+set from="jhammel@openplans.org"
+set hostname="openplans.org"
+set timeout=5
+set mail_check=5
+set sort=reverse-threads
+set sort_aux=date-received
+set pager_stop
+set realname="Jeff Hammel"
+set record="imaps://mail.openplans.org/INBOX.Sent"
+set abort_unmodified=no
+set implicit_autoview
+set markers=no
+
+set use_from=yes
+set use_envelope_from=yes
+
+source ~/.mutt/aliases
+set alias_file=~/.mutt/aliases            # Keep aliases in this file.
+
+color normal default default
+
+macro index d "<delete-message><previous-undeleted>"
+macro pager d "<delete-message><previous-undeleted>"
+
+# Ignore all headers
+ignore *
+
+# Then un-ignore the ones I want to see
+unignore From:
+unignore To:
+unignore Reply-To:
+unignore Subject:
+unignore Date:
+unignore CC:
+unignore BCC:
+
+# Now order the visable header lines
+hdr_order From: Subject: To: CC: BCC: Reply-To: Date:
+
+bind pager < previous-line
+bind pager > next-line
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.smartopen.ini	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,3 @@
+[DEFAULTS]
+handlers = Bugzilla, GoogleMaps, Wikipedia, Wiktionary, FedEx, MercurialRevision, URL, Google
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.subversion_config/config	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,103 @@
+### This file configures various client-side behaviors.
+###
+### The commented-out examples below are intended to demonstrate
+### how to use this file.
+
+### Section for authentication and authorization customizations.
+[auth]
+### Set store-passwords to 'no' to avoid storing passwords in the
+### auth/ area of your config directory.  It defaults to 'yes'.
+### Note that this option only prevents saving of *new* passwords;
+### it doesn't invalidate existing passwords.  (To do that, remove
+### the cache files by hand as described in the Subversion book.)
+# store-passwords = no
+### Set store-auth-creds to 'no' to avoid storing any subversion
+### credentials in the auth/ area of your config directory.
+### It defaults to 'yes'.  Note that this option only prevents
+### saving of *new* credentials;  it doesn't invalidate existing
+### caches.  (To do that, remove the cache files by hand.)
+# store-auth-creds = no
+
+### Section for configuring external helper applications.
+[helpers]
+### Set editor to the command used to invoke your text editor.
+###   This will override the environment variables that Subversion
+###   examines by default to find this information ($EDITOR, 
+###   et al).
+# editor-cmd = editor (vi, emacs, notepad, etc.)
+### Set diff-cmd to the absolute path of your 'diff' program.
+###   This will override the compile-time default, which is to use
+###   Subversion's internal diff implementation.
+# diff-cmd = diff_program (diff, gdiff, etc.)
+### Set diff3-cmd to the absolute path of your 'diff3' program.
+###   This will override the compile-time default, which is to use
+###   Subversion's internal diff3 implementation.
+# diff3-cmd = diff3_program (diff3, gdiff3, etc.)
+### Set diff3-has-program-arg to 'true' or 'yes' if your 'diff3'
+###   program accepts the '--diff-program' option.
+# diff3-has-program-arg = [true | false]
+
+### Section for configuring tunnel agents.
+[tunnels]
+### Configure svn protocol tunnel schemes here.  By default, only
+### the 'ssh' scheme is defined.  You can define other schemes to
+### be used with 'svn+scheme://hostname/path' URLs.  A scheme
+### definition is simply a command, optionally prefixed by an
+### environment variable name which can override the command if it
+### is defined.  The command (or environment variable) may contain
+### arguments, using standard shell quoting for arguments with
+### spaces.  The command will be invoked as:
+###   <command> <hostname> svnserve -t
+### (If the URL includes a username, then the hostname will be
+### passed to the tunnel agent as <user>@<hostname>.)  If the
+### built-in ssh scheme were not predefined, it could be defined
+### as:
+# ssh = $SVN_SSH ssh
+### If you wanted to define a new 'rsh' scheme, to be used with
+### 'svn+rsh:' URLs, you could do so as follows:
+# rsh = rsh
+### Or, if you wanted to specify a full path and arguments:
+# rsh = /path/to/rsh -l myusername
+### On Windows, if you are specifying a full path to a command,
+### use a forward slash (/) or a paired backslash (\\) as the
+### path separator.  A single backslash will be treated as an
+### escape for the following character.
+
+### Section for configuring miscelleneous Subversion options.
+[miscellany]
+### Set global-ignores to a set of whitespace-delimited globs
+### which Subversion will ignore in its 'status' output, and
+### while importing or adding files and directories.
+global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store *.pyc *.egg-info
+### Set log-encoding to the default encoding for log messages
+# log-encoding = latin1
+### Set use-commit-times to make checkout/update/switch/revert
+### put last-committed timestamps on every file touched.
+# use-commit-times = yes
+### Set no-unlock to prevent 'svn commit' from automatically
+### releasing locks on files.
+# no-unlock = yes
+### Set enable-auto-props to 'yes' to enable automatic properties
+### for 'svn add' and 'svn import', it defaults to 'no'.
+### Automatic properties are defined in the section 'auto-props'.
+# enable-auto-props = yes
+
+### Section for configuring automatic properties.
+[auto-props]
+### The format of the entries is:
+###   file-name-pattern = propname[=value][;propname[=value]...]
+### The file-name-pattern can contain wildcards (such as '*' and
+### '?').  All entries which match will be applied to the file.
+### Note that auto-props functionality must be enabled, which
+### is typically done by setting the 'enable-auto-props' option.
+# *.c = svn:eol-style=native
+# *.cpp = svn:eol-style=native
+# *.h = svn:eol-style=native
+# *.dsp = svn:eol-style=CRLF
+# *.dsw = svn:eol-style=CRLF
+# *.sh = svn:eol-style=native;svn:executable
+# *.txt = svn:eol-style=native
+# *.png = svn:mime-type=image/png
+# *.jpg = svn:mime-type=image/jpeg
+# Makefile = svn:eol-style=native
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.xinitrc	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,1 @@
+exec startfluxbox
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.xpdfrc	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,1 @@
+urlCommand "firefox -remote 'openURL(%s)'"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/antixls.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,14 @@
+
+SSCONVERT=`which ssconvert 2> /dev/null`;
+if [ -z "${SSCONVERT}" ]; then
+    echo "${SSCONVERT} not found.  Please install gnumeric.";
+    return 1;
+fi;
+for i in "$@";
+do
+    OUTPUT=${i%.xls}.txt;
+    $SSCONVERT -I Gnumeric_Excel:excel -T Gnumeric_stf:stf_csv "$i" "$OUTPUT" 2>/dev/null;
+    cat "$OUTPUT";
+done
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/clrscr	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,2 @@
+#!/bin/bash
+for i in `seq 1000`; do echo; done 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/desvn.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+desvn() {
+    
+    if [ "$#" == "1" ]
+    then
+        cd $1
+    fi
+
+    svn ls | grep '.*/$' | while read line
+    do
+        desvn $line
+    done
+    rm -rf .svn
+
+    if [ "$#" == "1" ]
+    then
+        cd ..
+    fi
+
+
+}
+
+desvn
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/keyshelp.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# help message for fluxbox keys
+if which gxmessage
+then
+    XMESSAGE="gxmessage -borderless"
+else
+    XMESSAGE=xmessage
+fi
+
+cat <(echo -e "Press <Control>+<Alt>+key to use the commands: \n") <(sed -n '/Control Mod1.*ExecCommand/ {s/Control Mod1//g;s/ExecCommand//g;s/:.*#/:/g;p}' ~/.fluxbox/keys) | ${XMESSAGE} -timeout 20 -nearmouse -file -
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/onelineit.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+sed -e 's/^ *//g' -e 's/ *$//g' | tr '\n' ' '
+echo
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pastebin.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,13 @@
+# all spaces must be converted to '+'
+# all newlines must be converted to %0D%0A
+# this is probably better off converted in a python script
+
+CONTENT_DATA=`python -c "import sys; print '%0D%0A'.join(sys.stdin.read().split('\n'))" | sed 's/ /+/g'`
+
+#echo $CONTENT_DATA
+#CONTENT_DATA=`echo ${CONTENT_DATA} | sed 's/ /+/g'`
+#echo $CONTENT_DATA
+#CONTENT_DATA=`echo ${CONTENT_DATA} | sed 's/$/%0D%0A/g'`
+
+wget --post-data="content=${CONTENT_DATA}&s=Submit+Post&description=&type=1&expiry=&name=" -O- http://www.pastebin.ca/index.php | grep 'meta http-equiv="refresh"' | sed 's/^.*\(http:[^"]*\).*/\1/'
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/swapscreens.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# swap screens between internal laptop monitor and external monitor
+
+INTERNAL="LVDS1"
+EXTERNAL="VGA1"
+INTERNAL_MODE="1366x768"
+EXTERNAL_MODE="1600x1200"
+
+xwininfo -root | grep "geometry $EXTERNAL_MODE"
+if [ $? -eq 0 ]
+then
+ xrandr --output $EXTERNAL --off --output $INTERNAL --mode $INTERNAL_MODE
+else
+ xrandr --output $INTERNAL --off --output $EXTERNAL --mode $EXTERNAL_MODE
+fi
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/venvit.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,36 @@
+#!/bin/bash
+# make a virtualenv for the product
+
+# usage
+if (( $# != 1 ))
+then
+    echo "Usage: $0 <svn-or-hg-location>"
+    exit 0
+fi
+
+# determine name of the package
+NAME=$1
+for i in /trunk /branches /tag
+do
+    NAME=${NAME%%$i*}
+done
+NAME=${NAME%%/} # remove trailing slash
+NAME=${NAME##*/}
+
+if svn info $1 2> /dev/null
+then
+    CHECKOUT="svn co"
+else
+    CHECKOUT="hg clone"
+fi
+
+# create a virtualenv and install the software
+VIRTUAL_ENV_LOCATION="${HOME}/virtualenv/virtualenv.py"
+python ${VIRTUAL_ENV_LOCATION} ${NAME}
+cd ${NAME}
+source bin/activate
+mkdir src/
+cd src/
+$CHECKOUT $1 ${NAME}
+cd ${NAME}
+python setup.py develop
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/vpn-mpt.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd /home/jhammel/mozilla/vpn/MPT-vpn/
+sudo openvpn --daemon --config Mozilla-MPT.ovpn --script-security 3
+tail -f /var/log/syslog
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/vpn-office.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd /home/jhammel/mozilla/vpn/Office-vpn/
+sudo openvpn --daemon --config Mozilla-MV-Office.ovpn --script-security 3
+tail -f /var/log/syslog
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/wgrep.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+import sys
+import urlparse
+import urllib2
+import tempfile
+import shutil
+import subprocess
+
+def usage():
+    print 'Usage: %s <url> <pattern>' % sys.argv[0]
+    sys.exit(0)
+
+def geturl(origurl):
+    # get the url
+    url = urlparse.urlsplit(origurl)
+    if not url[0]:
+        url = urlparse.urlsplit('http://%s' % origurl)
+    return url
+
+if __name__ == '__main__':
+    if len(sys.argv[1:]) != 2:
+        usage()
+    urlparts = geturl(sys.argv[1])
+    url = urlparse.urlunsplit(urlparts)
+
+    # ensure the url is openable
+    try:
+        u = urllib2.urlopen(url)
+    except urllib2.HTTPError, e:
+        print '%s\n%s' % (url, e)
+        sys.exit(1)
+
+    thedir = tempfile.mkdtemp()
+
+    # wget the files
+    wget = subprocess.Popen(['wget', '-r', '-l0',
+                             '--no-parent',
+                             '--no-check-certificate',
+                             '-P', thedir,
+                             u.url],
+                            stdout = subprocess.PIPE,
+                            stderr = subprocess.PIPE,
+                            )
+    out, err = wget.communicate()
+    code = wget.returncode
+    if code:
+        sys.exit(code)
+
+    # do da grep
+    grep = subprocess.Popen(['grep', '-r', '-l', 
+                             sys.argv[2], 
+                             thedir],
+                            stdout = subprocess.PIPE,
+                            stderr = subprocess.PIPE,
+                            )
+    out, err = grep.communicate()
+    for i in out.split('\n'):
+        print i.replace('%s/' % thedir, '%s://' % urlparts[0], 1)
+
+    destructive = True
+    if destructive:
+        shutil.rmtree(thedir)
+    else:
+        print thedir
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/yt2mp3.sh	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+YOUTUBEDL=/home/jhammel/music/youtube-dl
+
+URL=$1
+TITLE=$($YOUTUBEDL --get-title $URL)
+EXT=mp4
+$YOUTUBEDL -i -r 50k $URL -o "%(title)s.${EXT}" 
+rm -f audiodump.wav
+mplayer -vo null -ao pcm "$TITLE.$EXT"
+lame -q 2 audiodump.wav "$TITLE.mp3"
+#rm "$TITLE.$EXT"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/a8e.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import sys
+import urllib2
+
+def a8e(text):
+  text = text.split()
+  retval = []
+  for word in text:
+    if len(word) < 4:
+      retval.append(word)
+    else:
+      retval.append(word[0] + '%d' % (len(word) - 2) + word[-1])
+  return ' '.join(retval)
+
+def main(args=sys.argv[1:]):
+  if len(args) == 1 and (args[0].startswith('http://')
+                         or args[0].startswith('https://')):
+    text = urllib2.urlopen(args[0]).read()
+  else:
+    text = ' '.join(args)
+  # TODO: read from stdin if no args
+  print a8e(text)
+
+if __name__ == '__main__':
+  main()
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/abstract.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,39 @@
+
+def abstractmethod(method):
+    line = method.func_code.co_firstlineno
+    filename = method.func_code.co_filename
+    def not_implemented(*args, **kwargs):
+        raise NotImplementedError('Abstract method %s at File "%s", line %s should be implemented by a concrete class' % (repr(method), filename, line))
+    return not_implemented
+
+class AbstractBaseClass(object):
+
+    @abstractmethod
+    def foo(self, arg):
+        """foo does such and such"""
+
+    @abstractmethod
+    def bar(self):
+        """bar does something else"""
+
+class ConcreteClass(AbstractBaseClass):
+
+    def foo(self, arg):
+        print 'hello'
+
+if __name__ == '__main__':
+    c = ConcreteClass()
+    c.foo(1)
+    a = AbstractBaseClass()
+    try:
+        a.foo(1)
+    except NotImplementedError, e:
+        print e
+    try:
+        a.bar()
+    except NotImplementedError, e:
+        print e
+    c.foo(1)
+    a.foo(1)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/accentuate.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import random
+
+mapping = {'a': ['Ȁ', 'ȁ', 'à', 'Ѧ', 'ª', 'Å', 'Ą', 'ᥠ', 'Ӓ', 'ӑ', 'ά'],
+           'b': ['Б', 'ß', 'ᛒ', 'ᙘ', '฿', 'ط', 'Ҍ','ъ', 'β', 'Ƀ'],
+           'c': ['ç', 'ᥴ', 'ᕩ', 'උ', 'ʗ'],
+           'd': ['Ð', 'đ', 'ժ', 'Ժ', 'Ԁ', 'ɗ', 'ȡ'],
+           'e': ['ȅ', 'Ё', 'Є', 'Ę', 'ᣰ', 'ع', 'Ҿ', 'Ҽ', 'ξ', 'έ', 'ɇ', 'Ȼ'],
+           'f': ['ᚫ', 'ഽ', 'ߓ', 'Ғ', 'ғ', 'ϝ'],
+           'g': ['Ꮆ', 'Ᏻ', 'ສ', 'ອ', 'ʛ', 'ɠ', 'ǵ', 'Ǵ', 'Ǥ', 'ğ'],
+           'h': ['Ꮵ', 'ዝ', 'ߚ', 'ի', 'Ӊ', 'Ӈ', 'ӈ', 'Һ', 'Ҥ', 'ҥ', 'ђ', 'Ϧ'],
+           'i': ['ו', 'ḯ', 'í', 'ї', 'ί', 'Ϊ', 'Ί', 'ɨ'],
+           'j': ['ᒚ', 'ڷ', '˩', 'ʲ', 'ʝ', 'ȷ', 'ǰ'],
+           'k': ['ԟ', 'Ԟ', 'Ӄ', 'Ҡ', 'Ҝ', 'ќ', 'ʞ'],
+           'l': ['£', '₤', 'ᥧ', 'ட', '˪', 'ʟ', 'ᶅ'],
+           'm': ['ញ', 'ᛖ', 'ጢ', 'ᆻ', 'ӎ', 'Ӎ',],
+           'n': ['И', 'Й', 'א', 'ᥟ', 'ᜤ', '୩', 'Ӥ', 'Ҋ', 'η', 'ή'],
+           'o': ['ổ', 'ȍ', 'Ѳ', '๏', 'Ӫ', 'ό', 'Ό', '˚', 'ʘ', 'Ȱ'],
+           'p': ['Ⴒ', 'թ', 'Ҏ', 'ҏ', 'ρ', 'Ƿ'],
+           'q': ['գ', 'ʠ', 'ɖ'],
+           'r': ['ᣨ', 'ჩ', 'я', 'Ɍ', 'ȓ', 'Ȓ', 'ȑ', 'Ȑ'],
+           's': ['∫', '§', 'ᛊ', 'Ꮥ', 'క', 'ˢ', 'ȿ', 'ș', 'ᶘ'],
+           't': ['Ṱ', 'ל', 'ᛠ', 'ᚁ', 'ፕ', 'Է', 'Ե', 'Ҭ', 'Ϯ', 'ʈ', 'Ⱦ', 'ȶ'],
+           'u': ['ṹ', 'ᥩ', 'ᥳ', 'ப', 'ն', 'Մ', 'μ', 'ǚ',],
+           'v': ['Ѵ', 'ᜥ', 'Ꮴ', 'Ѷ', 'ν', 'ΰ'],
+           'w': ['Ѡ', 'Щ', 'ש', 'ឃ', 'ᜦ', 'Ꮤ', 'Ꮿ', 'ϣ'],
+           'x': ['χ', 'Ӽ', 'ӽ', 'Ҳ', 'ҳ', 'Ϫ', 'ˣ'],
+           'y': ['Ꭹ', 'Ꮍ','Ⴤ', 'Ӱ', 'Ӌ', 'ψ', 'Ϋ', 'Ύ', 'Ȳ'],
+           'z': ['ź', 'ʐ', 'ʑ', 'ɀ', 'Ȥ', 'ȥ'],
+           }
+
+if __name__ == '__main__':
+    import sys
+    arg = ' '.join(sys.argv[1:])
+    if not arg:
+        arg = sys.stdin.read()
+    retval = []
+    for letter in arg:
+        if letter.lower() in mapping:
+            retval.append(random.sample(mapping[letter.lower()], 1)[0])
+        else:
+            retval.append(letter)
+    print ''.join(retval)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/address.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+import sys
+from states import *
+
+def validate_zipcode(zip, zip4=None):
+    """ validate a zipcode"""
+    
+    if not zip:
+        # a non-existant zip-code is a valid zipcode
+        # ... i think....
+        return True 
+
+    if '-' in zip: # in this case, split zip into zip5 + zip4
+        zip, zip4 = zip.split('-')
+
+    zdict = { 'zip5': zip, 'zip4': zip4 }
+        
+    # if the 4-digit extension exists, add it to zip
+    if zip4:
+        zip += '-' + zip4
+
+    # validate zip code format
+    for i in 5, 4:
+        zstring = 'zip' + str(i)
+        z = zdict.get(zstring, '')
+        if z:
+            if (not z.isdigit()) or (len(z) != i):
+                return False
+
+    return zip
+
+def normalizeaddress(query):
+    """ returns normalize address, if it is an address """
+
+    # normalize the address
+    query = ','.join([i.strip() for i in query.split('\n')])
+    querylist = [i.strip() for i in query.split(',')]
+    
+    lastentry = querylist[-1]
+    
+    if lastentry[-1].isdigit():
+        # it must be a zip code
+        if lastentry[1].isalpha():
+            querylist = querylist[:-1] + lastentry.split()
+        if not validate_zipcode(querylist[-1]):
+            return False
+        state = querylist[-2]
+    else:
+        state = querylist[-1]
+
+    if not getstate(state):
+        return False
+
+    return ', '.join(querylist)
+
+def address(query):
+    """ 
+    format an address 
+    -- query should be a string
+    """
+    
+if __name__ == '__main__':
+    i = normalizeaddress(' '.join(sys.argv[1:]))
+    if i:
+        print i
+    else:
+        print 'Not an address'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/anagram.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+import os
+
+dictionary = []
+
+def read_dictionary(f):
+    for name in f.readlines():
+        name = name.strip('\n')
+        word = ''.join(name.split()).lower()
+        dictionary.append(word)
+
+def is_in(string1, string2):
+
+    string2 = list(string2)
+
+    try:
+        for i in string1:
+            string2.remove(i)
+    except ValueError:
+        return None
+
+    return ''.join(string2)
+
+def anagramize(theword, wordlist, level=0):
+
+    if 0:
+        print '%s%s : %s' % ('-' * level, theword, wordlist)
+
+    anagrams = []
+
+    # start the search with a new word
+    for index in range(len(wordlist)):
+        word = wordlist[index]
+        subword = is_in(word, theword)
+        if subword == '':
+            anagrams.append(word)
+            continue
+
+        if subword is None:
+            continue
+
+
+        sublist = [ i for i in wordlist[index:]
+                    if is_in(i, subword) is not None ]
+        subgram = anagramize(subword, sublist, level+1)
+
+        if subgram is not None:
+            anagrams += [ ' '.join((word, i)) for i in subgram ]
+
+    if 0:
+        print '%s%s returning %s' % ('-' * level, theword, anagrams)
+
+    if anagrams:
+        return anagrams
+    return None
+    
+if __name__ == '__main__':
+    import sys
+    from optparse import OptionParser
+
+    parser = OptionParser()
+    parser.add_option("-f", dest="filename", help="dictionary to read",
+                      default='')
+    (options, args) = parser.parse_args()
+
+    if not os.path.exists(options.filename):
+
+        dicts = [ '/home/jhammel/docs/dict.txt',
+                  '/usr/share/dict/cracklib-small',
+                  '/usr/share/dict/american-english' ]
+
+        for i in dicts:
+            if os.path.exists(i):
+                options.filename = i
+                break
+        else:
+            print 'Dictionary not found'
+            parser.print_help()
+            sys.exit(1)
+
+    if not args:
+        print 'please provide an anagram'
+        sys.exit(0)
+
+    f = file(options.filename, 'r')
+    read_dictionary(f)
+
+    # XXX could cleanup
+    anagram = ' '.join(args)
+    anagram = ''.join(anagram.split()).lower()
+
+    # don't use letter names
+    dictionary = [ i for i in dictionary if (len(i) > 1) or i in 'ai' ]
+
+    wordlist = [ i for i in dictionary
+                 if i and is_in(i, anagram) is not None ]
+    
+    anagrams = anagramize(anagram, wordlist)
+
+    if anagrams:
+        print '\n'.join(anagrams)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ascii.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,66 @@
+#!/usr/bin/env python 
+# extended ascii chart
+# 2010 openuniverse
+#
+# license: cc0 http://creativecommons.org/publicdomain/zero/1.0/
+
+print " " , "0 1 2 3 4 5 6 7 8 9 a b c d e f"
+print "0" , " " , u"\u263a", u"\u263b", u"\u2665", 
+print u"\u2666", u"\u2663", u"\u2660", u"\u2022", 
+print u"\u25d8", u"\u25cb", u"\u25d9", u"\u2642", 
+print u"\u2640", u"\u266a", u"\u266b", u"\u263c"
+
+print "1" , u"\u25ba", u"\u25c4", u"\u2195", u"\u203c", 
+print u"\u00b6", u"\u00a7", u"\u25ac", u"\u21a8",
+print u"\u2191", u"\u2193", u"\u2192", u"\u2190", 
+print u"\u221f", u"\u2194", u"\u25b2", u"\u25bc"
+
+x = 1
+y = 2
+print "2" , 
+for p in range(32, 127):
+    print chr(p),
+    x += 1
+    if x > 16: print ; x = 1 ; y += 1 ; print y,
+
+print u"\u2302"
+
+print "8" , u"\u00c7", u"\u00fc", u"\u00e9", u"\u00e2",
+print u"\u00e4", u"\u00e0", u"\u00e5", u"\u00e7", 
+print u"\u00ea", u"\u00eb", u"\u00e8", u"\u00ef", 
+print u"\u00ee", u"\u00ec", u"\u00c4", u"\u00c5" 
+
+print "9" , u"\u00c9", u"\u00e6", u"\u00c6", u"\u00f4", 
+print u"\u00f6", u"\u00f2", u"\u00fb", u"\u00f9", 
+print u"\u00ff", u"\u00d6", u"\u00dc", u"\u00a2", 
+print u"\u00a3", u"\u00a5", u"\u20a7", u"\u0192" 
+
+print "a" , u"\u00e1", u"\u00ed", u"\u00f3", u"\u00fa", 
+print u"\u00f1", u"\u00d1", u"\u00aa", u"\u00ba", 
+print u"\u00bf", u"\u2310", u"\u00ac", u"\u00bd", 
+print u"\u00bc", u"\u00a1", u"\u00ab", u"\u00bb" 
+
+print "b" , u"\u2591", u"\u2592", u"\u2593", u"\u2502", 
+print u"\u2524", u"\u2561", u"\u2562", u"\u2556", 
+print u"\u2555", u"\u2563", u"\u2551", u"\u2557", 
+print u"\u255d", u"\u255c", u"\u255b", u"\u2510" 
+
+print "c" , u"\u2514", u"\u2534", u"\u252c", u"\u251c", 
+print u"\u2500", u"\u253c", u"\u255e", u"\u255f", 
+print u"\u255a", u"\u2554", u"\u2569", u"\u2566", 
+print u"\u2560", u"\u2550", u"\u256c", u"\u2567" 
+
+print "d" , u"\u2568", u"\u2564", u"\u2565", u"\u2559", 
+print u"\u2558", u"\u2552", u"\u2553", u"\u256b", 
+print u"\u256a", u"\u2518", u"\u250c", u"\u2588", 
+print u"\u2584", u"\u258c", u"\u2590", u"\u2580" 
+
+print "e", u"\u03b1", u"\u00df", u"\u0393", u"\u03c0", 
+print u"\u03a3", u"\u03c3", u"\u03bc", u"\u03c4", 
+print u"\u03a6", u"\u0398", u"\u03a9", u"\u03b4", 
+print u"\u221e", u"\u03c6", u"\u03b5", u"\u2229" 
+
+print "f" , u"\u2261", u"\u00b1", u"\u2265", u"\u2264", 
+print u"\u2320", u"\u2321", u"\u00f7", u"\u2248", 
+print u"\u00b0", u"\u2219", u"\u00b7", u"\u221a", 
+print u"\u207f", u"\u00b2", u"\u25a0"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/aspects.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,18 @@
+class MakePythonLikeJavascript(object):
+    def __getattr__(self, name):
+        return undefined
+
+class undefined(MakePythonLikeJavascript):
+    def __nonzero__(self):
+        return False
+    def __str__(self):
+        return 'undefined'
+    __repr__ = __str__
+undefined = undefined() # singleton
+
+if __name__ == '__main__':
+    foo = MakePythonLikeJavascript()
+    foo.bar = 5
+    print foo.bar
+    print foo.fleem
+    print foo.fleem.flarg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cgiescape.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+import sys
+import cgi
+
+print cgi.escape(sys.stdin.read())
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cheeseshop.txt	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,103 @@
+Making your own cheeseshop
+
+It is a common misconception that the cheeseshop (pypi.python.org) is
+*the* place to go for python packages.  This is only true by
+convention.  I won't go into the history of
+distutils/setuptools/distribute/pip packaging fiasco.  Suffice it to
+say that (I hope) things are slowly converging and that both pip and
+easy_install, the two major ways of installing python software, both
+support a -i option to specify the URL of the package index (which is,
+by default http://pypi.python.org/simple).
+
+In its base form, easy_install and pip just crawl links.  You look at
+the base URL (see above) /<package>/<package>-<version>-<extension>
+and download this, unzip, run `python setup.py install` on it and
+you're done.  So if you want to make a cheeseshop, there are two
+essential tasks:
+
+ 1. Generating e.g. tarballs for a package and all of its dependencies
+ 2. Putting these tarballs on the web with some appropriate parent
+    directory
+
+Not rocket science...barely computer science, really.
+
+For generating packages and their dependencies, I used pip.  pip is
+really great for this.  I only used the command line interface, though
+if I was smarter, I probably should have looked at the API and figured
+out what pip is doing internally and I could have avoided a few
+steps.  Basically, using the --no-install option downloads the package
+and its dependencies for you and lets you do what you want with it. 
+
+I made a program for this, see http://k0s.org/hg/stampit . It's a
+python package, but it doesn't really do anything python-y.  It was
+just easier to write than a shell script for my purposes.  Basically
+it makes a virtualenv (probably overkill already), downloads the
+packages and their dependencies into it, runs `python setup.py sdist`
+on each package so that you have a source distribution, and prints out
+the location of each tarball.
+
+The source distribution is very important as we want packages that
+will work independent of platform.  These should.  If they don't, we
+can make them.
+
+So problem #1 solved.  Let's move on to problem #2: putting them
+somewhere on the web.
+
+Mozilla is so kind as to have given me a URL space on
+people.mozilla.org. Since easy_install and pip are really dumb and
+basically just crawl links, and since Apache is smart enough to
+generate index pages for directories that don't have index.html files
+in them, the hard part is already solved.  I will note that
+people.mozilla.org is not intended as a permanant place for these
+tarballs, just an interim instance until we decide where we really
+want to put them.
+
+Since I like to write scripts, I wrote a script that will run stampit
+and copy the resulting tarballs to a place appropriate to a
+cheeseshop.  You can see the code here:
+
+http://k0s.org/mozilla/package-it.sh
+
+The variables are pretty specialized to my setup, but of course that's fixable.
+
+Does it really work?
+
+Yes!  You can try it for yourself. Try:
+
+``easy_install -i http://people.mozilla.org/~jhammel/packages/ mozmill``
+
+Watch where the links come from.  Surprise!  They're all from
+http://people.mozilla.org/~jhammel/packages/ !
+I would *highly advise* doing this (and just about everything else in
+python) in a virtualenv so that you don't pollute your global
+site-packages.
+
+Why am I doing this?
+
+The Firefox buildslaves are supposed to fetch data only from mozilla
+URLs for stability.  So, if python packages need to be installed, they
+need to be available internal to Mozilla.  If a package didn't have
+dependencies, then this is a no-brainer.  But packages do have
+dependencies. Mozmill depends jsbridge, simplejson, and mozrunner.
+While this is a lot of work for just one package, if we want more
+python stuff in our buildbot tests, we'll need to do more of this, and
+I'd rather have a good solid methodology to do so.  I also imagine
+this growing as a place to put all of our python packages for internal
+Mozilla needs.
+
+I will note that I did this in a few hours from basically knowing the
+problem space but never having actually done it.  None of this is
+supposed to be a clean and polished solution.  But really, its not
+bad.  We did something similar but less functional at my last job, The
+Open Planning Project, for similar reasons, so its not like I tackled
+this blindly. This is not as fully functional as the cheeseshop.  A maintainer
+needs to run the package-it.sh script for each package (and its deps)
+they want installed.  There's no accounts or any of the other features
+the cheeseshop has.  But for a simple prototype and a way to move the
+discussion forward, its actually not that bad of a solution.  There
+are more robust ways of really doing the cheeseshop, such as
+http://github.com/ask/chishop , but for a package dumping ground, this
+solution works and its really not even that hacky (in my opinion
+anyway).
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/clearsilver.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,221 @@
+#!/usr/bin/python
+
+import sys, os
+
+KEY_RETURN="""
+"""
+
+class ClearSilver(object):
+    """
+    a blatant rip-off of quicksilver/katapult
+    """
+    def __init__(self, startswith=''):
+        self.matches = {}
+        self.sortable = True
+        if startswith:
+            self.build_matches(startswith)
+
+    def returnmatch(self):
+        keys = self.matches.keys()
+        if len(keys) == 1:
+            return keys[0], self.matches[keys[0]]
+        if self.sortable:
+            keys.sort()
+        return keys
+
+    def find_matches(self, startswith):
+        nixlist = []
+        for i in self.matches:
+            if not i.startswith(startswith):
+                nixlist.append(i)
+
+        for i in nixlist:
+            self.matches.pop(i)
+            
+        return self.returnmatch()
+        
+
+class PATHsilver(ClearSilver):    
+
+    def build_matches(self, startswith=''):
+        path = os.environ['PATH'].split(':')
+        path.reverse()
+        for directory in path:
+            try:
+                for binary in os.listdir(directory):
+                    if binary.startswith(startswith):
+                        self.matches[binary] = '/'.join((directory,binary))
+            except OSError:  # directory not found
+                continue
+        return self.returnmatch()
+
+
+    def exec_match(self, key):
+        item = self.matches[key]
+        os.execl(item, item)
+      
+
+class Wordsilver(ClearSilver):
+    dictfile = '/usr/share/dict/cracklib-small'
+    
+    def build_matches(self, startswith=''):
+        f = file(self.dictfile, 'r')
+        for i in f.readlines():
+            if i.startswith(startswith):
+                i = i.rstrip('\r\n')
+                self.matches[i] = i
+        return self.returnmatch()
+
+    def exec_match(self, key):        
+        item = self.matches[key]
+        print key
+
+class BookmarkSilver(ClearSilver):
+    def __init__(self, startswith=''):
+        ClearSilver.__init__(self)
+        self.sortable = False
+        if startswith:
+            self.build_matches(startswith)
+            
+    def add_url(self, i, startswith):
+        delimiter = '//'
+        j = i[i.index(delimiter) + len(delimiter):]
+        j = j.rstrip('/')
+        if j.startswith(startswith):
+            self.matches[j] = i
+            j = j.strip('w.')
+        if j.startswith(startswith):
+            self.matches[j] = i
+            
+    def build_matches(self, startswith=''):
+        # find the firefox files
+        firefoxdir = '/'.join((os.environ['HOME'], '.mozilla', 'firefox'))
+        profile = file('/'.join((firefoxdir, 'profiles.ini')), 'r').readlines()
+        profile = [i.rstrip('\n\r \t')  for i in profile]
+        index = profile.index('Name=default')
+        delimiter = 'Path='
+        while 1:
+            index += 1
+            if profile[index].startswith(delimiter):
+                profile = '/'.join((firefoxdir, profile[index][len(delimiter):]))
+                break
+        bookmarks = '/'.join((profile, 'bookmarks.html'))
+        history = '/'.join((profile, 'history.dat'))
+        import re
+        history = file(history, 'r').read()
+        history = re.findall('http.*//.*\)', history)
+        history.reverse()
+        for i in history:
+            i = i[:i.index(')')]
+            self.add_url(i, startswith)
+
+        bookmarks = file(bookmarks, 'r').read()
+        bookmarks = re.findall('"http.*//.*"', bookmarks)
+
+        for i in bookmarks:
+            i = i.strip('"')
+            i = i[:i.index('"')]
+            self.add_url(i, startswith)
+
+        return self.returnmatch()
+
+    def exec_match(self, key):
+        item = self.matches[key]
+        
+        os.system("firefox " + item)
+
+if __name__ == '__main__':
+
+    matcher_type = 'PATHsilver'
+
+    # parse options
+    options = { 'D' : 'Wordsilver', 'H' : 'BookmarkSilver' }
+    for i in sys.argv[1:]:
+        i = i.strip('-')
+        if options.has_key(i):
+            matcher_type = options[i]
+
+    # init the 'GUI'
+    import curses
+    stdscr = curses.initscr()
+    curses.noecho()
+    curses.cbreak()
+    stdscr.keypad(1)
+
+    try:
+# XXX should include colors at some point -- not right now, though
+#        curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
+
+        c = ''
+        matcher = None
+        matches = None
+        entered=''
+        
+        while 1:
+            y, x = stdscr.getmaxyx()
+            stdscr.refresh()
+            c = stdscr.getch()
+            stdscr.erase()
+
+            # handle backspaces 
+            if c == curses.KEY_BACKSPACE or c == 127:
+                entered = entered[:-1]
+                matcher = None
+                matches = None
+            else:
+                
+                try:
+                    c = chr(c)
+                except ValueError:
+                    continue
+                
+                if c == KEY_RETURN:
+                    break
+            
+                entered += c
+                
+            if not matcher:
+                matcher = eval(matcher_type + "()")
+                matches = matcher.build_matches(entered)
+            else:
+                
+                if c.isdigit() and int(c) < min(10, len(matches)):        
+                    for i in matches:
+                        if i.startswith(entered):
+                            break
+                    else:
+                        matches = matches[int(c):int(c)+1]
+                        break
+
+                matches = matcher.find_matches(entered)
+
+                
+            if isinstance(matches, list):
+                i=1
+                for match in matches:
+                    if i >= y: continue
+                    if i <= 10:
+                        numstr = " :" + str(i-1)
+                    else:
+                        numstr = ""
+                    stdscr.addstr(i,0, match + numstr)
+                    i += 1
+                stdscr.addstr(0,0, entered)
+
+                if matches: stdscr.addstr(1,0, matches[0] + " :0")
+            else:
+                stdscr.addstr(0,0,entered + " -> " + matches[1])
+
+    finally:
+        # 'GUI' cleanup
+        curses.nocbreak()
+        stdscr.keypad(0)
+        curses.echo()
+        curses.endwin()
+        
+        # execute the program (if found)
+        if not matches:
+            sys.exit(1)
+        matcher.exec_match(matches[0])
+                    
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cli.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+"""
+program illustrating command line in the form of
+``--option foo`` or ``--option=foo`` goes to a (key,value) paid
+and ``-tag`` gets appended to a list.  Further options go to a further list::
+
+    >>> main(['-foo', '--bar=fleem', 'baz'])
+    (['foo'], {'bar': 'fleem'}, ['baz'])
+"""
+
+import sys
+
+class ParserError(Exception):
+  """error for exceptions while parsing the command line"""
+
+def main(_args=sys.argv[1:]):
+
+  # return values
+  _dict = {}
+  tags = []
+  args = []
+
+  # parse the arguments
+  key = None
+  for arg in _args:
+    if arg.startswith('---'):
+      raise ParserError("arguments should start with '-' or '--' only")
+    elif arg.startswith('--'):
+      if key:
+        raise ParserError("Key %s still open" % key)
+      key = arg[2:]
+      if '=' in key:
+        key, value = key.split('=', 1)
+        _dict[key] = value
+        key = None
+        continue
+    elif arg.startswith('-'):
+      if key:
+        raise ParserError("Key %s still open" % key)
+      tags.append(arg[1:])
+      continue
+    else:
+      if key:
+        _dict[key] = arg
+        continue
+      args.append(arg)
+
+  # return values
+  return (_dict, tags, args)
+
+if __name__ == '__main__':
+  try:
+    _dict, tags, args = main()
+  except ParserError, e:
+    import pdb; pdb.set_trace() # for debugging
+  print _dict
+  print tags
+  print args
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/closure.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,4 @@
+directory = 'foo'
+bar = lambda: directory
+directory = 'fleem'
+print bar()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/dictarg.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+import sys
+
+def dictarg(adict, argv=sys.argv[1:]):
+
+    shopts = {}
+    
+    # build list of keys
+    for i in adict.keys():
+        for j in i:
+            s = str(j)
+            if len(s) == 1:
+                if shopts.has_key(s):
+                    continue
+                shopts[s] = i
+                break
+        else:
+            print >> sys.stderr, "dictarg: couldn't generate key for '%s'" % i
+            sys.exit(1)
+
+    optstring = "?"
+    for i in shopts.keys():
+        optstring += i + ':' # all these options should have arguments
+    
+    # look for command line args
+    import getopt
+
+    opts, args = getopt.getopt(argv, optstring)
+
+    if ('-?', '') in opts:
+        print 'Options:'
+        for i in shopts:
+            print '-%s %s [%s]' % (i, shopts[i], adict[shopts[i]])
+        sys.exit(0)
+        
+    for o, v in opts:
+        o = o[1:] # cut off the dash
+        adict[shopts[o]] = v
+
+# test if invoked from command line
+if __name__ == '__main__':
+    adict = {}
+    for i in sys.argv:
+        adict[i] = len(i)
+
+    # print the help
+    dictarg(adict, ['-?'])
+
+    # test functionality
+    print 'Enter test arguments: ',
+    line = sys.stdin.readline()[:-1].split(' ')
+    dictarg(adict, line)
+    print adict
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/dictify.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+divider = ':'
+
+def dictify(string):
+    lines = [ i.strip() for i in string.split('\n') if i.strip() ]
+    return dict([i.split(divider,1) for i in lines 
+                 if len(i.split(divider,1)) == 2])
+    
+if __name__ == '__main__':
+    import sys
+    feh = sys.stdin.read()
+    thedict = dictify(feh)
+    if sys.argv[1:]:
+        for i in sys.argv[1:]:
+            if thedict.has_key(i):
+                print thedict[i]
+    else:
+        print thedict
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/dotpath.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+import sys
+
+def filename(dotpath):
+    path = dotpath.split('.')
+    while path:
+        try:
+            module = __import__('.'.join(path))
+            return module.__file__.rstrip('c')
+        except ImportError:
+            path.pop()
+
+def main(args=sys.argv[1:]):
+    for arg in args:
+        try:
+            _filename = filename(arg)
+        except Exception, e:
+            print e
+            continue
+        print _filename
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/fireonce.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,15 @@
+class fireonce(object):
+    def __init__(self, func):
+        self.func = func
+    def __call__(self, *args, **kwargs):
+        if not self.func:
+            return None
+        retval = self.func(*args, **kwargs)
+        self.func = None
+
+@fireonce
+def foo(x):
+    print x
+    
+foo('bar')
+foo('fleem') # not printed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/hexify.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+import sys
+print ''.join([ '%'+ hex(ord(i))[-2:] for i in ' '.join(sys.argv[1:]) ])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/hg-merge.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+"""
+merge mercurial repositories
+
+Example:
+hg-merge.py --master http://hg.mozilla.org/build/talos http://hg.mozilla.org/build/pageloader#talos/pageloader
+"""
+
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import urlparse
+try:
+    from subprocess import check_call as call
+except:
+    from subprocess import call
+
+def url2filename(url):
+    """gets a filename from a url"""
+    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
+    path = path.rstrip('/')
+    assert path and '/' in path
+    return path.split('/')[-1]
+
+def manifest(hgrepo):
+    """manifest of a local hg repository"""
+    process = subprocess.Popen(['hg', 'manifest'], cwd=hgrepo, stdout=subprocess.PIPE)
+    stdout, stderr = process.communicate()
+    assert not process.returncode
+    manifest = stdout.strip().splitlines()
+    return set(manifest)
+
+def merge(hgroot, repo, subpath=None):
+    """merge repo to hgroot at subpath (None for repository root)"""
+
+    # get a manifest of the current repository
+    root_manifest = manifest(hgroot)
+    toplevel_contents = os.listdir(hgroot)
+
+    # staging area
+    tempdir = tempfile.mkdtemp()
+    fd, tmpfile = tempfile.mkstemp()
+    os.close(fd)
+
+    exception = None
+    try:
+
+        # clone the repository to be merged in
+        call(['hg', 'clone', repo, tempdir])
+
+        # check manifest for conflicts
+        repo_manifest = manifest(tempdir)
+        assert repo_manifest, "Empty repository: %s" % repo
+        intersection = root_manifest.intersection(repo_manifest)
+        assert not intersection, "Overlap between %s and %s: %s" % (hgroot, repo, intersection)
+
+        # create a bundle
+        call(['hg', 'bundle', tmpfile, '--all'], cwd=tempdir)
+
+        # apply the bundle
+        call(['hg', 'unbundle', tmpfile], cwd=hgroot)
+        call(['hg', 'merge'], cwd=hgroot)
+
+        if subpath:
+            # move the new files to their new locations
+            for item in repo_manifest:
+                path = os.path.join(subpath, item)
+                fullpath = os.path.join(hgroot, path)
+                assert not os.path.exists(fullpath), "%s already exists" % fullpath
+                subdirectory = os.path.dirname(fullpath)
+                if not os.path.exists(subdirectory):
+                    os.makedirs(subdirectory)
+                call(['hg', 'mv', item, path], cwd=hgroot)
+            call(['hg', 'commit', '-m', 'merge %s to %s' % (repo, subpath)], cwd=hgroot)
+        else:
+            call(['hg', 'commit', '-m', 'merge in %s' % repo], cwd=hgroot)
+
+    except Exception, exception:
+        pass # reraise on cleanup
+
+    # cleanup
+    shutil.rmtree(tempdir)
+    os.remove(tmpfile)
+    if exception is not None:
+        raise exception
+
+def main(args=sys.argv[1:]):
+
+    # parse command line options
+    usage = "%prog [options] http://hg.example.com/repository/path#destination/path [...]"
+    parser = optparse.OptionParser(usage=usage, description=__doc__)
+    parser.add_option('-m', '--master', dest='master',
+                      help="use this as the master repository (new clone, otherwise use CWD)")
+    options, args = parser.parse_args(args)
+    if not args:
+        parser.print_help()
+        parser.exit()
+
+    if options.master:
+        # clone the new repository
+        directory = url2filename(options.master)
+        if os.path.exists(directory):
+            shutil.rmtree(directory)
+        call(['hg', 'clone', options.master])
+        hgroot = os.path.join(os.getcwd(), directory)
+    else:
+        # get the root of the repository
+        process = subprocess.Popen(['hg', 'root'], stdout=subprocess.PIPE)
+        hgroot, stderr = process.communicate()
+        hgroot = hgroot.strip()
+        if process.returncode:
+            sys.exit(1)
+    assert os.path.exists(hgroot) and os.path.isdir(hgroot), "%s not found" % hgroot
+
+    # get the other repos to add
+    for repo in args:
+        subpath = None
+        if '#' in repo:
+            repo, subpath = repo.rsplit('#', 1)
+        merge(hgroot, repo, subpath)
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/html2flux.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+import sys
+from lxml import etree
+
+from lsex import lsex # local import
+executables = set([i.rsplit('/', 1)[-1] for i in lsex() ])
+
+def printmenu(dl, output, top=True):
+    
+    # XXX should do more checking
+    for child in dl.iterchildren():
+        if not top and child.tag == 'a':
+            print >> output, '[submenu] (%s)' % child.text
+        if child.tag == 'dt':
+            label = ' '.join([ i.strip() for i in child.itertext() if i.strip() ])
+        if child.tag == 'dd':
+            command = ' '.join([ i.strip() for i in child.itertext() if i.strip() ])
+            executable = command.split()[0]
+            if executable in executables:
+                print >> output, '[exec] (%s) {%s}' % (label, command)
+        if child.tag == 'dl':
+            printmenu(child, output, top=False)
+    if not top:
+        print >> output, '[end]'
+
+def main(args = sys.argv[1:]):
+
+    # setup input, output
+    if args:
+        htmlfile = file(args[0])
+    else:
+        htmlfile = sys.stdin
+    html = htmlfile.read()
+    fluxout = sys.stdout
+
+    # get first element
+    dom = etree.fromstring(html)
+    dl = dom.find('.//dl')
+
+    printmenu(dl, fluxout)
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/install.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,36 @@
+def install_hg(sources):
+    """
+    - sources : dict of hg sources to install: {'package': 'http://hg...'}
+    """
+    try:
+        from subprocess import check_call as call
+    except:
+        from subprocess import call
+
+    # see if you can find site-packages
+    import site
+    site_dir = os.path.abspath(os.path.dirname(site.__file__))
+    site_packages = os.path.join(site_dir, 'site-packages')
+    if not (os.path.exists(site_packages) and os.path.isdir(site_packages)):
+        raise IOError("Cannot find site-packages directory")
+
+    # figure out what you need to install
+    missing = set()
+    for source in sources:
+        try:
+            __import__(source)
+        except ImportError:
+            missing.add(source)
+
+    # install it
+    for source in missing:
+        call(['hg', 'clone', sources[source],
+              os.path.join(site_packages, source)])
+
+### install unpackaged dependencies
+if set(['install', 'develop']).intersection(sys.argv[1:]):
+    try:
+        install_hg(source)
+    except:
+        print 'Please make sure the source is installed:'
+        print source
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/install_config.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+"""
+installs config to a user's home directory
+this can be done with
+curl http://k0s.org/hg/config/raw-file/tip/python/install_config.py | python
+"""
+
+SRC='http://k0s.org/hg/config'
+import os
+import subprocess
+import sys
+
+# go home
+HOME=os.environ['HOME']
+os.chdir(HOME)
+
+commands = [ # make the home directory a repository
+             ['hg', 'init'],
+             ['hg', 'pull', SRC],
+             ['hg', 'update', '-C'],
+
+             # get virtual env
+             ['hg', 'clone', 'http://bitbucket.org/ianb/virtualenv'],
+             ['ln', '-s', HOME + '/virtualenv/virtualenv.py', HOME + '/bin/'],
+
+             # site-specific files
+             ['mkdir', '-p', '.subversion'],
+             ['rm', '-f', '.subversion/config'],
+             ['ln', '-s', os.path.join(HOME, '.subversion_config/config'), os.path.join(HOME, '.subversion/config')],
+             ]
+
+def execute(*commands):
+    """execute a series of commands"""
+    for command in commands:
+        print ' '.join(command)
+        code = subprocess.call(command)
+        if code:
+            sys.exit(code)
+
+execute(*commands)
+
+# make a (correct) .hg/hgrc file for $HOME
+subprocess.call('/bin/echo -e "[paths]\\ndefault = http://k0s.org/hg/config\\ndefault-push = ssh://k0s.org/hg/config" > ~/.hg/hgrc', shell=True)
+
+def install_develop(package):
+    src = 'http://k0s.org/hg/%s' % package
+    directory = '%s/src/%s' % (package, package)
+    commands = [ ['virtualenv/virtualenv.py', package],
+                 ['mkdir', '-p', directory ],
+                 ['hg', 'clone', src, directory] ]
+    execute(*commands)
+    old_directory = os.getcwd()
+    os.chdir(directory)
+    command = ['../../bin/python',  'setup.py', 'develop']
+    execute(command)
+    os.chdir(old_directory)
+    
+# install some python
+install_develop('smartopen')
+install_develop('silvermirror') # XXX this won't actually work since python-dev isn't installed; install it first
+
+postinstall_commands = [ ['ln', '-s', os.path.join(HOME, 'smartopen', 'bin', 'smartopen'), os.path.join(HOME, 'bin', 'smartopen') ],
+                         ['ln', '-s', os.path.join(HOME, 'silvermirror', 'bin', 'silvermirror'), os.path.join(HOME, 'bin', 'silvermirror') ],
+                         ]
+execute(*postinstall_commands)
+
+
+# - ubuntu packages to install:
+PACKAGES="mercurial unison fluxbox antiword xclip graphviz python-dev python-lxml curl arandr"
+print "Ensure the following packages are installed:"
+print "sudo apt-get install $PACKAGES"
+
+# setup git's global ignore, since git is silly about this and doesn't look for the file in the right place
+subprocess.call('if which git; then git config --global core.excludesfile ~/.gitignore; fi', shell=True)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/jsonex.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+"""
+JSON explorer
+"""
+
+import json
+import sys
+from pprint import pprint
+
+def main(args=sys.argv[1:]):
+    data = sys.stdin.read() # read from stdin
+    obj = json.loads(data)
+
+    if args:
+        for arg in args:
+            foo = arg.split('.') # split into objects
+            # TODO: split into slice notation
+            pass # TODO
+    else:
+        print json.dumps(obj, indent=2, sort_keys=True)
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/listify.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,20 @@
+def listify(listitems, ordered=False):
+    """ return an html list """
+    if not hasattr(listitems, '__iter__'):
+        thelist = ( listitems, )
+    if ordered:
+        tag, invtag = '<ol>\n', '</ol>'
+    else:
+        tag, invtag = '<ul>\n', '</ul>'
+
+    thelist = tag
+    
+    for i in listitems:
+        thelist += ' <li> ' + str(i) + ' <li>\n'
+
+    thelist += invtag
+    return thelist
+
+if __name__ == '__main__':
+    import sys
+    print listify(sys.argv)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/lolspeak.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+loldict = { 'am': 'is',
+            'and': 'n',
+            'are': 'r',
+            'ate': 'eated',
+            'back': 'bak',
+            'business': 'bizness',
+            'bye': 'bai',
+            'cat': 'kitteh',
+            'cheeseburger': 'cheezburger',
+            'cute': 'kyooot',
+            'food': 'foodz',
+            'fucking': 'fuxing',
+            'have': 'has',
+            'help': 'halp',
+            'hi': 'hai',
+            'is': 'iz',
+            'kitty': 'kitteh',
+            'later': 'l8r',
+            'making': 'makin',
+            'means': 'meens',
+            'more': 'moar',
+            'news': 'newz',
+            'please': 'plz',
+            'power': 'powr',
+            'saturday': 'caturday',
+            'says': 'sez',
+            'takes': 'takez',
+            'thanks': 'kthx',
+            'time': 'tiem',
+            'the': 'teh',
+            'there': 'thar',
+            'this': 'dis',
+            'towel': 'towul',
+            'uses': 'uzes',
+            'young': 'yung',
+            'your': 'ur'
+            }
+
+def translate(string):
+    retval = []
+    for word in string.split():
+        retval.append(loldict.get(word.lower(), word))
+    return ' '.join(retval)
+
+if __name__ == '__main__':
+    import sys
+    if sys.argv[1:]:
+        print translate(' '.join(sys.argv[1:]))
+    else:
+        print translate(sys.stdin.read())
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/lsex.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+import os
+import sys
+from optparse import OptionParser
+
+# make sure duplicate path elements aren't printed twice
+def ordered_set(alist):
+    seen = set()
+    new = []
+    for item in alist:
+        if item in seen:
+            continue
+        seen.add(item)
+        new.append(item)
+    return new
+
+def lsex(path=None):
+    """
+    list executable files on the path
+    - path: list of directories to search.  if not specified, use system path
+    """
+
+    if path is None:
+        # use system path
+        path = ordered_set(os.environ['PATH'].split(':'))
+
+    executables = []
+
+    # add the executable files to the list
+    for i in path:
+        if not os.path.isdir(i):
+            continue
+        files = [ os.path.join(i,j) for j in os.listdir(i) ]
+        files = filter(lambda x: os.access(x, os.X_OK), files)
+        files.sort() # just to make the output pretty
+        executables.extend(files)
+    return executables
+
+def executable_names(path=None):
+    executables = lsex(path)
+    executables = set([os.path.basename(i) for i in executables])
+    return executables
+
+if __name__ == '__main__':
+    parser = OptionParser()
+    parser.add_option('--names', action='store_true', default=False,
+                      help="list only the set of names")
+
+    options, args = parser.parse_args()
+    if options.names:
+        for i in sorted(executable_names()):
+            print i
+        sys.exit(0)
+    
+    for i in lsex():
+        print i
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/lsexts.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+import os
+
+def extensions(*filenames):
+    return set([os.path.splitext(f)[-1] for f in filenames
+                if '.' in f])
+
+def find_extensions(*directories):
+    _extensions = set()
+    for directory in directories:
+        for _, _, fnames in os.walk(directory):
+            _extensions.update(extensions(*fnames))
+    return _extensions
+        
+if __name__ == '__main__':
+    import sys
+    for ext in sorted(find_extensions(*sys.argv[1:])):
+        print ext
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/mutable_defaults.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+# see also: http://www.daniweb.com/software-development/python/threads/66697
+
+class Foo(object):
+  def __init__(self, mutable=['default']):
+    self.foo = mutable
+    self.foo.append(1)
+
+if __name__ == '__main__':
+  bar = Foo()
+  print len(bar.foo)
+  fleem = Foo()
+  print len(fleem.foo)
+  assert len(fleem.foo) == 2, "Don't use default mutable arguments!"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/onelineit.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+def onelineit(string):
+    string = string.split('\n')
+    string = [ i.strip() or '\n' for i in string ]
+    string = ' '.join(string)
+    string = string.split('\n')
+    string = [ i.strip() for i in string if i.strip() ]
+
+    return '\n\n'.join(string)
+
+if __name__ == '__main__':
+    import sys    
+    print onelineit(sys.stdin.read())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/optparse_undefined.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+illustrates usage of the undefined pattern from e.g.
+http://k0s.org/mozilla/hg/bzconsole/file/tip/bzconsole/command.py
+
+This is useful for scenarios similar to:
+- you have base configuration in a file
+- you have an OptionParser to read options in the command line
+- the CLI options should overwrite the file configuration iff
+  the user specifies an option
+"""
+
+from optparse import OptionParser
+
+class Undefined(object):
+    def __init__(self, default):
+        self.default=default
+
+class UndefinedOptionParser(OptionParser):
+
+    def add_option(self, *args, **kwargs):
+        kwargs['default'] = Undefined(kwargs.get('default'))
+        OptionParser.add_option(self, *args, **kwargs)
+
+    def parse_args(self, *args, **kwargs):
+        options, args = OptionParser.parse_args(self, *args, **kwargs)
+        return options, args
+
+if __name__ == '__main__':
+
+    myparser = UndefinedOptionParser()
+    myparser.add_option("--foo", dest='foo', default='hello')
+    myparser.add_option("--bar", dest='bar', default='goodbye')
+    myparser.add_option("--baz", dest='baz', default='helloagain')
+    myparser.add_option("--fleem", dest='fleem', default='aufwiedersehen')
+
+    myconfiguration = {'foo': 'hi',
+                       'bar': 'ciao'}
+    options, args = myparser.parse_args(['--foo', 'hello', '--baz', 'hola'])
+    for key, value in options.__dict__.items():
+        # XXX ideally you would move this to parse_args
+        if isinstance(value, Undefined):
+            options.__dict__[key] = myconfiguration.get(key, value.default)
+
+    assert options.foo == 'hello'
+    assert options.bar == 'ciao'
+    assert options.baz == 'hola'
+    assert options.fleem == 'aufwiedersehen'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/pastebin.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+import sys
+import urllib2
+import urllib
+content = sys.stdin.read()
+url = 'http://pastebin.com/api_public.php'
+data = dict(paste_code=content, paste_subdomain='mozilla')
+values = urllib.urlencode(data)
+req = urllib2.Request(url, values)
+response = urllib2.urlopen(req)
+the_page = response.read()
+
+print the_page
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/pbmoz.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+import urllib, sys
+
+if len(sys.argv) == 2:
+    url = "http://%s.pastebin.mozilla.org" % sys.argv[1]
+    fmt = sys.argv[1]
+else:
+    url = "http://pastebin.mozilla.org"
+    fmt = "None"
+
+body = sys.stdin.read()
+
+params = [
+    ('parent_pid', ''),
+    ('code2', body),
+    ('poster', ''),
+    ('expiry', 'd'),
+    ('paste', 'Send'),
+    ('format', fmt),
+    ]
+
+data = urllib.urlencode(params)
+
+req = urllib.urlopen(url, data)
+
+print req.geturl()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/prefs.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,49 @@
+import re
+comment = re.compile('/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/', re.MULTILINE)
+
+def read(filename):
+    token = '##//' # magical token
+    lines = [i.strip() for i in file(filename).readlines() if i.strip()]
+    retval = {}
+    _lines = []
+    for line in lines:
+        if line.startswith('#'):
+            continue
+        if '//' in line:
+            line = line.replace('//', token)
+        _lines.append(line)
+    string = '\n'.join(_lines)
+    string = re.sub(comment, '', string)
+    def pref(a, b):
+        retval[a] = b
+    lines = [i.strip().rstrip(';') for i in string.split('\n') if i.strip()]
+    for line in lines:
+        try:
+            _globals = {'retval': retval, 'pref': pref, 'user_pref': pref, 'true': True, 'false': False}
+            eval(line, _globals, {})
+        except SyntaxError:
+            print line
+            import pdb; pdb.set_trace()
+    for key in retval:
+        if isinstance(retval[key], basestring) and token in retval[key]:
+            retval[key] = retval[key].replace(token, '//')
+    return retval
+
+def write(filename, prefs, pref_string='user_pref("%s", %s);'):
+    f = file(filename, 'w')
+    for key, value in prefs.items():
+        if value is True:
+            print >> f, pref_string % (key, 'true')
+        elif value is False:
+            print >> f, pref_string % (key, 'true')
+        elif isinstance(value, basestring):
+            print >> f, pref_string % (key, repr(string(value)))
+        else:
+            print >> f, pref_string % (key, value) # should be numeric!
+    f.close()
+
+if __name__ == '__main__':
+    import sys
+    if not sys.argv[1:]:
+        sys.exit(1)
+    print read(sys.argv[1])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/process.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,52 @@
+import os
+import shlex
+import subprocess
+import sys
+
+def ps(arg='axwww'):
+    """
+    python front-end to `ps`
+    http://en.wikipedia.org/wiki/Ps_%28Unix%29
+    returns a list of process dicts based on the `ps` header
+    """
+    retval = []
+    process = subprocess.Popen(['ps', arg], stdout=subprocess.PIPE)
+    stdout, _ = process.communicate()
+    header = None
+    for line in stdout.splitlines():
+        line = line.strip()
+        if header is None:
+            # first line is the header
+            header = line.split()
+            continue
+        split = line.split(None, len(header)-1)
+        process_dict = dict(zip(header, split))
+        retval.append(process_dict)
+    return retval
+
+def running_processes(name, psarg='axwww', defunct=True):
+    """
+    returns a list of 2-tuples of running processes:
+    (pid, ['path/to/executable', 'args', '...'])
+     with the executable named `name`.
+     - defunct: whether to return defunct processes
+    """
+    retval = []
+    for process in ps(psarg):
+        command = process['COMMAND']
+        command = shlex.split(command)
+        if command[-1] == '<defunct>':
+            command = command[:-1]
+            if not command or not defunct:
+                continue
+        prog = command[0]
+        basename = os.path.basename(prog)
+        if basename == name:
+            retval.append((int(process['PID']), command))
+    return retval
+
+if __name__ == '__main__':
+    for arg in sys.argv[1:]:
+        processes = running_processes(arg)
+        for pid, command in processes:
+            print '%s %s : %s' % (pid, arg, command)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/randomize.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import os
+import random
+import subprocess
+import sys
+
+from optparse import OptionParser
+
+if __name__ == '__main__':
+    parser = OptionParser()
+    parser.add_option("-e", "--exec", dest="callable",
+                      help="program to execute")
+    (options, argv) = parser.parse_args()
+    args = []
+    for i in argv:
+        if os.path.isdir(i):
+            for root, dirs, files in os.walk(i):
+                args.extend([os.path.join(root, f) for f in files])
+        else:
+            args.append(i)
+    random.shuffle(args)
+    if options.callable:
+        for i in args:
+            subprocess.call([options.callable, i])
+    else:
+        print '\n'.join(args)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/realpath.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+import os, sys
+for i in sys.argv[1:]:
+    print os.path.realpath(i)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/relativelink.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+def link(path_info, path=None):
+
+    segments = path_info.split('/')
+    if segments[0]:
+        segments.insert(0, '')
+    
+    if len(segments) <3:
+        if not path or path == '/':
+            return './'
+        return path
+
+    nlayers = len(segments[2:])
+    string = '../' * nlayers
+
+    if not path or path == '/':
+        return string
+    return string + path
+
+if __name__ == '__main__':
+    import sys
+    assert len(sys.argv[1:]) == 2, "need two arguments"
+    path_info, path = sys.argv[1:]
+    print link(path_info, path)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/require.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,19 @@
+def require(url):
+    """
+    import a module from the web
+    url should be like scheme://host.name/path/to/module.py
+    """
+    import imp
+    import os
+    import tempfile
+    import urllib2
+    contents = urllib2.urlopen(url).read()
+    filename = url.rsplit('/', 1)[-1]
+    module = filename.rsplit('.', 1)[-1]
+    dest = tempfile.mkstemp(suffix='.py', prefix=module)
+    f = file(dest, 'w')
+    f.write(contents)
+    f.close()
+    return imp.load_source(module, dest)
+
+# TODO: make an equivalent method for a tarball
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/setup_repo.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+import os
+import subprocess
+import sys
+
+from optparse import OptionParser
+
+HOST='k0s.org'
+HGRC="""[paths]
+default = http://%(host)s/%(repo)s/%(name)s
+default-push = ssh://%(host)s/%(repo)s/%(name)s
+"""
+
+def call(command, *args, **kw):
+  code = subprocess.call(command, *args, **kw)
+  if isinstance(command, basestring):
+    cmdstr = command
+  else:
+    cmdstr = ' '.join(command)
+  print cmdstr
+  if code:
+    raise SystemExit("Command `%s` exited with code %d" % (cmdstr, code))
+        
+def main(args=sys.argv[1:]):
+
+  parser = OptionParser('%prog [options] location')
+  parser.add_option('-m', '--message',
+                    help='commit message')
+  options, args = parser.parse_args(args)
+  
+  if len(args) != 1:
+    parser.print_usage()
+    parser.exit()
+
+  repo = args[0].strip('/')
+  
+  directory = os.getcwd()
+  name = os.path.basename(directory)
+  os.chdir('..')
+  call(['scp', '-r', name, '%s:~/%s/' % (HOST, repo)])
+  call(['ssh', HOST, "cd %s/%s && hg init && hg add && hg ci -m '%s'" % (repo, name, options.message or 'initial commit of %s' % name)])
+  os.chdir(directory)
+  call(['hg', 'init'])
+  call(['hg', 'pull', 'http://%s/%s/%s' % (HOST, repo, name)])
+  call(['hg', 'update', '-C'])
+  f = file(os.path.join('.hg', 'hgrc'), 'a')
+  print >> f, HGRC % { 'host': HOST, 'repo': repo, 'name': name}
+
+if __name__ == '__main__':
+  main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/signature.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,30 @@
+import random
+import sys
+import time
+
+from optparse import OptionParser
+
+parser = OptionParser()
+parser.add_option('-f', '--file')
+parser.add_option('-o', '--output')
+(options, args) = parser.parse_args()
+
+if options.file:
+    f = file(options.file)    
+else:
+    f = sys.stdin
+
+lines = [ line.strip() or '\n' for line in f.read().strip().split('\n') ]
+content = '\n'.join(lines)
+fortunes = [i.strip() for i in content.split('\n\n') ]
+f.close()
+
+while 1:
+    if options.output:
+        f = file(sig, 'w')
+        print >> f, random.choice(fortunes)
+        f.close()
+    else:
+        print random.choice(fortunes)
+    time.sleep(1)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/simpleconf.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,6 @@
+def simpleconf(filename, sep='='):
+    assert os.path.exists(filename)
+    lines = [line.strip() for line in file(filename).readlines()]
+    lines = [line for line in lines if line and not line.startswith('#')]
+    assert not [line for line in lines if sep not in line]
+    return dict([line.split(sep, 1) for line in lines])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/simpleini.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+
+import os
+
+def read(fp, variables=None, default='DEFAULT',
+         comments=';#', separators=('=', ':'),
+         interpolate=True, strict=True):
+  """
+  read an .ini file and return a list of [(section, values)]
+  - fp : file pointer or name to read
+  - variables : default set of variables
+  - default : name of the section for the default section
+  - comments : characters that if they start a line denote a comment
+  - separators : strings that denote key, value separation in order
+  - strict : whether to be strict about parsing
+  """
+
+  if variables is None:
+    variables = {}
+
+  if isinstance(fp, basestring):
+    fp = file(fp)
+
+  sections = []
+  key = value = None
+  section_names = set([])
+
+  # read the lines
+  for line in fp.readlines():
+
+    stripped = line.strip()
+
+    # ignore blank lines
+    if not stripped:
+      # XXX should probably reset key and value to avoid continuation lines
+      key = value = None
+      continue
+
+    # ignore comment lines
+    if stripped[0] in comments:
+      continue
+
+    # check for a new section
+    if len(stripped) > 2 and stripped[0] == '[' and stripped[-1] == ']':
+      section = stripped[1:-1].strip()
+      key = value = None
+
+      # deal with DEFAULT section
+      if section.lower() == default.lower():
+        if strict:
+          assert default not in section_names
+        section_names.add(default)
+        current_section = variables
+        continue
+
+      if strict:
+        # make sure this section doesn't already exist
+        assert section not in section_names
+
+      section_names.add(section)
+
+      current_section = {}
+      sections.append((section, current_section))
+      continue
+
+    # if there aren't any sections yet, something bad happen
+    if not section_names:
+      raise Exception('No sections yet :(')
+
+    # (key, value) pair
+    for separator in separators:
+      if separator in stripped:
+        key, value = stripped.split(separator, 1)
+        key = key.strip()
+        value = value.strip()
+
+        if strict:
+          # make sure this key isn't already in the section or empty
+          assert key
+          if current_section is not variables:
+            assert key not in current_section
+        
+        current_section[key] = value
+        break
+    else:
+      # continuation line ?
+      if line[0].isspace() and key:
+        value = '%s%s%s' % (value, os.linesep, stripped)
+        current_section[key] = value
+      else:
+        # something bad happen!
+        raise Exception("Not sure what you're trying to do")
+
+  # interpret the variables
+  def interpret_variables(global_dict, local_dict):
+    variables = global_dict.copy()
+    variables.update(local_dict)
+
+    # string intepolation
+    if interpolate:
+      nonce = '__s__'
+      assert nonce not in global_dict
+      global_dict[nonce] = '%s'
+      for key, value in variables.items():
+        try:
+          value = value.replace('%s', '%(__s__)s') % global_dict
+          variables[key] = value
+        except:
+          if strict:
+            del global_dict[nonce]
+            raise Exception("could not intepolate variable %s: %s" % (key, value))
+          pass
+          
+      del global_dict[nonce]
+    return variables
+
+  sections = [(i, interpret_variables(variables, j)) for i, j in sections]
+  return sections
+
+if __name__ == '__main__':
+  import sys
+  for i in sys.argv[1:]:
+    path = os.path.abspath(i)
+    print read(i, strict=False, variables=dict(here=os.path.dirname(path)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/sshdiff.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+"""
+diff files over ssh
+"""
+
+import os
+import subprocess
+import sys
+import tempfile
+from optparse import OptionParser
+
+def main(args=sys.argv[1:]):
+    usage = "%prog host file"
+    parser = OptionParser(usage=usage, description=__doc__)
+    options, args = parser.parse_args(args)
+    try:
+        host, filename = args
+    except ValueError:
+        parser.print_usage()
+        parser.exit(1)
+    process = subprocess.Popen(["ssh", host, "cat", filename], stdout=subprocess.PIPE)
+    stdout, stderr = process.communicate()
+    fd, buffer = tempfile.mkstemp()
+    os.write(fd, stdout)
+    os.close(fd)
+    subprocess.call(['diff', os.path.join(os.environ['HOME'], filename), buffer])
+    try:
+        os.remove(buffer)
+    except:
+        pass
+
+if __name__ == '__main__':
+    main()
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/states.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,75 @@
+states =  {			
+    "AL": "Alabama",
+    "AK": "Alaska",
+    "AS": "American Samoa",
+    "AZ": "Arizona",
+    "AR": "Arkansas",
+    "AE": "Army P.O. Box",
+    "AP": "Army Post Office",
+    "CA": "California",
+    "CO": "Colorado",
+    "CT": "Connecticut",
+    "DE": "Delaware",
+    "DC": "District of Columbia",
+    "FL": "Florida",
+    "GA": "Georgia",
+    "GU": "Guam",
+    "HI": "Hawaii",
+    "ID": "Idaho",
+    "IL": "Illinois",
+    "IN": "Indiana",
+    "IA": "Iowa",
+    "KS": "Kansas",
+    "KY": "Kentucky",
+    "LA": "Louisiana",
+    "ME": "Maine",
+    "MD": "Maryland",
+    "MA": "Massachusetts",
+    "MI": "Michigan",
+    "MN": "Minnesota",
+    "MS": "Mississippi",
+    "MO": "Missouri",
+    "MT": "Montana",
+    "NE": "Nebraska",
+    "NV": "Nevada",
+    "NH": "New Hampshire",
+    "NJ": "New Jersey",
+    "NM": "New Mexico",
+    "NY": "New York",
+    "NC": "North Carolina",
+    "ND": "North Dakota",
+    "OH": "Ohio",
+    "OK": "Oklahoma",
+    "OR": "Oregon",
+    "OT": "Other",
+    "PA": "Pennsylvania",
+    "PR": "Puerto Rico",
+    "RI": "Rhode Island",
+    "SC": "South Carolina",
+    "SD": "South Dakota",
+    "TN": "Tennessee",
+    "TX": "Texas",
+    "US": "United States",
+    "UT": "Utah",
+    "VT": "Vermont",
+    "VI": "Virgin Islands",
+    "VA": "Virginia",
+    "WA": "Washington",
+    "WV": "West Virginia",
+    "WI": "Wisconsin",
+    "WY": "Wyoming",
+}
+
+def getstate(query):
+    """ 
+    return the state name of the query,
+    or None if its not in the list
+    """
+    
+    if query in states.keys():
+        return states[query]
+
+    if query in states.values():
+        return query
+
+    return None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/str2lnk.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+def str2lnk(string):
+    """transform a string to a legitimate link name for html"""
+    illegal_characters=' @,?/\\#'
+    for i in illegal_characters:
+        string = string.replace(i, '_')
+    newstring = ''
+    for i in string.split('_'):
+        if i:
+            newstring += i + '_'
+    return newstring[:-1]
+    
+if __name__ == '__main__':
+    import sys
+    try:
+        newstring=sys.argv[1]
+    except IndexError:
+        print '%s' % str2lnk.__doc__
+        print 'Usage: %s <string to be made a link>' % sys.argv[0]
+        sys.exit(0)
+
+    newstring = ' '.join(sys.argv)
+    print str2lnk(newstring)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/tablify.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,19 @@
+def tablify(table_lines, header=True):
+    table = '<table>\n'
+    if header:
+        tag, invtag = '<th> ', ' </th>'
+    else:
+        tag, invtag = '<td> ', ' </td>'
+    if not hasattr(table_lines, '__iter__'):
+        table_lines = ( table_lines, )
+    for i in table_lines:
+        table += '<tr>'
+        if not hasattr(i, '__iter__'):
+            i = (i,)
+        for j in i:
+            table += tag + str(j) + invtag
+        table += '</tr>\n'
+        tag = '<td> '
+        invtag = ' </td>'
+    table += '</table>'
+    return table
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/tld.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+URL = 'http://www.palosverdes.com/jesse/irc/country.txt'
+
+import urllib2
+
+def codes():
+  f = urllib2.urlopen(URL)
+  codes = {}
+  for line in f.readlines():
+    line = line.strip()
+    if not line:
+      continue
+    key, value = line.split(None, 1)
+    codes[key.lower()] = value
+  return codes
+codes = codes()
+
+def get(code):
+  code = code.lstrip('.').lower()
+  return codes.get(code)
+
+if __name__ == '__main__':
+  import sys
+  for arg in sys.argv[1:]:
+    print '%s: %s' % (arg, get(arg))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/unroll_deps.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,83 @@
+#!/usr/bin/env python 
+
+def cycle_check(order, dependencies):
+    """ensure no cyclic dependencies"""
+    order_dict = dict([(j, i) for i, j in enumerate(order)])
+    for package, deps in dependencies.items():
+        index = order_dict[package]
+        for d in deps:
+            assert index > order_dict[d], "Cyclic dependencies detected"
+
+
+def unroll_dependencies(dependencies):
+    """unroll dependencies"""
+    order = []
+
+    # unroll the dependencies
+    for package, deps in dependencies.items():
+        try:
+            index = order.index(package)
+        except ValueError:
+            order.append(package)
+            index = len(order) - 1
+        for dep in deps:
+            try:
+                dep_index = order.index(dep)
+                if dep_index > index:
+                    order.insert(dep_index+1, package)
+                    order.pop(index)
+                    index = dep_index
+            except ValueError:
+                order.insert(index, dep)
+
+    cycle_check(order, dependencies)
+    return order
+
+def unroll_dependencies2(dependencies):
+    """a variation"""
+    order = []
+
+    # flatten all
+    packages = set(dependencies.keys())
+    for deps in dependencies.values():
+        packages.update(deps)
+
+    while len(order) != len(packages):
+
+        for package in packages.difference(order):
+            if dependencies.get(package, set()).issubset(order):
+                order.append(package)
+                break
+        else:
+            raise AssertionError("Cyclic dependencies detected")
+
+    cycle_check(order, dependencies)
+    
+    return order
+
+if __name__ == '__main__':
+    deps = {'packageA': set(['packageB', 'packageC', 'packageF']),
+            'packageB': set(['packageC', 'packageD', 'packageE', 'packageG']),
+            'packageC': set(['packageE']),
+            'packageE': set(['packageF', 'packageG']),
+            'packageF': set(['packageG']),
+            'packageX': set(['packageA', 'packageG'])}
+    unrolled = unroll_dependencies(deps)
+    print unrolled
+
+    unrolled = unroll_dependencies2(deps)
+    print unrolled
+
+    # ensure cycle check works
+    deps['packageD'] = set(['packageX'])
+    try:
+        unroll_dependencies(deps)
+        raise Exception("Missed a cyclic dependency!")
+    except AssertionError:
+        pass
+        
+    try:
+        unroll_dependencies2(deps)
+        raise Exception("Missed a cyclic dependency!")
+    except AssertionError:
+        pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/urlhash.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+"""
+return a random URL hash
+"""
+
+import random
+import urllib
+
+chars = [ chr(i) for i in range(0,255) ]
+allowed = [ urllib.quote_plus(i) for i in chars 
+            if urllib.quote_plus(i) in chars ]
+
+def urlhash(len=10):
+  chars = random.sample(allowed, len)
+  string = ''.join(chars)
+  return urllib.quote_plus(string)
+
+if __name__ == '__main__':
+  print urlhash()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/venvit.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+"""
+venvit.py -- the equivalent of ez_setup.py for virtualenv, but less intrusive;
+It wants a one-step installation to install python into a new virtualenv.
+venvit is meant to be used via e.g. curl, although you can download it as well:
+
+ curl http://example.com/path/to/venvit.py | python - <package>
+
+If <package> is a package name, it tries to install it from the cheeseshop.
+
+If it is a svn/hg/git/tgz/etc URL, it should download and install the software
+in source.
+
+Only useful output -- like the scripts installed -- should be output to the
+user.
+
+Ideally, packages could have a venvit__init__.py (or a better name) that
+will be executed after installation (or a venvit.txt which would just be output
+to console, maybe falling back to the README
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/walk.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+def all_files(directory):
+    filenames = []
+    for dirpath, dirnames, files in os.walk('/home/jhammel/music'):
+        filenames.extend([os.path.join(dirpath, f) for f in files])
+    return sorted(filenames)
+
+def main(args=sys.argv[1:]):
+    if not args:
+        print "Usage: %s directory [directory] [...]" % os.path.basename(sys.argv[0])
+    for arg in args:
+        if os.path.isdir(arg):
+            for i in all_files(arg):
+                print i
+        elif os.path.isfile(arg):
+            print os.path.abspath(arg)
+        else:
+            print >> sys.stderr, "'%s' not a file or directory"
+        
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/which.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+def findInPath(fileName, path=os.environ['PATH']):
+    """python equivalent of which; should really be in the stdlib"""
+    dirs = path.split(os.pathsep)
+    for dir in dirs:
+        if os.path.isfile(os.path.join(dir, fileName)):
+            return os.path.join(dir, fileName)
+        if os.path.isfile(os.path.join(dir, fileName + ".exe")):
+            return os.path.join(dir, fileName + ".exe")
+
+if __name__ == '__main__':
+    for i in sys.argv[1:]:
+        print findInPath(i)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/window_path.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import os
+import subprocess
+import sys
+import window_title
+
+def main(filename):
+    title = window_title.active_window_title()
+    path = os.path.expanduser(title)
+    if not os.path.exists(path):
+        return
+    path = os.path.abspath(path)
+    return os.path.join(path, filename)
+
+if __name__ == '__main__':
+    print main(sys.stdin.read().strip())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/window_title.py	Mon Feb 13 16:24:06 2012 -0800
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+"""
+get the active window title
+"""
+
+import re
+import subprocess
+
+def active_window_id():
+    process = subprocess.Popen(['xprop', '-root'], stdout=subprocess.PIPE)
+    stdout, stderr = process.communicate()
+    for line in stdout.splitlines():
+        if '_NET_ACTIVE_WINDOW(WINDOW):' in line:
+            return line.rsplit(None, 1)[-1]
+
+def window_title(window_id):
+    process = subprocess.Popen(['xprop', '-id', window_id], stdout=subprocess.PIPE)
+    stdout, stderr = process.communicate()
+    for line in stdout.splitlines():
+        match = re.match("WM_NAME\((?P<type>.+)\) = (?P<name>.+)", line)
+        if match:
+            type = match.group("type")
+            if type == "STRING" or type == "COMPOUND_TEXT":
+                return match.group("name").strip('"')
+
+def active_window_title():
+    return window_title(active_window_id())
+
+def main():
+    title = active_window_title()
+    print title
+
+if __name__ == '__main__':
+    main()