cfd5d659d737

vim: sadness
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Mon, 22 Nov 2010 14:32:21 -0500
parents 8bd0f75b7689
children 372fdd7888c9
branches/tags (none)
files vim/.vimrc vim/colors/molokai.vim vim/sadness/bike/AUTHORS vim/sadness/bike/COPYING vim/sadness/bike/ChangeLog vim/sadness/bike/INSTALL vim/sadness/bike/NEWS vim/sadness/bike/PKG-INFO vim/sadness/bike/README vim/sadness/bike/README.emacs vim/sadness/bike/README.idle vim/sadness/bike/README.vim vim/sadness/bike/bike/__init__.py vim/sadness/bike/bike/bikefacade.py vim/sadness/bike/bike/globals.py vim/sadness/bike/bike/log.py vim/sadness/bike/bike/logging.py vim/sadness/bike/bike/mock.py vim/sadness/bike/bike/parsing/__init__.py vim/sadness/bike/bike/parsing/constants.py vim/sadness/bike/bike/parsing/fastparser.py vim/sadness/bike/bike/parsing/fastparserast.py vim/sadness/bike/bike/parsing/load.py vim/sadness/bike/bike/parsing/newstuff.py vim/sadness/bike/bike/parsing/parserutils.py vim/sadness/bike/bike/parsing/pathutils.py vim/sadness/bike/bike/parsing/setpath.py vim/sadness/bike/bike/parsing/test_fastparser.py vim/sadness/bike/bike/parsing/test_fastparserast.py vim/sadness/bike/bike/parsing/test_load.py vim/sadness/bike/bike/parsing/test_newstuff.py vim/sadness/bike/bike/parsing/test_parserutils.py vim/sadness/bike/bike/parsing/test_pathutils.py vim/sadness/bike/bike/parsing/test_utils.py vim/sadness/bike/bike/parsing/test_visitor.py vim/sadness/bike/bike/parsing/testall.py vim/sadness/bike/bike/parsing/utils.py vim/sadness/bike/bike/parsing/visitor.py vim/sadness/bike/bike/query/__init__.py vim/sadness/bike/bike/query/common.py vim/sadness/bike/bike/query/findDefinition.py vim/sadness/bike/bike/query/findReferences.py vim/sadness/bike/bike/query/getAllRelatedClasses.py vim/sadness/bike/bike/query/getPackageDependencies.py vim/sadness/bike/bike/query/getReferencesToModule.py vim/sadness/bike/bike/query/getTypeOf.py vim/sadness/bike/bike/query/relationships.py vim/sadness/bike/bike/query/setpath.py vim/sadness/bike/bike/query/test_common.py vim/sadness/bike/bike/query/test_findDefinition.py vim/sadness/bike/bike/query/test_findReferences.py vim/sadness/bike/bike/query/test_getPackageDependencies.py vim/sadness/bike/bike/query/test_getReferencesToClass.py vim/sadness/bike/bike/query/test_getReferencesToMethod.py vim/sadness/bike/bike/query/test_getReferencesToModule.py vim/sadness/bike/bike/query/test_getTypeOf.py vim/sadness/bike/bike/query/test_relationships.py vim/sadness/bike/bike/query/testall.py vim/sadness/bike/bike/refactor/__init__.py vim/sadness/bike/bike/refactor/extractMethod.py vim/sadness/bike/bike/refactor/extractVariable.py vim/sadness/bike/bike/refactor/inlineVariable.py vim/sadness/bike/bike/refactor/moveToModule.py vim/sadness/bike/bike/refactor/rename.py vim/sadness/bike/bike/refactor/setpath.py vim/sadness/bike/bike/refactor/test_extractMethod.py vim/sadness/bike/bike/refactor/test_extractVariable.py vim/sadness/bike/bike/refactor/test_inlineVariable.py vim/sadness/bike/bike/refactor/test_moveToModule.py vim/sadness/bike/bike/refactor/test_rename.py vim/sadness/bike/bike/refactor/test_renameClass.py vim/sadness/bike/bike/refactor/test_renameFunction.py vim/sadness/bike/bike/refactor/test_renameMethod.py vim/sadness/bike/bike/refactor/testall.py vim/sadness/bike/bike/refactor/utils.py vim/sadness/bike/bike/setpath.py vim/sadness/bike/bike/test_bikefacade.py vim/sadness/bike/bike/test_testutils.py vim/sadness/bike/bike/testall.py vim/sadness/bike/bike/testdata.py vim/sadness/bike/bike/testutils.py vim/sadness/bike/bike/transformer/WordRewriter.py vim/sadness/bike/bike/transformer/__init__.py vim/sadness/bike/bike/transformer/save.py vim/sadness/bike/bike/transformer/setpath.py vim/sadness/bike/bike/transformer/testall.py vim/sadness/bike/bike/transformer/undo.py vim/sadness/bike/ide-integration/BicycleRepairMan_Idle.py vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog-rebox vim/sadness/bike/ide-integration/Pymacs-0.20/Makefile vim/sadness/bike/ide-integration/Pymacs-0.20/PKG-INFO vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/.cvsignore vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/__init__.py vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/pymacs.py vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/rebox.py vim/sadness/bike/ide-integration/Pymacs-0.20/README vim/sadness/bike/ide-integration/Pymacs-0.20/README.html vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS-rebox vim/sadness/bike/ide-integration/Pymacs-0.20/TODO vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services.bat vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs.el vim/sadness/bike/ide-integration/Pymacs-0.20/rebox vim/sadness/bike/ide-integration/Pymacs-0.20/setup-emacs.py vim/sadness/bike/ide-integration/Pymacs-0.20/setup.py vim/sadness/bike/ide-integration/bike.vim vim/sadness/bike/ide-integration/bikeemacs.py vim/sadness/bike/ide-integration/test/README vim/sadness/bike/ide-integration/test/extractmethod.py vim/sadness/bike/ide-integration/test/scrap.py vim/sadness/bike/ide-integration/test/scrap2.py vim/sadness/bike/setup.py vim/sadness/bike/testall.py vim/sadness/ropevim/rope.vim vim/sadness/sadness.vim

Changes

--- a/vim/.vimrc	Tue Nov 16 17:53:55 2010 -0500
+++ b/vim/.vimrc	Mon Nov 22 14:32:21 2010 -0500
@@ -272,8 +272,10 @@
 map <F4> :TlistToggle<cr>
 map <leader>T :!/usr/local/bin/ctags --exclude='**/ckeditor' -R . $(test -f .venv && echo ~/lib/virtualenvs/`cat .venv`)<CR>
 
-" Rope
-source $HOME/.vim/sadness/ropevim/rope.vim
+" Rope and Bike.
+let g:bike_exceptions=1
+source $HOME/.vim/sadness/sadness.vim
+
 let ropevim_enable_shortcuts = 0
 let ropevim_guess_project = 1
 noremap <leader>rr :RopeRename<CR>
--- a/vim/colors/molokai.vim	Tue Nov 16 17:53:55 2010 -0500
+++ b/vim/colors/molokai.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -58,7 +58,7 @@
 hi Macro           guifg=#C4BE89               gui=italic
 hi SpecialKey      guifg=#66D9EF               gui=italic
 
-hi MatchParen      guifg=#E4E400 guibg=NONE    gui=bold
+hi MatchParen      guifg=#E4E400 guibg=#232728 gui=bold
 hi ModeMsg         guifg=#E6DB74
 hi MoreMsg         guifg=#E6DB74
 hi Operator        guifg=#F92672
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/AUTHORS	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,24 @@
+Authors
+-------
+
+Phil Dawes       <pdawes@users.sourceforge.net> - Current Maintainer 
+                                                  and Main Author
+Shae Erisson     <shae@lapland.fi>              - Original Maintainer
+
+
+The following people have contributed code, bugfixes and patches:
+
+Jürgen Hermann   <jh@web.de>
+Canis Lupus      
+Syver Enstad     <syver-en@online.no>           Windows emacs patches
+Mathew Yeates    <mathew@comma.jpl.nasa.gov>    VIM support and bug fixes
+Marius Gedminas  <mgedmin@delfi.lt>             More VIM support
+François Pinard  <pinard@iro.umontreal.ca>      Pymacs + help with 
+                                                emacs integration
+Ender            <ender@objectrealms.net>
+Jonathan         <jonathan@infogen.net.nz>
+Steve            <thepindropper@yahoo.com.au>
+Peter Astrand    <peter@cendio.se>
+
+See ChangeLog for more details.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/COPYING	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,32 @@
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000 by Shae Erisson <shae@lapland.fi>
+Copyright (c) 2001 by Phil Dawes <pdawes@users.sourceforge.net>
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ChangeLog	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,2034 @@
+2004-02-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added feature to
+	resolveImportedModuleOrPackage that searches the package hierarchy
+	of the scope even if it isn't in the pythonpath.
+
+2004-02-11  Phil Dawes  <pdawes@users.sf.net>
+
+	* bike/query/getTypeOf.py: rewrote resolveImportedModuleOrPackage
+	to use purely getModuleOrPackageUsingFQN searches. (doesnt use
+	getTypeOf Root searching any more)
+	
+	* bike/query/common.py: rewrote getLogicalLine to handle
+	multilines that parse seperately. (But was submitted by Peter
+	Astrand)
+
+2004-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added functionality to search from the
+	current directory if looking for an import and scope is a module
+
+2004-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/moveToModule.py: Added handling of individual
+	'from a.foo import theFunction'.
+
+	* bike/parsing/fastparserast.py: Added Peter Astrand's patch to
+	fix following bug:
+	'Find-References (and probably others) fails if there is more
+	whitespace than a single space between the "class"/"def" keyword
+	and the class/def name.'
+
+	* bike/query/common.py: fixed bug in just-written-code where no
+	dest in Printnl causes npe.
+	
+	* bike/query/common.py: Fixed a bug in MatchFinder. Printnl ast
+	nodes (print >>foo, bah) look at there children the opposito way
+	to the way the text comes. (i.e. they do visit(bah), visit(foo) in
+	the example above). Wrote code to get round this.
+
+2004-02-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/moveToModule.py: added more functionality to
+	moveFunction
+
+	* bike/bikefacade.py: added expanduser to normalizeFilename so
+	that ~/src/foo gets turned into a proper full path.
+
+	* bike/bikefacade.py: exposed moveClassToNewModule.
+
+	* bike/refactor/moveClass.py: started move-class-to-new-module
+	refactoring.
+
+2004-02-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/pathutils.py: new module containing all the
+	functions that search all the files in the pythonpath.
+
+	* bike/parsing/extended_ast.py: Removed this module. SourceFile is
+	now in load.py, the rest is in fastparserast.py
+
+	* ide-integration/BicycleRepairMan_Idle.py : Added patch from
+	Steve <thepindropper@yahoo.com.au> to allow easier saving of files
+	before refactoring in IDLE
+
+2004-02-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: lots of cleanup. Renamed Source
+	class to SourceFile. Slimmed down Package and Root. Am planning on
+	removing this module completely, and moving the classes into other
+	modules.
+
+
+	* bike/refactor/extractVariable.py: refactored and removed
+	extractLocalVariable_old
+
+	* bike/refactor/extractMethod.py: refactored and removed
+	extractMethod_old
+
+	* bike/refactor/test_rename*.py: Removed the 'rename twice'
+	tests. They are no longer applicable (since BRM saves to disk
+	after each refactoring)
+
+	* bike/transformer/: Moved save.py and undo.py into the
+	transformer package
+
+	* bike/parsing/newstuff.py: moved generatePackageDependencies into
+	the parsing package, because it needs to be used by other modules
+	in the parsing package.
+
+2004-02-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added generatePackageDependencies
+	which given a file in a package hierarchy, yields a list of
+	external packages and modules used by the package.
+
+	* bike/parsing/newstuff.py: Rewrote
+	generateModuleFilenamesInPythonPath wrt new ref search scheme.
+	Scheme: If the module you are searching from is in a package
+	hierarchy, scan every module in the hierarchy, and the files in
+	the directory above it (since they can reach the package without
+	including it in PYTHONPATH).
+	If the module is in a non-package directory, search in all files
+	in the directory, and in any packages below that directory.
+	N.B. this is in addition to directories in the PYTHONPATH.
+
+2004-02-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Removed getRegexMatchesInPythonPath
+
+	* bike/parsing/newstuff.py: Modified getSourceNodesContainingRegex
+	to search the pythonpath + the set of python files in the
+	directory above the root package of the current file. This should
+	remove the requirement to add the root directory to the python
+	path, and thus prevent BRM from finding references in other
+	package structures.
+
+	* bike/query/common.py: Removed scanASTSourceNodesForMatches and walkSourceNodes
+
+	* bike/globals.py: Added True/False declaration for python 2.2
+	back-compatibility.
+
+2004-01-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added code to check for \ in a previous
+	line when locating logical lines
+
+2004-01-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added a test and fixed a bug that meant
+	find-definitions from multiline statements wouldn't work if the
+	braces were equalised on the following line. 
+	(thanks again to Detlev for reporting this bug)
+
+2004-01-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added a test and fixed a bug that meant
+	find-definitions from multiline statements wouldn't work. 
+	(thanks to Detlev for reporting this bug)
+
+2004-01-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added Detlevs patch to not recurse into
+	subversion directories.
+
+2004-01-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Added code in
+	generateModuleFilenamesInPythonPath to ensure each filename is
+	generated once. (and added test to check for it)
+	(Thanks to Detlev & Syver for this bug report)
+
+	* bike/query/common.py (globalScanForMatches): Removed old
+	ast-based code from globalScanForMatches
+
+2004-01-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug where 'from foo import aou'
+	would cause an assert to fail if foo didn't exist. (Thanks Syver)
+
+2004-01-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added code to normalize paths coming into
+	BRM. (hopefully fixes Syver's problems on windows - Thanks Syver)
+
+	
+2003-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug in
+	Bicyclerepair_idle.
+
+----------------------- 0.9 BETA4 -------------------------------
+
+2003-09-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug where brmctx
+	was being tested for a __nonzero__ operator due to new wrapper
+	stuff.
+	Also made the matches window a singleton
+
+	* bike/query/findReferences.py: Rewrote attribute reference
+	finding algorithm to locate a possible match, and then check if
+	the match class shares a common ancestor with the target. (rather
+	than finding all classes in the target hierarchy and then testing
+	each match class against the hierarchy).
+	This results in a 10000% 
+
+2003-09-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added buildClassHierarchy
+	functionality to guess a class hierarchy, but found that it's
+	still much too slow to handle the wxpython class hierarchy of 1900
+	odd classes under 1 root!
+
+
+2003-09-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/fastparserast.py: Added maskedsrc to the cache
+
+	* bike/query/getTypeOf.py: Added caching of type lookups
+
+	* bike/bikefacade.py: Added a generic wrapper which purges the
+	caches before and after each brm ctx call
+
+2003-08-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Added simple caching mechanism for
+	sourceNodes
+
+2003-08-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Removed some crufty methods and
+	base classes for managing the ast tree hierarchy
+
+	* bike/bikefacade.py: Removed a couple of ast related methods
+
+	* bike/query/findReferences.py: Modified the findRefs
+	functionality to exclude matches where the confidence is high that
+	it's *not* the right type.
+
+	* bike/parsing/load.py: removed the load function (and made
+	necessary refactorings to remove it)
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added setWarningLogger
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Fixed bug where "../.." was being
+	added to sys.path. This was because extended_ast.py was adding
+	importing setpath.py.
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added warning code to print message if
+	sys.path is changed by setpath.py
+
+	* ide-integration/test/README: Added ide tests for inline and
+	extract variable
+
+	* bike/bikefacade.py: Removed the load() function, and fixed
+	inline and extract local variable
+
+----------------------- 0.9 BETA3 -------------------------------
+
+2003-08-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Fixed removeLibdirsFromPath to work with
+	windows python lib directories
+
+----------------------- 0.9 BETA2 -------------------------------
+
+2003-08-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/*: Made it backward compatible with python 2.2
+
+	* ide-integration/bike.vim: Adapted vim plugin to work with new
+	api.
+
+----------------------- 0.9 BETA1 -------------------------------
+
+2003-08-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/test_*: Misc fixes for windows paths
+
+	* ide-integration/BicycleRepairMan_Idle.py: Cleaned up error
+	handling for undo stack
+
+	* bike/query/*: Misc fixes for tests
+
+	* bike/refactor/extractMethod.py: Updated to work with new
+	non-tree system
+
+2003-08-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: Converted createSourceNodeAt to create a
+	directory structure rather than an ast. (and broke a load of tests)
+
+2003-08-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: added test setup fixture to change directory
+	before executing tests
+
+2003-08-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug which was stopping sub
+	packages from being found properly
+
+	* bike/query/relationships.py: Fixed getAllClassesInHierarchy and
+	getAllDerivedClasses to work without AST. Uses a smart algorithm
+	which scans the text of files with regexes for baseclassnames and
+	import aliases to narrow down the likely candidates.
+	
+
+2003-08-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Updated docs for python2.3/idlefork
+
+2003-08-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added code to just use
+	1 window for matches, and to reopen it if needed after it is closed
+
+2003-08-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Fixed bug which cause BRM to descend into
+	non-package directorys
+
+	* bike/parsing/extended_ast.py: Added a couple of new functions to
+	handle pythonpaths for queries and refactorings
+
+2003-08-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: modified globalScanForMatches to scan
+	files in addition to walking the ast.
+
+	* bike/query/findReferences.py: Added code to work with new
+	stateless design.
+
+2003-07-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Removed module locating code from
+	findDefinition, and made it use resolveImportedModuleOrPackage
+	instead.
+
+	* bike/query/getTypeOf.py: Modified resolveImportedModuleOrPackage
+	to use the newstuff function getModuleOrPackageUsingFQN if it cant
+	locate the module in the AST tree.
+
+	* bike/parsing/newstuff.py: modified getModuleUsingFQN
+	to handle packages. renamed to getModuleOrPackageUsingFQN 
+
+2003-07-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Made necessary modifications 
+	enable finding of function definitions without importing code
+	(uses the python path to determine where to look). Doesnt work for
+	methods yet.
+
+2003-07-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/inlineVariable.py: Applied Jonathan's patch which
+	fixes bug when multiple instances of a variable are on one line.
+
+2003-06-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: changed findReferences interface
+	to take a filename instead of a srcnode
+
+	* bike/query/findReferences.py: Fixed bug where error wasnt being
+	reported properly
+
+2003-06-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: renamed findReferences to
+	findReferences_old, and created a new findReferences which takes a
+	filename instead of the srcnode
+
+	* bike/bikefacade.py: Removed getFullyQualifiedNameOfScope - it's
+	not used anywhere, and relies on the fqn stuff working.
+
+	* all tests: attempted to remove all usage of fqn from
+	tests. Instead, replaced with name and filename tests. This is
+	because fqn is one of the major things binding the scopes
+	together. 
+
+	* bike/bikefacade.py: removed getTypeOfExpression. It's not used
+	anywhere. Will reinstate when it is required again.
+
+	* bike/query/getTypeOf.py: Fixed bug where a recursive function
+	could cause BRM to stack overflow
+
+2003-06-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added resolveImportedModuleOrPackage fn
+	to try and split the number of calls to getTypeOf()
+
+	* bike/query/getTypeOf.py: Fixed bug where a[0].theMethod() would
+	cause brm to barf.
+
+	* bike/parsing/fastparserast.py: Beefed up the __str__ members for
+	fastparser nodes
+
+2003-06-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Removed output.py. (functionality now in
+	save.py)
+
+2003-06-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: removed the ismodified stuff, in
+	an attempt to make the xast hierarchy a read-only resource.
+	Added a hook in save.py to update the xast whenever somebody
+	queues an update to be saved.
+
+	* bike/parsing/save.py: Added new save module which maintains its
+	own queue of src to be written back to disk. Replaces output.py
+
+2003-05-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/undo.py (UndoStack.undo): refactored to use dictionary
+
+	* bike/query/findDefinition.py: Refactored main function to have a
+	'stateless' interface (i.e. no need to pass a context).
+	findAllPossibleDefinitionsByCoords(filepath,lineno,col)	
+
+2003-05-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py (getRoot): Made the Root object a
+	singleton. Use the getRoot() method to get it. This is an
+	intermediate step in making the parser stateless. (idea is to make
+	it pretend to be stateless by being a singleton, then once the
+	interfaces have changed, transition the parser code to actually
+	make it stateless)
+
+2003-04-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added exception catching and error
+	reporting to bike-emacs integration
+
+2003-03-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* Applied Jonathan's patches
+	    - InlineVariable handles multiline statements
+	    - Fix to bike vim integration
+	
+2003-03-31  Marius Gedminas  <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Removed unnecessary argument
+	to BikeRename().
+
+	* bike/query/common.py: Fixed handling of lambdas in MatchFinder.
+
+2003-03-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractVariable.py: Made a start on the
+	extract-local-variable refactoring
+
+2003-03-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/inlineVariable.py: Made a start on the
+	inline-local-variable refactoring
+
+----------------------- 0.8 BETA2 -------------------------------
+
+2003-03-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug where
+	paths with spaces meant that you couldn't select a reference when
+	doing a findReferences. (Thanks to Andy Bulka for the report)
+
+	* bike/query/getTypeOf.py: Added infinite recursion protection to
+	getTypeOf
+
+	* bike/query/relationships.py: Added some performance improving
+	code when searching for a classhierarchy. Rather than doing a
+	getTypeOf() on every base class, it finds the strings likely to be
+	base classes (i.e. the name of the base class, and any 'import
+	name as foo' lines) to narrow the search.
+
+2003-03-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug in extract method,
+	where blank lines were messing up the indentation in the resultant
+	block
+
+
+----------------------- 0.8 BETA1 -------------------------------
+	
+2003-03-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Fixed bug in brm with emacs on
+	windows, where the mark can be active and nil at the same time.
+
+	* bike/bikefacade.py (BRMContext_impl.load): Fixed bug which
+	affected windows users. Path needs to be saved after it's been
+	normalized.
+
+2003-03-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: fixed bug in attribute finding
+	code - was only searching the first function
+
+	* bike/query/getTypeOf.py: Fixed bug where x = x.bah() would cause
+	recursion error. (just catches the stack overflow)
+
+2003-03-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/*: implemented automatic importing of changed files. This
+	means that ide integration stuff no longer has to import code into
+	brm whenever it is saved.
+
+2003-02-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.vim: Consolidated RenameMethod,
+	RenameFunction and RenameClass into 1 menu option. This is because
+	brm now supports renaming of variables and attributes and I didn't
+	want to add another 2 menu items.
+	
+
+2003-02-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Fixed rename 'prompt'
+	bug. Consolidated all the rename stuff into 1 menu option.
+
+2003-02-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/*: removed getReferencesToClass/Function/Method and
+	replaced with findReferences
+
+2003-02-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: Added findReferencesIncludingDefn
+	and made 'vanilla' findReferences not return the definition.  This
+	paves the way for a unified rename that can be used to rename
+	anything.	
+
+2003-02-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Fixed bug reported by Marius - if
+	class is declared in __init__.py, it blows up.
+
+	* bike/query/findReferences.py: Fixed bugs in
+	'getDefinitionAndScope' logic, so can handle nested classes etc..
+
+2003-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToClass.py: Replaced module logic
+	with call to findReferences()
+
+	* tests: modified or removed tests that tested for the erroneous
+	'import a.b.bah.TheClass'. (A class or function can't be imported
+	- only a module)
+
+2003-01-24  Marius Gedminas <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Show the line itself after finding
+	references/definition.
+
+2003-01-23  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py: Fixed a trivial NameError in
+	MatchFinder.visitGlobal().
+
+2003-01-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Refactored and cleaned up the code in
+	this module.
+
+2003-01-22  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py: Fixed another ValueError, this time on
+	"from foo import bar" lines.
+
+2003-01-20  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py, bike/query/findDefinition.py,
+	bike/query/findReferences.py: Fixed ValueError: list.index(x): x not
+	in list" error caused by several visitFunction methods visiting
+	their child nodes (argument names and default values) out-of-order.
+
+2003-01-16  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/refactor/extractMethod.py: Now puts spaces after commas in
+	generated code.
+
+2003-01-15  Marius Gedminas <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Better load failure diagnostics.
+
+2003-01-14  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/bikefacade.py, bike/parsing/fastparserast.py,
+	ide-integration/BicycleRepairMan_Idle.py: CRLF -> LF translation
+
+2003-01-13  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/bikefacade.py: Added a function to check whether a given file
+	was ever imported.
+
+	* bike/test_bikefacade.py: Unit test for the above.
+
+	* ide-integration/bike.vim: Added code to watch for modified files
+	and reimport them into if they had been imported previously.
+
+2003-01-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToModule.py: Added Ender's
+	getReferencesToModule module (and test module)
+
+2003-01-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Added some find class attribute
+	definition functionality
+
+2003-01-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: fixed bug where 'import'
+	statements in fn scopes weren't being searched
+
+	* ide-integration/bike.vim: Modified Marius' bike.vim vi
+	integration to support new rename and findReferences calls.
+	
+2003-01-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added fix to redisplay frame in
+	emacs, and to test for mark correctly in emacs.
+
+2003-01-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* AUTHORS: Added Mathew and Marius
+
+2003-01-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.emacs: Added simple instructions for installing pymacs.
+
+	* ide-integration/Pymacs-0.20: I'm going to ship pymacs-0.20 with
+	bicyclerepairman. I've modified it a little to make installation
+	easier.
+
+	* ide-integration/bikeemacs.py: Moved bikeemacs back to its
+	original place.
+	
+
+2003-01-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Cleaned this up a bit
+
+	* bike/parsing/fastparser.py: Fixed bug reported by Mathew Yeates
+	where more than one space between 'class' and the name foxed the
+	parser.
+
+2002-12-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: Started work on unified
+	findReferences code. (uses findDefinition to compare matches)
+
+	* ide-integration/emacs/bikeemacs.py: Rewrote emacs integration
+	using the excellent pymacs package
+
+2002-12-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed findDefinition
+	cosmetic bug
+
+	* ide-integration/bike.el, bikeemacs: Added Syver Enstad's patch
+	for allowing filenames with spaces
+
+2002-12-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Completed support for
+	findDefinition
+
+	* ide-integration/bike.el: added code to handle the fact that if
+	you select a region, the point is one greater than the end of the
+	region and so misses it.
+
+2002-12-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Added code to scan for other
+	method matches after locating the 100% one
+
+2002-12-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added basic
+	finddefinition support to idle
+
+	* ide-integration/bikeemacs.py: Added finddefinition support to xemacs
+
+	* bike/bikefacade.py: Exposed findDefinition through bikefacade
+
+	* bike/query/findDefinition.py: Added new query interface for
+	finding the definition of a reference, given its line/col position
+	in a module. Just supports function, method, and class references
+	for now.
+
+---------------------- 0.7 ---------------------------------------
+
+2002-11-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Fixed bug where saving buffers caused
+	the new emacs protocol to get in a tangle. My solution was to add
+	a disableMessages capability
+
+---------------------- 0.7RC3 ------------------------------------
+
+2002-11-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added acknowledgement protocol, to
+	get round synchronisation problems in windows emacs
+
+2002-11-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing: decommissioned addtypeinfo, typeinfo, tokenutils,
+	tokenhandler, matchTokensToAST, doublelinkedlist, testdata 
+
+	* bike/query/getReferencesToClass.py: Fixed bug where 
+	'from foo import *' would cause an exception if searching for a
+	class called 'foo'
+
+	* bike/*/test_*.py: Removed dependency on brmtransformer.
+
+2002-11-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Rewrote extract method module to
+	use all the new cool stuff (and operate or strings). Doesnt use
+	linked lists, iterators, tokens, brmtransformer or any of that
+	shite any more.
+
+2002-11-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug where classscope was being
+	searched if the name wasnt found in methodscope. This is incorrect
+	because class scope isn't visible except through 'self' or a fully
+	qualified classname.
+
+2002-11-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Re-wrote MatchFinder to scan along the
+	source code text when visiting ast nodes. This removes the need to
+	match tokens in order to find the source code location of an ast
+	node.
+
+---------------------- 0.7RC1 ------------------------------------
+
+	
+2002-11-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added performance enhancement to
+	getAllDerivedClasses. Now does string search on file before ast
+	searching the classes.
+
+2002-10-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Finished
+	findReferencesByCoordinates support in idle.
+
+2002-10-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added trace
+	console. Started integration of findReferencesByCoordinates into
+	idle.
+
+	* ide-integration/bike-emacs.py: Added xemacs support for
+	getFullyQualifiedNameOfScope, getTypeOfExpression and
+	findReferencesByCoordinates
+
+
+2002-10-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added getFullyQualifiedNameOfScope,
+	getTypeOfExpression and findReferencesByCoordinates
+
+2002-10-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: changed promptForRename callback signature
+	to be linenumbers and columnnumbers
+
+	* bike/refactor/renameMethod.py: Added prompt
+	functionality. 
+
+2002-10-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added functionality to handle scanning
+	for types of references (needed by getReferencesToMethod)
+
+	* bike/query/getReferencesToMethod.py: Implemented to use
+	common.py stuff
+
+2002-09-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Split out common query code into common.py
+
+2002-09-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameFunction.py: Now uses the getReferences stuff
+	
+2002-09-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/transformer/WordRewriter.py: Split this class out of the
+	renameClass module.	
+
+	* bike/transformer: Added new transformer package to contain code
+	which rewrites the internal representation of the sourcecode
+
+	* bike/bikefacade.py: Implemented locateNode to use the new
+	fastparserast stuff.
+
+	* bike/parsing/extended_ast.py: Added code to set fqn (fully
+	qualified name) attributes on the fastparser ast
+
+2002-09-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Finished modification to use
+	getReferencesToClass. 
+
+2002-09-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Refactored getType() functionality out
+	of ast classes and into a query module.
+
+	* bike/parsing/fastparser.py: Added parsing of import and from
+	lines to fastparser, and optimised a little.
+
+2002-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Started modification to use
+	getReferencesToClass. 
+
+2002-08-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToClass.py: New module which returns a
+	sequence of references to a class
+
+	* bike/parsing/fastparser.py: Wrote new parser which builds a tree
+	of functions and classes, very quickly.
+
+2002-08-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Fixed bug where attempting to
+	tokenize small strings would result in attributeerror
+
+2002-08-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/logging.py: Logging module. Eventually will be replaced by
+	import logging, but for now is a copy of the code by Vinay Sajip
+	(to save people from having to download the module)
+
+	* bike/parsing/brmtransformer.py: Added simple fix - tuple being
+	concatinated to list was causing problems
+
+
+---------------------- 0.6.7 ------------------------------------
+	
+2002-07-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added Canis fix for
+	the bug which stopped brm from displaying the menu when starting
+	idle via right-click file.
+
+	* bike/bikefacade.py: Added Canis windows compatability fix for
+	dealing with .pyw files
+
+	
+2002-07-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug where extracting an
+	expression from a line just below a block opener (e.g. if foo:)
+	would cause a parse error.
+
+2002-07-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Doc about problems on windows
+
+---------------------- 0.6.6 ------------------------------------
+	
+2002-07-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/doublelinkedlist.py: Optimised to use a list rather
+	than a class instance for each link element.
+
+2002-07-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/typeinfo.py: Fixed bug - package wasn't checking
+	parent packages (and Root) for types. This meant that modules
+	imported from higher up the tree weren't being found.
+
+	* bike/parsing/extended_ast.py: Renamed 'Top' to 'Root'
+
+---------------------- 0.6.5 ------------------------------------
+
+2002-07-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Minor bug fix
+
+2002-07-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added code so that it waits for
+	buffer to be reloaded in emacs before sending the request to
+	update the next one.
+
+	* ide-integration/bike.el: Added bug fix - if prompt for rename
+	was on file not loaded, emacs would send a message back to brm
+	when it ran find-file, which buggered up the 'rename-this-method?' 
+	interaction.
+
+2002-07-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Added support for GNU emacs
+
+	* README.emacs: renamed from README.xemacs
+
+	* 
+
+2002-07-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added code to handle more windows filename
+	brokenness
+
+2002-07-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added same optimisation to
+	renameMethod.
+
+	* bike/refactor/renameClass.py: Added optimisation: source string
+	is scanned for classname before visiting ast. (with the lazy ast
+	creation this means that files aren't parsed unless they contain
+	the keyword (or are linked to the source via function call).
+
+	* bike/parsing/extended_ast.py: Refactored .source member into
+	.getSource() method and implemented so that tokens are
+	synchronised with source if they're modified. 
+
+2002-07-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Added lazy parsing of ast when
+	source.getModule() is called.
+
+	* bike/parsing/typeinfo.py: Added PackageTypeInfo which deduces
+	child types by interrogating the package rather than relying on
+	children to register themselves in the typeinfo. This was required
+	to facilitate lazy parsing of ast. (since parse would have had to
+	be done to add module node to package). A lookup of a module now
+	causes getModule() to be called on the sourcefile, thus triggering
+	parse of source into ast.
+
+---------------------- 0.6.4 ------------------------------------
+
+2002-06-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Added bug fix for superflous
+	brackets. Basically, if brackets are unecessary (e.g. '(a).foo()')
+	then they aren't in the parse tree but are in the token
+	stream. This buggers up the token matching.
+	This fix just ignores unmatching ')'s. It was the simplist thing
+	that could possibly work, but may cause problems later - needs
+	lots of testing.
+
+---------------------- 0.6.3 ------------------------------------
+	
+2002-06-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Fixed bug where getattr renamed
+	all occurences of the methodattr in the rest of the tokens
+
+2002-06-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug where commend before
+	the extracted block would make brm think it should be extracting
+	an expression rather than a block.
+
+	* bike/parsing/addtypeinfo.py: Fixed the same bug in _getImportedType
+
+	* bike/refactor/renameClass.py: Fixed bug where the module search
+	routine in the 'From foo import *' code was using the parent scope
+	as the search position. This doesnt work if 'from' is nested in a
+	class since parent scope is a module, not a package. Added method
+	_getParentPackage() to handle this correctly.
+
+2002-06-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed the 'loop' bug. extract
+	method will now recognise variables assigned to by the extracted
+	function and used in a loop by the calling function.
+
+2002-06-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Lots of refactoring prior to
+	fixing a bug.
+
+2002-06-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/doublelinkedlist.py: Rewrote 'insert' so that it
+	doesnt move the iterator. Renamed old method to
+	insertAndPositionIteratorOnNewElement.
+
+2002-06-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed the parse error when
+	extracting code from an if...else... block. The problem was that
+	the code below the extraction contained the 'else', but not the
+	'if'. This is hacked around by inserting an 'if 1: <indent>
+	pass'. This seems to work, but I welcome a better way of handling
+	this.
+
+	* bike/parsing/output.py: Added code to ensure that indent never
+	dips below 0. This fixes a bug in parsing during method extracts
+	out of nested blocks.
+
+	* bike/refactor/extractMethod.py: Fixed the 'don't know what type
+	this isAssAttr(Name('item'), 'decl', 'OP_ASSIGN')' bug
+
+---------------------- 0.6 --------------------------------------
+	
+2002-05-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/test/*: Added manual test script for testing ide
+	integration before a release
+	
+	* ide-integration/BicycleRepairMan_Idle.py: Now imports code into
+	brm when loaded, or saved for the first time.
+
+	* ide-integration/bike.el: Now imports all loaded python files
+	into brm. Also checks to see if file was just updated to avoid
+	superflous reloads.
+
+2002-05-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Added menu for brm
+
+	* bike/parsing/undo.py: Added an internal undo buffer size
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added generic
+	exception reporting to idle
+
+	* ide-integration/bikeemacs.py: Added generic exception
+	reporting. All exceptions are handled and reported back to the
+	user.
+
+2002-05-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Exposed undo to idle
+
+	* ide-integration/bikeemacs.py: Exposed undo to emacs
+
+	* bike/bikefacade.py: Exposed undo functionality to facade
+
+	* bike/parsing/undo.py: Added undo functionality
+
+2002-05-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/test_extractMethod.py: Fixed bug in expression
+	extracting code (which caused a parse exception with correct code)
+
+	* bike/bikefacade.py: Added public interface
+
+---------------------- 0.5 --------------------------------------
+
+	* ide-integration: Created new directory for integration modules 
+
+2002-05-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Exposed extract function to idle
+
+	* bike/ui/bikeemacs.py: Exposed extract function to emacs
+
+	* bike/refactor/extractMethod.py: Added support for extracting
+	expressions into methods (e.g.  a = 1+2   ->  a = self.oneplustwo())
+	Added support for extracting functions.
+
+2002-05-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Extract Method pretty much
+	finished. Now on with the testing...
+
+2002-05-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added extract method support
+	for idle
+
+2002-05-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bike.el: implemented extract-method for emacs
+
+	* bike/bikefacade.py: Exposed extract-method to the outside world
+
+	
+2002-05-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Implemented simple extract
+	method
+
+2002-04-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/matchTokensToAST.py: The 'new' addtokens. Instead
+	of each AST node getting its own slice of tokens, there is only
+	one token list and each node has 2 linked list iterators pointing
+	to the start and end of its tokens in within it.
+	Thus the process of calculating the position of these iterators is
+	now called 'token matching' rather than 'adding tokens to ast'.
+
+	Having only 1 token stream vastly simplifies things. There are no
+	consistency problems when renaming or moving tokens, and no need
+	to 'divide' the comments amongst the AST nodes. 
+	This enables one matching algorithm to be able to cater for all
+	ast nodes without specialized logic.
+	
+	* bike/parsing/vector.py, bike/parsing/doublelinkedlist.py:
+	containers which support the same bi-directional iterator
+	interface. Used in refactoring the parsing module to use a linked
+	list of tokens
+
+2002-04-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Removed use of tokens
+
+---------------------- 0.4.3 ------------------------------------
+
+2002-04-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: fixed import problem in
+	windows
+
+	* bike/parsing/load.py: Added code so that if you select a
+	directory it will load all the modules and packages in it even if
+	it isnt a package (i.e. doesnt have a __init__.py), but would
+	recurse into non-package sub directories.
+
+	* bike/ui/*: This is no longer a package, since the only 2 files
+	are installed elsewhere.
+
+	* setup.py: Made BicycleRepairMan_Idle.py a root level
+	module. This means it can be used with idle by just adding
+	[BicycleRepairMan_Idle] to your .idle file.
+	
+
+2002-04-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Addtokens class now takes tokens in
+	constructor. The addTokens function is renamed to
+	addTokensToASTFromSrc. This will pave the way for Source nodes to
+	hold tokens rather than the source as a string
+
+	* bike/parsing/tokenhandler.py: Fixed bug which caused name ast
+	node to not be tokenized
+
+	* bike/parsing/load.py: Added check for __init__.py before
+	recursing into sub directories. This means that non-package sub
+	directories will not be recursed into. (i.e. the user must load
+	those seperately)
+
+	
+2002-03-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* NEWS: consolidated all README-version files into one NEWS file
+
+	* README*: updated documentation
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed another windows filename
+	isnt normalized bug
+
+	* bike/ui/bike.el: Added same functionality as for idle
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added load on save
+	functionality - means each saved python file gets automatically
+	imported into bicyclerepairman.
+
+2002-03-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added functionality to deduce the package
+	of the loaded module/package by inspecting parent directories for
+	__init__.py modules. This allows adding of new modules to an
+	existing AST.
+
+2002-03-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Added Evelyn's ammendment to doc 
+
+---------------------- 0.4.2 ------------------------------------
+
+2002-03-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* setup.py: Removed Icons stuff from setup
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed some bugs with idle
+	integration in windows:
+		- Ask if should rename dialogs dont take focus (which
+	makes selection disappear in windows)
+		- Filename normalizing means that filenames get compared correctly.
+
+2002-03-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: Changed the test package structure generation
+	code to add __init__.py modules to the packages. This will be used
+	to work with the new loader code (when I write it).
+
+2002-03-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed bug which was stopping
+	changed files from being reloaded on windows
+
+---------------------- 0.4.1 ------------------------------------
+
+2002-03-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed bug where rename method
+	prompts weren't visible to the user.
+
+	* bike/parsing/addtypeinfo.py: Fixed a bug which meant that
+	sourcenode wasnt getting added to default arguments, which caused
+	brm to crash when attempting to tokenize these. 
+
+
+---------------------- 0.4 --------------------------------------
+
+2002-03-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* setup.py: Removed bikegui and pyxmi from the setup
+	program. These are now deprecated.
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added the idle support module
+	to cvs.
+
+	* bike/parsing/tokenhandler.py: Simplified SimpleTokenHandler
+
+	* bike/parsing/extended_ast.py: Removed ExtendedNode base class -
+	it isnt needed (thanks Evelyn)
+
+	* bike/parsing/tokenutils.py: fixed bug in
+	_getOffsetOfTokensCorrespondingToParseTree which was including the
+	NL token in the offset it returned.
+
+	* bike/bikefacade.py: Changed signature of rename method
+	callback. It now sends filename and coords as args rather than
+	exposing the ast nodes to the client.
+
+2002-03-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/__init__.py: Moved bikefacade.py (from the ui package) into
+	the bike package. This is now referenced from __init__.py so a
+	client can do:   
+	import bike;  ctx = bike.load("mypath"); ctx.renameMethod()
+	
+
+	* bike/parsing/typeinfo.py: ModuleTypeinfo.getTypeOf()
+	functionality now uses the imported module *name* to check other
+	modules, rather than a reference to the module itself. This is to
+	allow module reloading.
+
+	* bike/parsing/extended_ast.py: Added 'addtypeinfo' call to Source
+	node. This is now done when the sourcenode is added to the parent
+	node rather than being run once over the whole tree. This
+	facilitates adding additional trees to the ast without having to
+	run the whole addtypeinfo step again.
+
+	* bike/parsing/addtypeinfo.py: Removed the subclasses stuff from
+	the classtypeinfo functionality. Doing this at initial-parse time
+	is too brittle, since a reload of a child source node could remove
+	(or add) a subclass from a base class.
+	Instead, subclasses are calculated at refactoring time.
+
+	
+
+2002-03-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Removed addfqn,
+	addparentscopeToNode and addSourcenode to nodes functionality from
+	the SourceModule, and integrated them with the first 'addtypeinfo'
+	pass. This almost halves the initial parsing time.
+
+
+2002-03-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Changed renameMethod signature to
+	take a method fqn rather than class and method parameters. This
+	allows the tests to take advantage of the same signature for
+	renameMethod,renameFunction and renameClass.
+
+	* bike/ui/bikeemacs.py: refactored to use the new bikefacade module
+
+	* bike/ui/bikefacade.py: New module which provides easy interface
+	into brm, for integrating into IDEs.
+
+	* bike/parsing/test_addtypeinfo.py: Added recursion handling for
+	things like a=a() (just catches the runtime error)
+
+2002-02-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: found a problem with lambdas - they
+	take the reference from the outer scope. If the reference is a
+	loop variable (e.g. for i in blah) then it is reassigned which
+	knackers the closure.
+	Solution -  lambda i=i: doSomethingWith(i)
+
+	* bike/ui/bikegui.py: removed reliance on tokens
+
+	* bike/parsing/tokenhandler.py: added getStartCoords() and
+	getEndCoords() functions.
+	
+
+2002-02-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* */setpath.py: code which insures pythonpath includes path
+	to the bike module (used for running test scripts). This is
+	imported by most modules.
+	
+	* bike/parsing/extended_ast.py: moved addParentScopeToNodes()
+	functionality from addtypeinfo into Source class.
+
+	* bike/parsing/addtypeinfo.py: For deduced types (e.g. types got
+	from function calls), the closure of the type deducing function is
+	put in the typeinfo rather than the type itself. The closure is
+	then run at lookup.
+	This facilitates lazy loading, and means source modules can be
+	reloaded without invalidating the typeinfo objects.
+	
+2002-02-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikeemacs.py: Added reload source functionality
+
+	* bike/ui/bike.el: Added support for renameMethod - prompts user
+	for types that brm can't deduce
+
+2002-02-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikeemacs.py: New support for emacs
+
+	* bike/parsing/addtypeinfo.py: Fixed bug which was causing
+	inheritance specs not to be renamed
+
+	* bike/parsing/output.py: Added some code to preserve level of
+	indent in multiline (comma ended) statements (e.g. function
+	arguments, class inheritence args etc...). This really needs
+	reworking into a general solution, but works 70% of the time for
+	now.
+
+2002-01-31  Phil Dawes  <pdawes@bea.com>
+
+	* bike/parsing/output.py: Added comment indenting code which
+	should preserve the indent level of comments
+
+2002-01-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Added functionality to rename the
+	function and class ref in 'import a.b.theFunction and from a
+	import theClass' type statements
+
+	* bike/parsing/renameFunction.py: new refactoring
+	
+	* bike/parsing/tokenhandler.py: Added code to update the typeinfo
+	objects of the parent scope and the Top node. This enables renames
+	to be carried out more than once on the same ast
+
+	* bike/parsing/addtypeinfo.py: Removed node.typeinfo.fqn. refactor
+	code should now use node.fqn
+
+2002-01-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Added token functionality to
+	Name. Removed the getPreceedingTokens() stuff - the getTokens()
+	now returns all tokens including preceeding comments, tokens
+	etc... getNodeTokens() returns just the tokens associated with the
+	node. This is consistent across all the tokenhandler base classes.
+
+	* bike/parsing/tokenutils.py: Fixed bug in _appendTokens where
+	the src 'raise foo' would result in 'raise' being picked up when
+	searching for 'foo' because both tokens are of the same type (name).
+
+2002-01-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Added code to class tokenizer to
+	delegate tokens to the baseclass spec (i.e. bah in 
+	'class foo(bah):'). 
+	
+	* bike/parsing/tokenhandler.py: Class handler stuff to output
+	tokens (see above). This means that renameClass now renames class
+	refs in baseclass specs.
+	
+2002-01-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Fixed a bug which stopped classes
+	that inherited from classes not in the ast from having method
+	declarations renamed.
+
+2002-01-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Added support for handling line breaks.
+   	    i.e.   if foo and \
+	              bah:
+
+	* bike/refactor/renameClass.py: Started new refactoring -
+	renameClass
+
+	* bike/parsing/addtypeinfo.py: removed 'typing indirect recursive
+	functions causes stack overflow' bug
+
+	* bike/refactor/renameMethod.py: Refactored the code so that the
+	renameMethodReferences is done once, with a list of all the
+	classes (in the hierarchy) to match.
+	
+
+2002-01-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Now renames methods on all
+	related classes (base classes and sub classes).
+
+	* doc/*: added some html documentation
+	
+2002-01-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Did some major refactoring and
+	removed all the code which is functionally duplicated in the
+	addtypeinfo module.
+
+	* bike/parsing/addtypeinfo.py: Spruced up the type inference
+	stuff.
+	ModuleTypeInfo now handles from foo import * by storing a list of
+	other modules to search.
+
+2002-01-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Save now returns a list of the files modified
+
+2002-01-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Added lazy tokenization. Source
+	node now parses the source (rather than being handed the ast).
+
+2002-01-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Added lazy saving. Files are only saved
+	if source modified.
+ 
+	* bike/testutils.py: Added new utility to find an ast node in a
+	tree based on attributes of the node. 
+	e.g. getMatchingASTNode(ast,"Function",name="foo")
+ 
+2002-01-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added functionality to look for
+	method and ref renames in sub classes
+
+2002-01-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Added support for imports, import
+	from and import as statements
+
+2002-01-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Fixed bug where method call was
+	split over 2 lines. The problem is that the tokenlist contains the
+	NL, but the parsetree doesnt, so the matching wasnt working. See
+	addtokens test_doesntBarfWhenMethodCallSplitOverTwoLines for details.
+
+	* bike/parsing/brmtransformer.py: Added 2 classes which override
+	Print and Println, and return the child nodes in the desired order
+	(they are the wrong way round as they come out of
+	ast.py). The print_stmt method returns these.
+
+	* bike/parsing/output.py: Added code to handle spacing with commas
+	and stream operators
+
+2002-01-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/test_renameMethod.py: Refactored tests so that
+	BikeGUI can use them (through template method).  Tests are now
+	split into RenameMethodTests,
+	RenameMethodReferenceTests_ImportsClass and
+	RenameMethodReferenceTests_doesntImportClass. This is because
+	bikegui 
+	
+2002-01-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikegui.py: Added dialog to ask user if want to rename
+	method reference (for cases where the type engine can't deduce the
+	type of the instance)
+
+2002-01-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikegui.py: Added a simple gui for renameMethod
+
+2002-01-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added functionality to strip of preceeding
+	directories from package structures. (so if you load
+	'/usr/local/python2.2/compiler', the root package is 'compiler')
+	
+	* bike/parsing/load.py: Added load_readonly(), which doesn't do the
+	addtokens step. 
+	Also added code to enable load() to be called more than once, to
+	add new files and packages to the tree.
+	Moved ui messages into constants module
+	
+2002-01-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/brmtransformer.py: removed addTokens() step from
+	parse(), so that it must be called seperately. This is because it
+	isn't complete, and imposes quite a performance penalty. (and it's
+	not needed by pyxmi). Updated all the tests to reflect this.
+
+2002-01-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py :  Added getSubClasses()
+	functionality to class typeinfo.
+
+2001-12-30  Phil Dawes  <pdawes@users.sourceforge.net>
+	* bike/*: Fixed path bugs for windows platform. All tests run on
+	win32 python now.
+	
+2001-12-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Added 'self' type to function
+	typeinfo. This means renameMethod can handle self.theMethod()
+	automatically.
+
+2001-12-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* pyxmi: Wrote little tool to create xmi representation of python
+	code. Suitable for loading into argouml.
+	
+	* bike/ui/bikecli.py: Added progress meter support. (also in
+	addtokens.py, renameMethod.py, load.py and output.py
+
+2001-12-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Fixed bug where function call
+	returning instance resulted in crash. 'e.g. e().f()'
+
+2001-12-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Reworked addtokens scheme to 'get all
+	tokens for node, and then pass them to children to take their
+	nodes'. This makes for a much easier time processing tokens.
+
+2001-12-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Changed Getattr rename
+	functionality to work when attribute token isn't second token of
+	node tokenlist
+
+	* bike/refactor/test_renameMethod.py: refactored renameMethod
+	tests into generic abstract base class. These are now used by the
+	ui package (rather than vice versa)
+
+	* bike/ui/bikecli.py: Added code to tell you how many changes have
+	been made, and advice on what might be wrong if this number is 0.
+
+2001-12-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Added getNodeTokens()
+	implementation to miss out any preceeding cruft not picked up by
+	addtoken functionality on previous nodes.
+
+2001-12-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Changed renameMethodDefinition to
+	work with nested methods (utilising the new typeinfo.fqn stuff).
+	Removed findclass and findmethod.
+
+2001-12-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikecli.py: Modified prompt message a bit. Added actual
+	standard io stuff so that it works with a user input as well as
+	through the test harness.
+
+	* bike/refactor/renameMethod.py: Modified RenameMethodReferences
+	to create a stack of scopes. The code uses the typeinfo from each
+	scope to determine the type of references, and if it can't find
+	the type there, it checks its own references deduced from the
+	classname passed in. I.e. it assumes that the classname is a
+	class, even if it can't find the definition, and renames instances
+	derived from it.
+
+	Also ammended the 'prompt user callback' code to only ask the user
+	if the type engine doesnt know the type of the instance
+	expression. (before now it was prompting if the type was not the
+	same as the input classname)
+
+2001-12-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikecli.py: Added code to handle prompting the user for
+	whether the method reference should be renamed.
+
+	* bike/refactor/renameMethod.py: Added code to prompt user when
+	type of object instance isn't known
+
+2001-12-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor.py: now takes advantage of typeinfo stuff to
+	deduce types of references
+	
+2001-12-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: New classes to deduce the types of
+	references. Adds a typeinfo attribute to each scope ast node,
+	which maps reference names to their types (currently as strings).
+
+2001-11-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added stack to maintain
+	references to object instances while visiting package structure
+
+2001-11-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added support for 'from foo
+	import *'
+	
+	* bike/ui/test_bikecli.py: Refactored tests so that all the single
+	file tests are exercised in a package hierarchy context.
+
+2001-11-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added support to rename methods
+	based on imported classes
+
+2001-11-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Refactored code (took out
+	RenameMethod class, since wasnt using instance state). Added
+	support for compound references (a.b.c.foo)
+
+2001-11-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: removed. (see load.py instead)
+
+	* bike/refactor/renameMethod.py: Added support for fully qualified
+	classnames in _findClass. e.g. a.b.bah.foo. This means that the ui
+	now supports renaming package nested methods (but not their
+	references).
+
+2001-11-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing: Added fixes to parser module to reflect changes in
+	python 2.2 compiler module
+
+2001-11-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: new function 'save' saves an entire ast
+	tree
+
+	* bike/refactor/renameMethod.py: Adapted to take an ast rather
+	than source file
+
+2001-11-14  Phil Dawes  <pdawes@bea.com>
+
+	* bike/parsing/load.py: Replacement for load_application.py using
+	Juergen's pythius loader code. load() hierarchically loads a bunch
+	of packages and modules into a big AST.
+
+	* bike/parsing/extended_ast.py: Fleshed out Package and Top nodes
+	to support hierarchical module ast
+
+
+2001-11-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: Fixed import visitor code to
+	handle comma seperated imports. (i.e. import foo,bar). Added code
+	to recognise imports via a from clause (i.e. from foo import bar)
+
+	Removed Imports.py. Integrated code into load_application
+	
+
+2001-11-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: Added load_application and
+	Imports modules back into build. Started writing tests for them.
+
+	
+2001-11-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/brmtransformer.py : Rewrote this to override the
+	methods which create nodes at the root of the parse. This means
+	that a few methods adding parser nodelists to ast nodes should
+	cater for practically all the AST nodes.
+
+	* bike/parsing/tokenhandler.py (GetattrTokenHander.renameAttr):
+	added renameAttr method which renames the attribute in the object
+	state, and in the corresponding tokens.  This is a very brittle
+	implementation, but will be fixed as new functionality is
+	added. (it's the simplist thing right now)
+
+	* bike/parsing/addtokens.py (AddTokens.visitGetattr): added
+	token support for getattr
+
+	* bike/parsing/tokenutils.py: Added getTokensPreceedingNodes,
+	which takes a parsetree of nodes and returns all the tokens before
+	the node represented by the parsetree. This is important because
+	until there is an token-handling implementation of all the ast
+	nodes, some tokens will be missed. By eating the tokens in between
+	the implemented ast nodes, this ensures all the tokens will be
+	outputted at the end.
+
+	
+2001-10-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	Created new CVS module, which makes use of distutils much more
+	uniform.
+	
+	* setup.py: Created distutils setup stript: 
+
+2001-10-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: Code to handle spacing in inline comments
+
+	* refactor/renameMethod.py: Started code to handle references when
+	object is created in same scope
+
+
+2001-10-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: spaces in conditionals (a == b etc..)
+
+	* parsing/tokenutils.py: Refactored code in TokenList to handle
+	rearranging indent/dedent tokens so that whole-line comments are
+	indented with the things they comment. The transformations are now
+	done after the initial scan (slower, but easier to follow)
+	
+	
+2001-10-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: ensured a.b not seperated by spaces. 
+
+	
+2001-10-22  Phil Dawes  <pdawes@users.sourceforge.net>
+	
+	* parsing/output.py: Code to seperate a=b with spaces (a = b)
+
+	* ui/test_cli.py: Merged cli tests with renameMethod tests to
+	ensure all tests work through the cli
+
+2001-10-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* */testall.py: unified testing scripts so that all tests can be
+	run from one place
+	
+2001-10-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ui/cli.py: Added simple command line interface.
+
+2001-10-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: Finished simple ast->string functionality
+	
+2001-10-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* testall.py: added master test script
+
+	* parsing/tokenhandler.py (FunctionTokenHandler.rename): added
+	rename a function and keep tokens in sync functionality
+
+
+2001-10-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: started tokens -> string functionality
+
+2001-10-07  Phil Dawes  <pdawes@users.sourceforge.net>
+	* refactor/renameMethod.py: very basic findClass, findMethod
+	functionality. Needs refactoring into analysis package, and
+	merging with existing code
+	
+2001-10-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* refactor/simplediff.py: wrote a simple diff utility to support
+	writing top down tests. (i.e. do a renameMethod, then assert that
+	the diff is correct)
+
+	
+2001-10-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* refactor/renameMethod.py: Got fedup with trying to secondguess
+	what the parser module should do. Decided to do some top-down
+	proper XP style development. Started with implementing the
+	renameMethod story.
+
+2001-10-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/test_addtokens.py: refactored tests so that they use
+	brmtransformer to get a node, rather than mocking it.
+
+2001-09-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/brmtransformer.py: Added nodelist to pass_stmt
+	
+2001-09-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/addtokens.py (AddTokens.visitModule): finished method
+
+	* parsing/tokenutils.py
+	(TokenConverter.getTokensUptoLastNewlineBeforeCode): method added
+
+2001-09-27  Phil Dawes  <pdawes@users.sourceforge.net>
+	
+	* parsing/addtokens.py: started visitmodule() impl 
+
+	* parsing/extended_ast.py: Added tokens support to Module
+
+2001-09-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/test_addtokens.py Refactored tests. Made up better names.
+
+2001-09-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	Laptop broke. Continuing with an older version of the code (hence
+	the gap in changelog)
+
+	* parsing/tokenutils.py (TokenConverter.getTokensToColon): Added
+	function which just gobbles tokens to the next colon. Refactored
+	getTokensStartBlock() to use this instead of walking the nodelist,
+	since I think all 
+
+	* parsing/addtokens.py (AddTokens.visitFunction): Now that
+	function and class no longer need to pass in partial nodelists,
+	the code is common. Refactored common code into
+	visitCompoundNode().
+
+	(hence the gap in the changelog)
+	
+	* parsing/tokenhandler.py: removed the preceeding tokens code -
+	you ain't gonna need it!
+
+	* parsing/test_addtokens.py: changed visitclass tests to use
+	mockobjects
+
+2001-09-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/tokenhandler.py: 
+
+	* parsing/*: Integrated code with bike parsing package
+
+	Split tokenhandler base classes into seperate module
+	Merged brmast stuff into extended_ast package
+	
+	
+2001-09-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: Added more unit tests 
+
+2001-09-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: Added more unit tests 
+
+
+2001-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_addtokens.py: Added some mock objects and tests
+	
+2001-08-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: beefed up the unit tests a bit
+
+2001-08-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* brmtransformer.py: This module now just contains code to add the
+	nodelist member to each ast node as the compiler generates
+	it. This is so the code in addtokens has access to the original
+	python parser nodes to generate tokens from.
+
+	* addtokens.py: Moved the code to add the tokens to the ast nodes
+	to this module. It now relies on there being a 'nodelist' member
+	on each ast object, containing the original python parser
+	nodelist.
+
+	* brmast.py: Added hack to retrofit TokenHandler base class to
+	existing compiler.ast classes. This means that we no longer have
+	to include compiler classes with the distribution. 
+	Not sure if this is completely legal - doesn't work with jython.
+
+	Removed stock Python compiler classes from src tree.
+	
+
+2001-08-27  Phil Dawes  <pdawes@users.sourceforge.net>
+	Set about reimplementing the token stuff - will now add tokens to
+	ast objects *after* the nodes have been processed by the compiler
+	module.
+	
+2001-08-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Added support for tokenising strings as well as
+	files.
+
+	* test_tokenutils.py: removed testdata directory, and moved all
+	the testdata into this module, now that the tokenutils stuff can
+	take strings as well as files
+
+	* brmtransformer.py: Renamed TransformerWithTokens to Transformer,
+	now that it's in a seperate module.
+
+	* brmast.py: Refactored the added token code out of ast module
+	into this one. Created a seperate mixin called TokenHandler rather
+	than sticking this code in the Node base class. Each class now
+	re-inherits this baseclass.
+	Unfortunately this means that I had to modify the transformer.py
+	file to import brmast rather than ast. Need to think of a better
+	way of doing this.
+
+2001-08-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* brmtransformer.py: Created new brmtransformer module and
+	refactored token code from transformer.Transformer into seperate
+	class TransformerWithTokens.  Refactored common code from
+	funcdef() and classdef() into do_compound_stmt()
+
+	* transformer.py: Now that all new code is factored out, reverted
+	to original transformer module from Python-2.1/Tools/compiler.
+
+	* tokenutils.py: Added code to alter DEDENT token line numbers
+	when they are rearranged
+
+2001-08-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Added code to do token reordering to ensure that
+	comments immediately before a block of code are placed after the
+	previous block DEDENT token.
+
+2001-08-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* transformer.py: tidied up code, and released prototype
+
+2001-08-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ast.py: Refactored management of tokens into base Node
+	class. Removed code from Class, and moved node->token conversion
+	to transformer.py
+
+	* transformer.py: See above
+	
+2001-08-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ast.py: Added support for tokens in 'Class' nodes. 'Class' uses
+	nodes passed to convert to tokens using TokenConverter.
+
+	
+2001-08-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Started TokenConverter class to convert python
+	parser nodes to tokens.
+
+	* test_tokenutils.py: unit tests for above
+
+------------------  One year later... -------------------------
+
+
+2000-10-21 19:02  gwilder
+
+	* context.py, refactor/.cvsignore, refactor/NewClass.py,
+	refactor/Refactor.py, refactor/__init__.py:
+	
+	first refactoring: NewClass
+
+2000-10-21 18:56  gwilder
+
+	* kickstand/: test_HasFromStar.py, test_IsClass.py,
+	test_IsGlobal.py, test_all.py, test_context.py,
+	test_load_application.py, testdata/HasFromStar_tf1.py,
+	testdata/HasFromStar_tf2.py, testdata/IsGlobal_tf1.py,
+	testdata/load_application_tf1.expected,
+	testdata/load_application_tf1.py,
+	testdata/rf_addclass_tf1.expected, testdata/rf_addclass_tf1.py:
+	
+	more tests
+
+2000-10-21 18:55  gwilder
+
+	* analysis/: HasFromStar.py, IsClass.py, IsGlobal.py,
+	Superclasses.py, TODO:
+	
+	more analysis functions
+
+2000-10-21 18:38  gwilder
+
+	* parsing/: .cvsignore, Imports.py, README, TODO, __init__.py,
+	extended_ast.py, load_application.py:
+	
+	parse and load a whole app.
+
+2000-10-13 19:32  gwilder
+
+	* INSTALL, analysis/.cvsignore, analysis/IsClass.py,
+	analysis/IsGlobal.py, analysis/README, analysis/TODO,
+	analysis/__init__.py, assembly/genpy.py, kickstand/test_IsClass.py,
+	kickstand/test_IsGlobal.py, kickstand/test_all.py,
+	kickstand/testdata/.cvsignore, kickstand/testdata/IsClass_tf1.py,
+	kickstand/testdata/IsGlobal_tf1.py:
+	
+	new analysis functions; install instructions; testsuite additions.
+
+2000-09-28 00:59  eris
+
+	* .cvsignore, CHANGES, README, assembly/.cvsignore,
+	disassembly/.cvsignore, kickstand/.cvsignore,
+	kickstand/test_common.py, kickstand/treefailtest.py,
+	kickstand/treematchtest.py, kickstand/unequalvars.py,
+	sprocket/.cvsignore, sprocket/common.py, sprocket/common.txt:
+	
+	
+	added .cvsignore files in each dir got the unit test for
+	sprocket/common.py working, added files for that test.
+
+2000-09-06 01:21  jhermann
+
+	* CHANGES, INSTALL, README, TODO:
+	
+	Added administrative files
+
+2000-09-05 22:13  jhermann
+
+	* assembly/__init__.py, disassembly/__init__.py,
+	kickstand/__init__.py, sprocket/__init__.py:
+	
+	Made the inits non-empty
+
+2000-09-05 22:11  jhermann
+
+	* __init__.py:
+	
+	Minor correction
+
+2000-09-01 18:33  jhermann
+
+	* kickstand/__init__.py, kickstand/test_fsm.py,
+	kickstand/test_regast.py, sprocket/__init__.py, sprocket/common.py,
+	sprocket/fsm.py, sprocket/regast.py:
+	
+	Initial source checkin (2000-09-01)
+
+2000-09-01 18:26  jhermann
+
+	* .cvsignore, __init__.py, assembly/__init__.py, assembly/genpy.py,
+	disassembly/__init__.py, disassembly/ast.py, disassembly/consts.py,
+	disassembly/transformer.py:
+	
+	Initial source checkin (2000-09-01)
+
+2000-09-01 18:22  jhermann
+
+	* README:
+	
+	Additions by shae
+
+2000-08-19 01:35  eris
+
+	* README:
+	
+	
+	new dir structure by snibril aka Jürgen Herrman first stab at a
+	tree matcher in common.py
+
+2000-08-01 01:44  jhermann
+
+	* README:
+	
+	Added a readme dummy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/INSTALL	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,17 @@
+Bicycle Repair Man - a Python Refactoring Browser
+=================================================
+
+$Id: INSTALL,v 1.4 2002/03/29 13:10:49 pdawes Exp $
+
+-----------------------------------------------------------------------------
+
+Bicycle Repair Man requires Python 2.2 and above. 
+
+Run 
+% python setup.py install
+
+
+Then look for at the relevant README file to integrate Bicycle Repair
+Man with your IDE.
+
+-----------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/NEWS	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,98 @@
+Main highlights of each new version. See ChangeLog for a more detailed
+description of changes.
+
+Version 0.9
+-----------
+
+This version removes the requirement to load files into
+bicyclerepairman before refactoring. Instead, it searches the
+PYTHONPATH (and the path in which the file being queried is in). This
+allows 'findDefinition' queries to be made on references
+(e.g. classes, methods) where the definition is in the python library.
+
+
+Version 0.8
+-----------
+
+This release improves on the internal type-deduction engine to handle
+variables and attributes. To reflect this, 'rename' now works on
+variables and attributes, in addition to methods, functions and
+classes. This release also adds vim support (thanks to Marius Gedminas
+and Matt Yeates for this)
+
+Version 0.7
+-----------
+
+This release includes a totally re-written type querying engine, which
+is much faster and paves the way for new refactorings. It also adds
+the 'FindReferences' and 'FindDefinition' query to emacs and idle. 
+
+
+Version 0.6
+-----------
+
+This release adds undo functionality to the mix, and beefs up the idle
+and emacs integration so that code is automatically imported into brm
+when you load a file into a buffer.
+
+
+Version 0.5
+-----------
+
+This release adds the ExtractMethod refactoring
+
+
+Version 0.4
+-----------
+
+This release adds support for IDLE (see README.idle), and fixes a few
+bugs. The CLI and GUI interfaces are now deprecated and have been
+removed from this release.
+
+
+
+Version 0.3
+-----------
+
+This release adds the RenameClass and RenameFunction refactorings.
+It also contains the initial xemacs integration functionality (see
+README.xemacs).
+
+
+
+Version 0.2
+-----------
+
+This release adds a simple GUI for renaming methods - run bikegui.py
+after installation.
+
+There's also some upgrades to pyxmi. It should now be able to generate
+xmi to model all generalizations (including cross-package ones).
+N.B. pyxmi.py is now called py2xmi.py. See changelog for reasons!
+
+
+
+Version 0.1
+-----------
+
+This is the first release of Bicycle Repair Man. It requires python
+version 2.2 and above.
+
+This version supports a partial implementation of the RenameMethod
+refactoring through a command line interface. 
+
+It automatically renames the method and references to the method that
+it can deduce. It asks you about method references it can't deduce the
+instance type of.
+
+This software should be considered alpha, and may damage your source
+files - backup your sources before use!
+
+See INSTALL for installation and usage instructions.
+
+
+N.B. This package also contains pyxmi - a little python -> xmi tool I
+cobbled together out of the bicycle repair man parsing package. It
+generates an xmi file out of a source-file or package-structure,
+suitable for loading into the argouml tool. See
+http://argouml.tigris.org.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/PKG-INFO	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: bicyclerepair
+Version: 0.9
+Summary: Bicycle Repair Man, the Python refactoring tool
+Home-page: http://bicyclerepair.sourceforge.net
+Author: Phil Dawes
+Author-email: pdawes@users.sourceforge.net
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,70 @@
+Bicycle Repair Man - a Python Refactoring Browser
+=================================================
+
+Copyright (c) 2000 by Shae Erisson <shae@lapland.fi>
+Copyright (c) 2001-3 by Phil Dawes <pdawes@users.sourceforge.net>
+
+All rights reserved, see COPYING for details.
+
+$Id: README,v 1.7 2003/08/24 19:48:43 pdawes Exp $
+
+-----------------------------------------------------------------------------
+
+Bicycle Repair Man is the Python Refactoring Browser, helping
+Pythonistas everywhere glide over the gory details of refactoring their
+code. Watch him extract jumbled code into well ordered classes. Gasp, as
+he renames all occurrences of a method. Thank You, Bicycle Repair Man!
+
+execute ./testall.py to run all the tests
+
+see INSTALL for installation instructions (uses distutils).
+
+see README.idle, README.emacs etc.. for instructions on how to
+integrate bicyclerepairman into supported IDEs.
+
+-----------------------------------------------------------------------------
+
+
+What's Python? 
+
+Python is a programming language. To find out more
+about it, go to the Python Homepage at http://www.python.org/
+  
+
+What's a Refactoring Browser? 
+
+A Refactoring Browser is an editor that automates Refactorings. The
+first Refactoring Browser was written by Dr. Don Roberts and Dr. John
+Brant at the University of Illinois in Urbana-Champagne. Dr. Don
+Roberts wrote his Ph.D. thesis on the design and implementation of the
+Refactoring Browser. For more detail, read the aforementioned thesis
+at http://st-www.cs.uiuc.edu/~droberts/thesis.pdf
+  
+
+What's a Refactoring? 
+
+A Refactoring is a behaviour preserving change to source code. Some
+Refactorings are RenameVariable, RenameClass, RenameMethod,
+PullUpMethod, and PushDownVariable. Lots of people say it's very easy
+to just type a different name in where your class, method, or variable
+is defined. That's not always a refactoring though.  The Refactoring
+Browser is smart enough to rename every reference to your class,
+method or variable. If you've ever renamed a variable and broken
+classes in widely scattered parts of your system, you might be happier
+using a Refactoring Browser. A Refactoring Browser operates on any of
+method, function, class, or variable. It can add, delete, rename, move
+up down or sideways, inline and abstract. There are some operations
+that are specific to one of the three types, such as abstracting a
+variable into accessors, or turing several lines of code into a
+separate method.
+
+For more information on Refactoring, check out the websites of Martin
+Fowler at http://www.martinfowler.com/ and his Refactoring Site at
+http://www.refactoring.com/ .  
+
+
+Why Bicycle Repair Man?
+
+The Bicycle Repair Man was a superhero in a Monty Python skit, his
+special power was repairing bicycles. 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.emacs	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,115 @@
+Instructions for running Bicycle Repair Man through emacs/xemacs
+----------------------------------------------------------------
+
+N.B. You need xemacs / emacs 21 or above.
+
+The emacs integration utilises the excellent 'Pymacs' package, written
+by François Pinard, which integrates python with emacs. A copy of this
+software is included with this package.
+
+
+There are 3 steps to installing bicyclerepairman for emacs:
+
+1) Install the base bicyclerepairman package
+
+2) Install the Pymacs package (if you haven't already got it)
+
+3) Modify your .emacs to active the bicyclerepairman functionality
+
+See the sections below for instructions on doing each of these.
+
+WINDOWS USERS: 
+You need to have both the python executable and the scripts directory
+(e.g. c:\Python22/Scripts) in your path for Bicyclerepairman to work.
+
+There are a couple of niggles with brm/emacs on
+windows. See the comments at the end of this file.
+
+
+
+
+
+
+
+1) Installation of Base Bicyclerepairman:
+-----------------------------------------
+
+- install bicyclerepair man as per INSTALL
+
+
+2) Installation of Pymacs:
+--------------------------
+
+(You can skip this if you already have pymacs installed.
+
+- Go to the ide-integration/Pymacs-0.20 directory
+- Run 
+      python setup.py install
+- Run 
+      python setup-emacs.py -l <LISP DIR>    
+  OR  
+      python setup-emacs.py -E xemacs -l <LISP DIR>
+  Depending on your version of emacs.
+
+- Add the following into your .emacs or .xemacs/init.el:
+
+;; pymacs
+(autoload 'pymacs-load "pymacs" nil t)
+(autoload 'pymacs-eval "pymacs" nil t)
+(autoload 'pymacs-apply "pymacs")
+(autoload 'pymacs-call "pymacs")
+
+- Check that it has installed correctly:
+  (Taken from the pymacs README)
+
+
+    To check that `pymacs.el' is properly installed, start Emacs and give
+    it the command `M-x load-library RET pymacs': you should not receive
+    any error.  
+
+    To check that `pymacs.py' is properly installed, start
+    an interactive Python session (e.g. from a command shell) and type
+    `from Pymacs import lisp': you should not receive any error.  
+
+	To check that `pymacs-services' is properly installed, type
+	`pymacs-services' in a shell; you should then get a line ending
+	with "(pymacs-version VERSION)". Press ctrl-c to exit.
+
+
+If you have any problems, consult the README file included with the
+pymacs distribution. N.B. I renamed the setup script to setup-emacs.py
+to make it more intuitive and easier for windows users. I've also
+added a pymacs-services.bat file to allow it to run on windows.
+
+
+3) Activating the Bike/Emacs integration
+----------------------------------------
+
+Add the following to your .emacs or .xemacs/init.el, after the pymacs
+stuff:
+
+(pymacs-load "bikeemacs" "brm-")
+(brm-init)
+
+
+You need to be using python-mode for the bicyclerepairman menu to
+appear. If you haven't already, enable this with:
+
+(autoload 'python-mode "python-mode" "Python editing mode." t)
+(setq auto-mode-alist
+      (cons '("\\.py$" . python-mode) auto-mode-alist))
+
+
+
+Usage:
+------
+
+Load a python file into emacs. A BicycleRepairMan menu should appear.
+
+
+Windows GNU-Emacs users
+-----------------------
+
+The load dialog in windows GNU-Emacs doesn't seem to allow selection
+of directories. If this is the case for you, use 'M-x brm-load' to
+import a package hierarchy.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.idle	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,47 @@
+BicycleRepairMan_Idle.py is the name of the idle integration module.
+
+
+Installation on Python 2.3 or idlefork
+--------------------------------------
+1) Install Bicycle Repair Man (see INSTALL)
+
+2) Add the following to your ~/.idlerc/config-extensions.cfg:
+(NOTE - I had to put this in my
+<PYTHONLIBDIR>/idlelib/config-extensions.def for it to work correctly)
+
+[BicycleRepairMan_Idle]
+enable=1
+trace=0
+[BicycleRepairMan_Idle_cfgBindings]
+brm-find-references=
+brm-find-definition=
+brm-rename=
+brm-extract-method=
+brm-undo=
+
+Python sourcefile editor windows will now have a 'BicycleRepairMan'
+menu.
+
+
+
+Installation on python 2.2 version of idle
+------------------------------------------
+
+1) Install Bicycle Repair Man (see INSTALL)
+
+2) Add the following line to your <idle-installation>/config.txt or
+~/.idle:
+
+[BicycleRepairMan_Idle]
+
+
+Python sourcefile editor windows will now have a 'BicycleRepairMan'
+menu.
+
+
+
+Caveats
+-------
+
+Sometimes dialogs get lost behind windows. If things seem to have
+paused in a rename-method, try looking for a dialog.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,2 @@
+Instructions for installing bike.vim are in the file itself.
+See ide-integration/bike.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+# The root bicyclerepairman package
+# do:
+# ---------------------
+# import bike
+# ctx = bike.load()
+# ---------------------
+# to instantiate a bicyclerepairman context object
+
+
+from bikefacade import init, NotAPythonModuleOrPackageException, CouldntLocateASTNodeFromCoordinatesException, UndoStackEmptyException
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/bikefacade.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,274 @@
+import os
+import sys
+import compiler
+from parser import ParserError
+from bike.parsing.pathutils import getRootDirectory
+from bike.refactor import extractMethod
+from bike.refactor.rename import rename
+from bike.refactor.extractMethod import coords
+from bike.transformer.save import save as saveUpdates
+from bike.parsing.utils import fqn_rcar, fqn_rcdr
+from bike.parsing import visitor
+from bike.transformer.undo import getUndoStack, UndoStackEmptyException
+from bike.parsing.fastparserast import getRoot, Class, Function
+from bike.query.common import getScopeForLine
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
+from bike.query.findReferences import findReferences
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.refactor import inlineVariable, extractVariable, moveToModule
+from bike.parsing.load import Cache
+from bike import log
+
+def init():
+    #context = BRMContext_impl()
+    context = BRMContext_wrapper()
+    return context
+
+# the context object public interface
+class BRMContext(object):
+
+
+    def save(self):
+        """ save the changed files out to disk """
+
+    def setRenameMethodPromptCallback(self, callback):
+        """
+        sets a callback to ask the user about method refs which brm
+        can't deduce the type of. The callback must be callable, and
+         take the following parameters:
+          - filename
+          - linenumber
+          - begin column
+          - end column
+         (begin and end columns enclose the problematic method call)
+        """
+        
+    def renameByCoordinates(self, filename_path, line, col, newname):
+        """ an ide friendly method which renames a class/fn/method
+        pointed to by the coords and filename"""
+
+    def extract(self, filename_path, 
+                begin_line, begin_col,
+                end_line, end_col, 
+                name):
+        """ extracts the region into the named method/function based
+        on context"""
+
+    def inlineLocalVariable(self,filename_path, line, col):
+        """ Inlines the variable pointed to by
+        line:col. (N.B. line:col can also point to a reference to the
+        variable as well as the definition) """
+
+
+    def extractLocalVariable(self,filename_path, begin_line, begin_col,
+                             end_line, end_col, variablename):
+        """ Extracts the region into a variable """
+
+    def setProgressLogger(self,logger):
+        """ Sets the progress logger to an object with a write method
+        """
+        
+    def setWarningLogger(self,logger):
+        """ Sets the warning logger to an object with a write method
+        """
+
+    def undo(self):
+        """ undoes the last refactoring. WARNING: this is dangerous if
+        the user has modified files since the last refactoring.
+        Raises UndoStackEmptyException"""
+
+    def findReferencesByCoordinates(self, filename_path, line, column):
+        """ given the coords of a function, class, method or variable
+        returns a generator which finds references to it.
+        """
+
+    def findDefinitionByCoordinates(self,filename_path,line,col):        
+        """ given the coordates to a reference, tries to find the
+        definition of that reference """
+
+    def moveClassToNewModule(self,filename_path, line, 
+                             newfilename):
+        """ moves the class pointed to by (filename_path, line)
+        to a new module """
+
+        
+class NotAPythonModuleOrPackageException: pass
+class CouldntLocateASTNodeFromCoordinatesException: pass
+
+
+# Wrapper to ensure that caches are purged on each request
+class BRMContext_wrapper:
+    def __init__(self):
+        self.brmctx = BRMContext_impl()
+
+    def __getattr__(self,name):
+        return BRMContext_callWrapper(self.brmctx,name)
+
+
+class BRMContext_callWrapper:
+    def __init__(self,brmctx,methodname):
+        self.name = methodname
+        self.brmctx = brmctx
+
+    def __call__(self,*args):
+        Cache.instance.reset()
+        try:
+            return getattr(self.brmctx,self.name)(*args)
+        finally:
+            Cache.instance.reset()
+
+
+class BRMContext_impl(BRMContext):
+    
+    def __init__(self):
+        self.ast = getRoot()
+
+        # Used because some refactorings delegate back to the user.
+        # this flag ensures that code isnt imported during those times
+        self.readyToLoadNewCode = 1 
+        self.paths = []
+        getUndoStack(1)  # force new undo stack
+        if not getRoot().unittestmode:
+            log.warning = sys.stderr            
+        self.promptUserClientCallback = None
+
+    def _getAST(self):
+        return self.ast
+
+    # returns a list of saved filenames
+    def save(self):
+        savedfiles = saveUpdates()
+        return savedfiles
+
+    def setRenameMethodPromptCallback(self, callback):
+        self.promptUserClientCallback = callback
+
+
+    def normalizeFilename(self,filename):
+        filename = os.path.expanduser(filename)
+        filename = os.path.normpath(os.path.abspath(filename))
+        return filename
+
+    def extractMethod(self, filename_path, 
+                        begin_line, begin_column, 
+                        end_line, end_column, 
+                        methodname):
+        self.extract(filename_path, begin_line, begin_column,
+                     end_line, end_column,methodname)
+
+    def extractFunction(self, filename_path, 
+                        begin_line, begin_column, 
+                        end_line, end_column, 
+                        methodname):
+        self.extract(filename_path, begin_line, begin_column,
+                     end_line, end_column,methodname)
+
+    # does it based on context
+    def extract(self, filename_path, 
+                begin_line, begin_col,
+                end_line, end_col, 
+                name):
+        filename_path = self.normalizeFilename(filename_path)
+        extractMethod.extractMethod(filename_path,
+                                    coords(begin_line, begin_col), 
+                                    coords(end_line, end_col), name)
+
+    def inlineLocalVariable(self,filename_path, line, col):
+        filename_path = self.normalizeFilename(filename_path)
+        inlineVariable.inlineLocalVariable(filename_path,line,col)
+
+    def extractLocalVariable(self,filename_path, begin_line, begin_col,
+                             end_line, end_col, variablename):
+        filename_path = self.normalizeFilename(filename_path)
+        extractVariable.extractLocalVariable(filename_path,
+                                             coords(begin_line, begin_col),
+                                             coords(end_line, end_col),
+                                             variablename)
+
+    def moveClassToNewModule(self,filename_path, line, 
+                             newfilename):
+        filename_path = self.normalizeFilename(filename_path)
+        newfilename = self.normalizeFilename(newfilename)
+        moveToModule.moveClassToNewModule(filename_path, line, 
+                                       newfilename)
+
+    def undo(self):
+        getUndoStack().undo()
+
+    def _promptUser(self, filename, lineno, colbegin, colend):
+        return self.promptUserClientCallback(filename, lineno, colbegin, colend)
+
+
+    # must be an object with a write method
+    def setProgressLogger(self,logger):
+        log.progress = logger
+
+    # must be an object with a write method
+    def setWarningLogger(self,logger):
+        log.warning = logger
+
+
+    # filename_path must be absolute
+    def renameByCoordinates(self, filename_path, line, col, newname):
+        filename_path = self.normalizeFilename(filename_path)
+        Cache.instance.reset()
+        try:
+            self._setNonLibPythonPath(filename_path)
+            rename(filename_path,line,col,newname,
+                   self.promptUserClientCallback)
+        finally:
+            Cache.instance.reset()
+
+    def _reverseCoordsIfWrongWayRound(self, colbegin, colend):
+        if(colbegin > colend):
+            colbegin,colend = colend,colbegin
+        return colbegin,colend
+
+
+    def findDefinitionByCoordinates(self,filename_path,line,col):
+        filename_path = self.normalizeFilename(filename_path)
+        self._setCompletePythonPath(filename_path)
+        return findAllPossibleDefinitionsByCoords(filename_path,line,col)
+
+        
+    # filename_path must be absolute
+    def findReferencesByCoordinates(self, filename_path, line, column):
+        filename_path = self.normalizeFilename(filename_path)
+        self._setNonLibPythonPath(filename_path)
+        return findReferences(filename_path,line,column)
+        
+    def refreshASTFromFileSystem(self):
+        for path in self.paths:
+            self.ast = loadast(path, self.ast)
+
+    def _setCompletePythonPath(self,filename):
+        pythonpath = [] + sys.path  # make a copy
+        self.ast.pythonpath = pythonpath
+        
+    def _setNonLibPythonPath(self,filename):
+        if getRoot().unittestmode:
+            return
+        pythonpath = self._removeLibdirsFromPath(sys.path)
+        pythonpath = [os.path.abspath(p) for p in pythonpath]
+        self.ast.pythonpath = pythonpath
+
+    def _getCurrentSearchPath(self):
+        return self.ast.pythonpath
+    
+    def _removeLibdirsFromPath(self, pythonpath):
+        libdir = os.path.join(sys.prefix,"lib").lower()
+        pythonpath = [p for p in pythonpath
+                      if not p.lower().startswith(libdir)]
+        return pythonpath
+
+        
+def _deducePackageOfFile(filename):
+    package = ""
+    dot = ""
+    dir = os.path.dirname(filename)
+    while dir != ""and \
+          os.path.exists(os.path.join(dir, "__init__.py")):
+        dir, dirname = os.path.split(dir)
+        package = dirname+dot+package
+        dot = "."
+    return package
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/globals.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,6 @@
+try:
+    True = 1
+    False = 0
+except:
+    pass
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/log.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,8 @@
+import sys
+class SilentLogger:
+    def write(*args):
+        pass
+
+progress = SilentLogger()
+warning = SilentLogger()
+#warning = sys.stderr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/logging.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1995 @@
+#! /usr/bin/env python
+#
+# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# For the change history, see README.txt in the distribution.
+#
+# This file is part of the Python logging distribution. See
+# http://www.red-dove.com/python_logging.html
+#
+
+"""
+Logging module for Python. Based on PEP 282 and comments thereto in
+comp.lang.python, and influenced by Apache's log4j system.
+
+Should work under Python versions >= 1.5.2, except that source line
+information is not available unless 'inspect' is.
+
+Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging' and log away!
+"""
+
+import sys, os, types, time, string, socket, cPickle, cStringIO
+
+from SocketServer import ThreadingTCPServer, StreamRequestHandler
+
+
+try:
+    import thread
+except ImportError:
+    thread = None
+try:
+    import inspect
+except ImportError:
+    inspect = None
+
+__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
+__status__  = "alpha"
+__version__ = "0.4.5"
+__date__    = "4 June 2002"
+
+#---------------------------------------------------------------------------
+#   Miscellaneous module data
+#---------------------------------------------------------------------------
+
+#
+#_srcfile is used when walking the stack to check when we've got the first
+# caller stack frame.
+#If run as a script, __file__ is not bound.
+#
+if __name__ == "__main__":
+    _srcfile = None
+else:
+    if string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
+        _srcfile = __file__[:-4] + '.py'
+    else:
+        _srcfile = __file__
+    _srcfile = os.path.normcase(_srcfile)
+
+#
+#_startTime is used as the base when calculating the relative time of events
+#
+_startTime = time.time()
+
+#
+# Some constants...
+#
+
+DEFAULT_TCP_LOGGING_PORT    = 9020
+DEFAULT_UDP_LOGGING_PORT    = 9021
+DEFAULT_HTTP_LOGGING_PORT   = 9022
+DEFAULT_SOAP_LOGGING_PORT   = 9023
+DEFAULT_LOGGING_CONFIG_PORT = 9030
+SYSLOG_UDP_PORT             = 514
+
+#---------------------------------------------------------------------------
+#   Level related stuff
+#---------------------------------------------------------------------------
+#
+# Default levels and level names, these can be replaced with any positive set
+# of values having corresponding names. There is a pseudo-level, ALL, which
+# is only really there as a lower limit for user-defined levels. Handlers and
+# loggers are initialized with ALL so that they will log all messages, even
+# at user-defined levels.
+#
+CRITICAL = 50
+FATAL = CRITICAL
+ERROR = 40
+WARN = 30
+INFO = 20
+DEBUG = 10
+ALL = 0
+
+_levelNames = {
+    CRITICAL : 'CRITICAL',
+    ERROR    : 'ERROR',
+    WARN     : 'WARN',
+    INFO     : 'INFO',
+    DEBUG    : 'DEBUG',
+    ALL      : 'ALL',
+    'CRITICAL'  : CRITICAL,
+    'ERROR'     : ERROR,
+    'WARN'      : WARN,
+    'INFO'      : INFO,
+    'DEBUG'     : DEBUG,
+    'ALL'       : ALL,
+}
+
+def getLevelName(lvl):
+    """
+    Return the textual representation of logging level 'lvl'. If the level is
+    one of the predefined levels (CRITICAL, ERROR, WARN, INFO, DEBUG) then you
+    get the corresponding string. If you have associated levels with names
+    using addLevelName then the name you have associated with 'lvl' is
+    returned. Otherwise, the string "Level %s" % lvl is returned.
+    """
+    return _levelNames.get(lvl, ("Level %s" % lvl))
+
+def addLevelName(lvl, levelName):
+    """
+    Associate 'levelName' with 'lvl'. This is used when converting levels
+    to text during message formatting.
+    """
+    _acquireLock()
+    try:    #unlikely to cause an exception, but you never know...
+        _levelNames[lvl] = levelName
+        _levelNames[levelName] = lvl
+    finally:
+        _releaseLock()
+
+#---------------------------------------------------------------------------
+#   Thread-related stuff
+#---------------------------------------------------------------------------
+
+#
+#_lock is used to serialize access to shared data structures in this module.
+#This needs to be an RLock because fileConfig() creates Handlers and so
+#might arbitrary user threads. Since Handler.__init__() updates the shared
+#dictionary _handlers, it needs to acquire the lock. But if configuring,
+#the lock would already have been acquired - so we need an RLock.
+#The same argument applies to Loggers and Manager.loggerDict.
+#
+_lock = None
+
+def _acquireLock():
+    """
+    Acquire the module-level lock for serializing access to shared data.
+    This should be released with _releaseLock().
+    """
+    global _lock
+    if (not _lock) and thread:
+        import threading    #this had better work
+        _lock = threading.RLock()
+    if _lock:
+        _lock.acquire()
+
+def _releaseLock():
+    """
+    Release the module-level lock acquired by calling _acquireLock().
+    """
+    if _lock:
+        _lock.release()
+
+#---------------------------------------------------------------------------
+#   The logging record
+#---------------------------------------------------------------------------
+
+class LogRecord:
+    """
+    LogRecord instances are created every time something is logged. They
+    contain all the information pertinent to the event being logged. The
+    main information passed in is in msg and args, which are combined
+    using msg % args to create the message field of the record. The record
+    also includes information such as when the record was created, the
+    source line where the logging call was made, and any exception
+    information to be logged.
+    """
+    def __init__(self, name, lvl, pathname, lineno, msg, args, exc_info):
+        """
+        Initialize a logging record with interesting information.
+        """
+        ct = time.time()
+        self.name = name
+        self.msg = msg
+        self.args = args
+        self.levelname = getLevelName(lvl)
+        self.levelno = lvl
+        self.pathname = pathname
+        try:
+            self.filename = os.path.basename(pathname)
+            self.module = os.path.splitext(self.filename)[0]
+        except:
+            self.filename = pathname
+            self.module = "Unknown module"
+        self.exc_info = exc_info
+        self.lineno = lineno
+        self.created = ct
+        self.msecs = (ct - long(ct)) * 1000
+        self.relativeCreated = (self.created - _startTime) * 1000
+        if thread:
+            self.thread = thread.get_ident()
+        else:
+            self.thread = None
+
+    def __str__(self):
+        return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
+            self.pathname, self.lineno, self.msg)
+
+    def getMessage(self):
+        """
+        Return the message for this LogRecord, merging any user-supplied
+        arguments with the message.
+        """
+        msg = str(self.msg)
+        if self.args:
+            msg = msg % self.args
+        return msg
+
+#---------------------------------------------------------------------------
+#   Formatter classes and functions
+#---------------------------------------------------------------------------
+
+class Formatter:
+    """
+    Formatters need to know how a LogRecord is constructed. They are
+    responsible for converting a LogRecord to (usually) a string which can
+    be interpreted by either a human or an external system. The base Formatter
+    allows a formatting string to be specified. If none is supplied, the
+    default value of "%s(message)\\n" is used.
+
+    The Formatter can be initialized with a format string which makes use of
+    knowledge of the LogRecord attributes - e.g. the default value mentioned
+    above makes use of the fact that the user's message and arguments are pre-
+    formatted into a LogRecord's message attribute. Currently, the useful
+    attributes in a LogRecord are described by:
+
+    %(name)s            Name of the logger (logging channel)
+    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
+                        WARN, ERROR, CRITICAL)
+    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
+                        "WARN", "ERROR", "CRITICAL")
+    %(pathname)s        Full pathname of the source file where the logging
+                        call was issued (if available)
+    %(filename)s        Filename portion of pathname
+    %(module)s          Module (name portion of filename)
+    %(lineno)d          Source line number where the logging call was issued
+                        (if available)
+    %(created)f         Time when the LogRecord was created (time.time()
+                        return value)
+    %(asctime)s         Textual time when the LogRecord was created
+    %(msecs)d           Millisecond portion of the creation time
+    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
+                        relative to the time the logging module was loaded
+                        (typically at application startup time)
+    %(thread)d          Thread ID (if available)
+    %(message)s         The result of msg % args, computed just as the
+                        record is emitted
+    """
+    def __init__(self, fmt=None, datefmt=None):
+        """
+        Initialize the formatter either with the specified format string, or a
+        default as described above. Allow for specialized date formatting with
+        the optional datefmt argument (if omitted, you get the ISO8601 format).
+        """
+        if fmt:
+            self._fmt = fmt
+        else:
+            self._fmt = "%(message)s"
+        self.datefmt = datefmt
+
+    def formatTime(self, record, datefmt=None):
+        """
+        This method should be called from format() by a formatter which
+        wants to make use of a formatted time. This method can be overridden
+        in formatters to provide for any specific requirement, but the
+        basic behaviour is as follows: if datefmt (a string) is specified,
+        it is used with time.strftime() to format the creation time of the
+        record. Otherwise, the ISO8601 format is used. The resulting
+        string is returned.
+        """
+        ct = record.created
+        if datefmt:
+            s = time.strftime(datefmt, time.localtime(ct))
+        else:
+            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ct))
+            s = "%s,%03d" % (t, record.msecs)
+        return s
+
+    def formatException(self, ei):
+        """
+        Format the specified exception information as a string. This
+        default implementation just uses traceback.print_exception()
+        """
+        import traceback
+        sio = cStringIO.StringIO()
+        traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
+        s = sio.getvalue()
+        sio.close()
+        if s[-1] == "\n":
+            s = s[:-1]
+        return s
+
+    def format(self, record):
+        """
+        The record's attribute dictionary is used as the operand to a
+        string formatting operation which yields the returned string.
+        Before formatting the dictionary, a couple of preparatory steps
+        are carried out. The message attribute of the record is computed
+        using msg % args. If the formatting string contains "%(asctime)",
+        formatTime() is called to format the event time. If there is
+        exception information, it is formatted using formatException()
+        and appended to the message.
+        """
+        record.message = record.getMessage()
+        if string.find(self._fmt,"%(asctime)") >= 0:
+            record.asctime = self.formatTime(record, self.datefmt)
+        s = self._fmt % record.__dict__
+        if record.exc_info:
+            if s[-1] != "\n":
+                s = s + "\n"
+            s = s + self.formatException(record.exc_info)
+        return s
+
+#
+#   The default formatter to use when no other is specified
+#
+_defaultFormatter = Formatter()
+
+class BufferingFormatter:
+    """
+    A formatter suitable for formatting a number of records.
+    """
+    def __init__(self, linefmt=None):
+        """
+        Optionally specify a formatter which will be used to format each
+        individual record.
+        """
+        if linefmt:
+            self.linefmt = linefmt
+        else:
+            self.linefmt = _defaultFormatter
+
+    def formatHeader(self, records):
+        """
+        Return the header string for the specified records.
+        """
+        return ""
+
+    def formatFooter(self, records):
+        """
+        Return the footer string for the specified records.
+        """
+        return ""
+
+    def format(self, records):
+        """
+        Format the specified records and return the result as a string.
+        """
+        rv = ""
+        if len(records) > 0:
+            rv = rv + self.formatHeader(records)
+            for record in records:
+                rv = rv + self.linefmt.format(record)
+            rv = rv + self.formatFooter(records)
+        return rv
+
+#---------------------------------------------------------------------------
+#   Filter classes and functions
+#---------------------------------------------------------------------------
+
+class Filter:
+    """
+    The base filter class. Loggers and Handlers can optionally use Filter
+    instances to filter records as desired. The base filter class only allows
+    events which are below a certain point in the logger hierarchy. For
+    example, a filter initialized with "A.B" will allow events logged by
+    loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B"
+    etc. If initialized with the empty string, all events are passed.
+    """
+    def __init__(self, name=''):
+        """
+        Initialize with the name of the logger which, together with its
+        children, will have its events allowed through the filter. If no
+        name is specified, allow every event.
+        """
+        self.name = name
+        self.nlen = len(name)
+
+    def filter(self, record):
+        """
+        Is the specified record to be logged? Returns 0 for no, nonzero for
+        yes. If deemed appropriate, the record may be modified in-place.
+        """
+        if self.nlen == 0:
+            return 1
+        elif self.name == record.name:
+            return 1
+        elif string.find(record.name, self.name, 0, self.nlen) != 0:
+            return 0
+        return (record.name[self.nlen] == ".")
+
+class Filterer:
+    """
+    A base class for loggers and handlers which allows them to share
+    common code.
+    """
+    def __init__(self):
+        """
+        Initialize the list of filters to be an empty list.
+        """
+        self.filters = []
+
+    def addFilter(self, filter):
+        """
+        Add the specified filter to this handler.
+        """
+        if not (filter in self.filters):
+            self.filters.append(filter)
+
+    def removeFilter(self, filter):
+        """
+        Remove the specified filter from this handler.
+        """
+        if filter in self.filters:
+            self.filters.remove(filter)
+
+    def filter(self, record):
+        """
+        Determine if a record is loggable by consulting all the filters. The
+        default is to allow the record to be logged; any filter can veto this
+        and the record is then dropped. Returns a boolean value.
+        """
+        rv = 1
+        for f in self.filters:
+            if not f.filter(record):
+                rv = 0
+                break
+        return rv
+
+#---------------------------------------------------------------------------
+#   Handler classes and functions
+#---------------------------------------------------------------------------
+
+_handlers = {}  #repository of handlers (for flushing when shutdown called)
+
+class Handler(Filterer):
+    """
+    The base handler class. Acts as a placeholder which defines the Handler
+    interface. Handlers can optionally use Formatter instances to format
+    records as desired. By default, no formatter is specified; in this case,
+    the 'raw' message as determined by record.message is logged.
+    """
+    def __init__(self, level=ALL):
+        """
+        Initializes the instance - basically setting the formatter to None
+        and the filter list to empty.
+        """
+        Filterer.__init__(self)
+        self.level = level
+        self.formatter = None
+        #get the module data lock, as we're updating a shared structure.
+        _acquireLock()
+        try:    #unlikely to raise an exception, but you never know...
+            _handlers[self] = 1
+        finally:
+            _releaseLock()
+        self.createLock()
+
+    def createLock(self):
+        """
+        Acquire a thread lock for serializing access to the underlying I/O.
+        """
+        if thread:
+            self.lock = thread.allocate_lock()
+        else:
+            self.lock = None
+
+    def acquire(self):
+        """
+        Acquire the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.acquire()
+
+    def release(self):
+        """
+        Release the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.release()
+
+    def setLevel(self, lvl):
+        """
+        Set the logging level of this handler.
+        """
+        self.level = lvl
+
+    def format(self, record):
+        """
+        Do formatting for a record - if a formatter is set, use it.
+        Otherwise, use the default formatter for the module.
+        """
+        if self.formatter:
+            fmt = self.formatter
+        else:
+            fmt = _defaultFormatter
+        return fmt.format(record)
+
+    def emit(self, record):
+        """
+        Do whatever it takes to actually log the specified logging record.
+        This version is intended to be implemented by subclasses and so
+        raises a NotImplementedError.
+        """
+        raise NotImplementedError, 'emit must be implemented '\
+                                    'by Handler subclasses'
+
+    def handle(self, record):
+        """
+        Conditionally emit the specified logging record, depending on
+        filters which may have been added to the handler. Wrap the actual
+        emission of the record with acquisition/release of the I/O thread
+        lock.
+        """
+        if self.filter(record):
+            self.acquire()
+            try:
+                self.emit(record)
+            finally:
+                self.release()
+
+    def setFormatter(self, fmt):
+        """
+        Set the formatter for this handler.
+        """
+        self.formatter = fmt
+
+    def flush(self):
+        """
+        Ensure all logging output has been flushed. This version does
+        nothing and is intended to be implemented by subclasses.
+        """
+        pass
+
+    def close(self):
+        """
+        Tidy up any resources used by the handler. This version does
+        nothing and is intended to be implemented by subclasses.
+        """
+        pass
+
+    def handleError(self):
+        """
+        This method should be called from handlers when an exception is
+        encountered during an emit() call. By default it does nothing,
+        which means that exceptions get silently ignored. This is what is
+        mostly wanted for a logging system - most users will not care
+        about errors in the logging system, they are more interested in
+        application errors. You could, however, replace this with a custom
+        handler if you wish.
+        """
+        #import traceback
+        #ei = sys.exc_info()
+        #traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
+        #del ei
+        pass
+
+class StreamHandler(Handler):
+    """
+    A handler class which writes logging records, appropriately formatted,
+    to a stream. Note that this class does not close the stream, as
+    sys.stdout or sys.stderr may be used.
+    """
+    def __init__(self, strm=None):
+        """
+        If strm is not specified, sys.stderr is used.
+        """
+        Handler.__init__(self)
+        if not strm:
+            strm = sys.stderr
+        self.stream = strm
+        self.formatter = None
+
+    def flush(self):
+        """
+        Flushes the stream.
+        """
+        self.stream.flush()
+
+    def emit(self, record):
+        """
+        If a formatter is specified, it is used to format the record.
+        The record is then written to the stream with a trailing newline
+        [N.B. this may be removed depending on feedback]. If exception
+        information is present, it is formatted using
+        traceback.print_exception and appended to the stream.
+        """
+        try:
+            msg = self.format(record)
+            self.stream.write("%s\n" % msg)
+            self.flush()
+        except:
+            self.handleError()
+
+class FileHandler(StreamHandler):
+    """
+    A handler class which writes formatted logging records to disk files.
+    """
+    def __init__(self, filename, mode="a+"):
+        """
+        Open the specified file and use it as the stream for logging.
+        By default, the file grows indefinitely. You can call setRollover()
+        to allow the file to rollover at a predetermined size.
+        """
+        StreamHandler.__init__(self, open(filename, mode))
+        self.maxBytes = 0
+        self.backupCount = 0
+        self.baseFilename = filename
+        #self.backupIndex = 0
+        self.mode = mode
+
+    def setRollover(self, maxBytes, backupCount):
+        """
+        Set the rollover parameters so that rollover occurs whenever the
+        current log file is nearly maxBytes in length. If backupCount
+        is >= 1, the system will successively create new files with the
+        same pathname as the base file, but with extensions ".1", ".2"
+        etc. appended to it. For example, with a backupCount of 5 and a
+        base file name of "app.log", you would get "app.log", "app.log.1",
+        "app.log.2", ... through to "app.log.5". When the last file reaches
+        its size limit, the logging reverts to "app.log" which is truncated
+        to zero length. If maxBytes is zero, rollover never occurs.
+        """
+        self.maxBytes = maxBytes
+        self.backupCount = backupCount
+        if maxBytes > 0:
+            self.mode = "a+"
+
+    def doRollover(self):
+        """
+        Do a rollover, as described in setRollover().
+        """
+#       Old algorithm
+#        if self.backupIndex >= self.backupCount:
+#            self.backupIndex = 0
+#            fn = self.baseFilename
+#        else:
+#            self.backupIndex = self.backupIndex + 1
+#            fn = "%s.%d" % (self.baseFilename, self.backupIndex)
+#        self.stream.close()
+#        self.stream = open(fn, "w+")
+        self.stream.close()
+        if self.backupCount > 0:
+            for i in range(self.backupCount - 1, 0, -1):
+                sfn = "%s.%d" % (self.baseFilename, i)
+                dfn = "%s.%d" % (self.baseFilename, i + 1)
+                if os.path.exists(sfn):
+                    #print "%s -> %s" % (sfn, dfn)
+                    if os.path.exists(dfn):
+                        os.remove(dfn)
+                    os.rename(sfn, dfn)
+            dfn = self.baseFilename + ".1"
+            if os.path.exists(dfn):
+                os.remove(dfn)
+            os.rename(self.baseFilename, dfn)
+        self.stream = open(self.baseFilename, "w+")
+
+    def emit(self, record):
+        """
+        Output the record to the file, catering for rollover as described
+        in setRollover().
+        """
+        if self.maxBytes > 0:                   # are we rolling over?
+            msg = "%s\n" % self.format(record)
+            if self.stream.tell() + len(msg) >= self.maxBytes:
+                self.doRollover()
+        StreamHandler.emit(self, record)
+
+    def close(self):
+        """
+        Closes the stream.
+        """
+        self.stream.close()
+
+class SocketHandler(Handler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a streaming socket. The socket is kept open across logging calls.
+    If the peer resets it, an attempt is made to reconnect on the next call.
+    Note that the very simple wire protocol used means that packet sizes
+    are expected to be encodable within 16 bits (i.e. < 32767 bytes).
+    """
+
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+        """
+        Handler.__init__(self)
+        self.host = host
+        self.port = port
+        self.sock = None
+        self.closeOnError = 1
+
+    def makeSocket(self):
+        """
+        A factory method which allows subclasses to define the precise
+        type of socket they want.
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((self.host, self.port))
+        return s
+
+    def send(self, s):
+        """
+        Send a pickled string to the socket. This function allows for
+        partial sends which can happen when the network is busy.
+        """
+        sentsofar = 0
+        left = len(s)
+        while left > 0:
+            sent = self.sock.send(s[sentsofar:])
+            sentsofar = sentsofar + sent
+            left = left - sent
+
+    def makePickle(self, record):
+        """
+        Pickles the record in binary format with a length prefix, and
+        returns it ready for transmission across the socket.
+        """
+        s = cPickle.dumps(record.__dict__, 1)
+        n = len(s)
+        slen = "%c%c" % ((n >> 8) & 0xFF, n & 0xFF)
+        return slen + s
+
+    def handleError(self):
+        """
+        An error has occurred during logging. Most likely cause -
+        connection lost. Close the socket so that we can retry on the
+        next event.
+        """
+        if self.closeOnError and self.sock:
+            self.sock.close()
+            self.sock = None        #try to reconnect next time
+
+    def emit(self, record):
+        """
+        Pickles the record and writes it to the socket in binary format.
+        If there is an error with the socket, silently drop the packet.
+        If there was a problem with the socket, re-establishes the
+        socket.
+        """
+        try:
+            s = self.makePickle(record)
+            if not self.sock:
+                self.sock = self.makeSocket()
+            self.send(s)
+        except:
+            self.handleError()
+
+    def close(self):
+        """
+        Closes the socket.
+        """
+        if self.sock:
+            self.sock.close()
+            self.sock = None
+
+class DatagramHandler(SocketHandler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a datagram socket. Note that the very simple wire protocol used means
+    that packet sizes are expected to be encodable within 16 bits
+    (i.e. < 32767 bytes).
+
+    """
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+        """
+        SocketHandler.__init__(self, host, port)
+        self.closeOnError = 0
+
+    def makeSocket(self):
+        """
+        The factory method of SocketHandler is here overridden to create
+        a UDP socket (SOCK_DGRAM).
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        return s
+
+    def send(self, s):
+        """
+        Send a pickled string to a socket. This function allows for
+        partial sends which can happen when the network is busy.
+        """
+        sentsofar = 0
+        left = len(s)
+        addr = (self.host, self.port)
+        while left > 0:
+            sent = self.sock.sendto(s[sentsofar:], addr)
+            sentsofar = sentsofar + sent
+            left = left - sent
+
+class SysLogHandler(Handler):
+    """
+    A handler class which sends formatted logging records to a syslog
+    server. Based on Sam Rushing's syslog module:
+    http://www.nightmare.com/squirl/python-ext/misc/syslog.py
+    Contributed by Nicolas Untz (after which minor refactoring changes
+    have been made).
+    """
+
+    # from <linux/sys/syslog.h>:
+    # ======================================================================
+    # priorities/facilities are encoded into a single 32-bit quantity, where
+    # the bottom 3 bits are the priority (0-7) and the top 28 bits are the
+    # facility (0-big number). Both the priorities and the facilities map
+    # roughly one-to-one to strings in the syslogd(8) source code.  This
+    # mapping is included in this file.
+    #
+    # priorities (these are ordered)
+
+    LOG_EMERG     = 0       #  system is unusable
+    LOG_ALERT     = 1       #  action must be taken immediately
+    LOG_CRIT      = 2       #  critical conditions
+    LOG_ERR       = 3       #  error conditions
+    LOG_WARNING   = 4       #  warning conditions
+    LOG_NOTICE    = 5       #  normal but significant condition
+    LOG_INFO      = 6       #  informational
+    LOG_DEBUG     = 7       #  debug-level messages
+
+    #  facility codes
+    LOG_KERN      = 0       #  kernel messages
+    LOG_USER      = 1       #  random user-level messages
+    LOG_MAIL      = 2       #  mail system
+    LOG_DAEMON    = 3       #  system daemons
+    LOG_AUTH      = 4       #  security/authorization messages
+    LOG_SYSLOG    = 5       #  messages generated internally by syslogd
+    LOG_LPR       = 6       #  line printer subsystem
+    LOG_NEWS      = 7       #  network news subsystem
+    LOG_UUCP      = 8       #  UUCP subsystem
+    LOG_CRON      = 9       #  clock daemon
+    LOG_AUTHPRIV  = 10  #  security/authorization messages (private)
+
+    #  other codes through 15 reserved for system use
+    LOG_LOCAL0    = 16      #  reserved for local use
+    LOG_LOCAL1    = 17      #  reserved for local use
+    LOG_LOCAL2    = 18      #  reserved for local use
+    LOG_LOCAL3    = 19      #  reserved for local use
+    LOG_LOCAL4    = 20      #  reserved for local use
+    LOG_LOCAL5    = 21      #  reserved for local use
+    LOG_LOCAL6    = 22      #  reserved for local use
+    LOG_LOCAL7    = 23      #  reserved for local use
+
+    priority_names = {
+        "alert":    LOG_ALERT,
+        "crit":     LOG_CRIT,
+        "critical": LOG_CRIT,
+        "debug":    LOG_DEBUG,
+        "emerg":    LOG_EMERG,
+        "err":      LOG_ERR,
+        "error":    LOG_ERR,        #  DEPRECATED
+        "info":     LOG_INFO,
+        "notice":   LOG_NOTICE,
+        "panic":    LOG_EMERG,      #  DEPRECATED
+        "warn":     LOG_WARNING,    #  DEPRECATED
+        "warning":  LOG_WARNING,
+        }
+
+    facility_names = {
+        "auth":     LOG_AUTH,
+        "authpriv": LOG_AUTHPRIV,
+        "cron":     LOG_CRON,
+        "daemon":   LOG_DAEMON,
+        "kern":     LOG_KERN,
+        "lpr":      LOG_LPR,
+        "mail":     LOG_MAIL,
+        "news":     LOG_NEWS,
+        "security": LOG_AUTH,       #  DEPRECATED
+        "syslog":   LOG_SYSLOG,
+        "user":     LOG_USER,
+        "uucp":     LOG_UUCP,
+        "local0":   LOG_LOCAL0,
+        "local1":   LOG_LOCAL1,
+        "local2":   LOG_LOCAL2,
+        "local3":   LOG_LOCAL3,
+        "local4":   LOG_LOCAL4,
+        "local5":   LOG_LOCAL5,
+        "local6":   LOG_LOCAL6,
+        "local7":   LOG_LOCAL7,
+        }
+
+    def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
+        """
+        If address is specified as a string, UNIX socket is used.
+        If facility is not specified, LOG_USER is used.
+        """
+        Handler.__init__(self)
+
+        self.address = address
+        self.facility = facility
+        if type(address) == types.StringType:
+            self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            self.socket.connect(address)
+            self.unixsocket = 1
+        else:
+            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+            self.unixsocket = 0
+
+        self.formatter = None
+
+    # curious: when talking to the unix-domain '/dev/log' socket, a
+    #   zero-terminator seems to be required.  this string is placed
+    #   into a class variable so that it can be overridden if
+    #   necessary.
+    log_format_string = '<%d>%s\000'
+
+    def encodePriority (self, facility, priority):
+        """
+        Encode the facility and priority. You can pass in strings or
+        integers - if strings are passed, the facility_names and
+        priority_names mapping dictionaries are used to convert them to
+        integers.
+        """
+        if type(facility) == types.StringType:
+            facility = self.facility_names[facility]
+        if type(priority) == types.StringType:
+            priority = self.priority_names[priority]
+        return (facility << 3) | priority
+
+    def close (self):
+        """
+        Closes the socket.
+        """
+        if self.unixsocket:
+            self.socket.close()
+
+    def emit(self, record):
+        """
+        The record is formatted, and then sent to the syslog server. If
+        exception information is present, it is NOT sent to the server.
+        """
+        msg = self.format(record)
+        """
+        We need to convert record level to lowercase, maybe this will
+        change in the future.
+        """
+        msg = self.log_format_string % (
+            self.encodePriority(self.facility,
+                                string.lower(record.levelname)),
+            msg)
+        try:
+            if self.unixsocket:
+                self.socket.send(msg)
+            else:
+                self.socket.sendto(msg, self.address)
+        except:
+            self.handleError()
+
+class SMTPHandler(Handler):
+    """
+    A handler class which sends an SMTP email for each logging event.
+    """
+    def __init__(self, mailhost, fromaddr, toaddrs, subject):
+        """
+        Initialize the instance with the from and to addresses and subject
+        line of the email. To specify a non-standard SMTP port, use the
+        (host, port) tuple format for the mailhost argument.
+        """
+        Handler.__init__(self)
+        if type(mailhost) == types.TupleType:
+            host, port = mailhost
+            self.mailhost = host
+            self.mailport = port
+        else:
+            self.mailhost = mailhost
+            self.mailport = None
+        self.fromaddr = fromaddr
+        self.toaddrs = toaddrs
+        self.subject = subject
+
+    def getSubject(self, record):
+        """
+        If you want to specify a subject line which is record-dependent,
+        override this method.
+        """
+        return self.subject
+
+    def emit(self, record):
+        """
+        Format the record and send it to the specified addressees.
+        """
+        try:
+            import smtplib
+            port = self.mailport
+            if not port:
+                port = smtplib.SMTP_PORT
+            smtp = smtplib.SMTP(self.mailhost, port)
+            msg = self.format(record)
+            msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % (
+                            self.fromaddr,
+                            string.join(self.toaddrs, ","),
+                            self.getSubject(record), msg
+                            )
+            smtp.sendmail(self.fromaddr, self.toaddrs, msg)
+            smtp.quit()
+        except:
+            self.handleError()
+
+class BufferingHandler(Handler):
+    """
+  A handler class which buffers logging records in memory. Whenever each
+  record is added to the buffer, a check is made to see if the buffer should
+  be flushed. If it should, then flush() is expected to do the needful.
+    """
+    def __init__(self, capacity):
+        """
+        Initialize the handler with the buffer size.
+        """
+        Handler.__init__(self)
+        self.capacity = capacity
+        self.buffer = []
+
+    def shouldFlush(self, record):
+        """
+        Returns true if the buffer is up to capacity. This method can be
+        overridden to implement custom flushing strategies.
+        """
+        return (len(self.buffer) >= self.capacity)
+
+    def emit(self, record):
+        """
+        Append the record. If shouldFlush() tells us to, call flush() to process
+        the buffer.
+        """
+        self.buffer.append(record)
+        if self.shouldFlush(record):
+            self.flush()
+
+    def flush(self):
+        """
+        Override to implement custom flushing behaviour. This version just zaps
+        the buffer to empty.
+        """
+        self.buffer = []
+
+class MemoryHandler(BufferingHandler):
+    """
+    A handler class which buffers logging records in memory, periodically
+    flushing them to a target handler. Flushing occurs whenever the buffer
+    is full, or when an event of a certain severity or greater is seen.
+    """
+    def __init__(self, capacity, flushLevel=ERROR, target=None):
+        """
+        Initialize the handler with the buffer size, the level at which
+        flushing should occur and an optional target. Note that without a
+        target being set either here or via setTarget(), a MemoryHandler
+        is no use to anyone!
+        """
+        BufferingHandler.__init__(self, capacity)
+        self.flushLevel = flushLevel
+        self.target = target
+
+    def shouldFlush(self, record):
+        """
+        Check for buffer full or a record at the flushLevel or higher.
+        """
+        return (len(self.buffer) >= self.capacity) or \
+                (record.levelno >= self.flushLevel)
+
+    def setTarget(self, target):
+        """
+        Set the target handler for this handler.
+        """
+        self.target = target
+
+    def flush(self):
+        """
+        For a MemoryHandler, flushing means just sending the buffered
+        records to the target, if there is one. Override if you want
+        different behaviour.
+        """
+        if self.target:
+            for record in self.buffer:
+                self.target.handle(record)
+            self.buffer = []
+
+    def close(self):
+        """
+        Flush, set the target to None and lose the buffer.
+        """
+        self.flush()
+        self.target = None
+        self.buffer = []
+
+class NTEventLogHandler(Handler):
+    """
+    A handler class which sends events to the NT Event Log. Adds a
+    registry entry for the specified application name. If no dllname is
+    provided, win32service.pyd (which contains some basic message
+    placeholders) is used. Note that use of these placeholders will make
+    your event logs big, as the entire message source is held in the log.
+    If you want slimmer logs, you have to pass in the name of your own DLL
+    which contains the message definitions you want to use in the event log.
+    """
+    def __init__(self, appname, dllname=None, logtype="Application"):
+        Handler.__init__(self)
+        try:
+            import win32evtlogutil, win32evtlog
+            self.appname = appname
+            self._welu = win32evtlogutil
+            if not dllname:
+                dllname = os.path.split(self._welu.__file__)
+                dllname = os.path.split(dllname[0])
+                dllname = os.path.join(dllname[0], r'win32service.pyd')
+            self.dllname = dllname
+            self.logtype = logtype
+            self._welu.AddSourceToRegistry(appname, dllname, logtype)
+            self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
+            self.typemap = {
+                DEBUG   : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                INFO    : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                WARN    : win32evtlog.EVENTLOG_WARNING_TYPE,
+                ERROR   : win32evtlog.EVENTLOG_ERROR_TYPE,
+                CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
+         }
+        except ImportError:
+            print "The Python Win32 extensions for NT (service, event "\
+                        "logging) appear not to be available."
+            self._welu = None
+
+    def getMessageID(self, record):
+        """
+        Return the message ID for the event record. If you are using your
+        own messages, you could do this by having the msg passed to the
+        logger being an ID rather than a formatting string. Then, in here,
+        you could use a dictionary lookup to get the message ID. This
+        version returns 1, which is the base message ID in win32service.pyd.
+        """
+        return 1
+
+    def getEventCategory(self, record):
+        """
+        Return the event category for the record. Override this if you
+        want to specify your own categories. This version returns 0.
+        """
+        return 0
+
+    def getEventType(self, record):
+        """
+        Return the event type for the record. Override this if you want
+        to specify your own types. This version does a mapping using the
+        handler's typemap attribute, which is set up in __init__() to a
+        dictionary which contains mappings for DEBUG, INFO, WARN, ERROR
+        and CRITICAL. If you are using your own levels you will either need
+        to override this method or place a suitable dictionary in the
+        handler's typemap attribute.
+        """
+        return self.typemap.get(record.levelno, self.deftype)
+
+    def emit(self, record):
+        """
+        Determine the message ID, event category and event type. Then
+        log the message in the NT event log.
+        """
+        if self._welu:
+            try:
+                id = self.getMessageID(record)
+                cat = self.getEventCategory(record)
+                type = self.getEventType(record)
+                msg = self.format(record)
+                self._welu.ReportEvent(self.appname, id, cat, type, [msg])
+            except:
+                self.handleError()
+
+    def close(self):
+        """
+        You can remove the application name from the registry as a
+        source of event log entries. However, if you do this, you will
+        not be able to see the events as you intended in the Event Log
+        Viewer - it needs to be able to access the registry to get the
+        DLL name.
+        """
+        #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
+        pass
+
+class HTTPHandler(Handler):
+    """
+    A class which sends records to a Web server, using either GET or
+    POST semantics.
+    """
+    def __init__(self, host, url, method="GET"):
+        """
+        Initialize the instance with the host, the request URL, and the method
+        ("GET" or "POST")
+        """
+        Handler.__init__(self)
+        method = string.upper(method)
+        if method not in ["GET", "POST"]:
+            raise ValueError, "method must be GET or POST"
+        self.host = host
+        self.url = url
+        self.method = method
+
+    def emit(self, record):
+        """
+        Send the record to the Web server as an URL-encoded dictionary
+        """
+        try:
+            import httplib, urllib
+            h = httplib.HTTP(self.host)
+            url = self.url
+            data = urllib.urlencode(record.__dict__)
+            if self.method == "GET":
+                if (string.find(url, '?') >= 0):
+                    sep = '&'
+                else:
+                    sep = '?'
+                url = url + "%c%s" % (sep, data)
+            h.putrequest(self.method, url)
+            if self.method == "POST":
+                h.putheader("Content-length", str(len(data)))
+            h.endheaders()
+            if self.method == "POST":
+                h.send(data)
+            h.getreply()    #can't do anything with the result
+        except:
+            self.handleError()
+
+#---------------------------------------------------------------------------
+#   Manager classes and functions
+#---------------------------------------------------------------------------
+
+class PlaceHolder:
+    """
+    PlaceHolder instances are used in the Manager logger hierarchy to take
+    the place of nodes for which no loggers have been defined [FIXME add
+    example].
+    """
+    def __init__(self, alogger):
+        """
+        Initialize with the specified logger being a child of this placeholder.
+        """
+        self.loggers = [alogger]
+
+    def append(self, alogger):
+        """
+        Add the specified logger as a child of this placeholder.
+        """
+        if alogger not in self.loggers:
+            self.loggers.append(alogger)
+
+#
+#   Determine which class to use when instantiating loggers.
+#
+_loggerClass = None
+
+def setLoggerClass(klass):
+    """
+    Set the class to be used when instantiating a logger. The class should
+    define __init__() such that only a name argument is required, and the
+    __init__() should call Logger.__init__()
+    """
+    if klass != Logger:
+        if type(klass) != types.ClassType:
+            raise TypeError, "setLoggerClass is expecting a class"
+        if not issubclass(klass, Logger):
+            raise TypeError, "logger not derived from logging.Logger: " + \
+                            klass.__name__
+    global _loggerClass
+    _loggerClass = klass
+
+class Manager:
+    """
+    There is [under normal circumstances] just one Manager instance, which
+    holds the hierarchy of loggers.
+    """
+    def __init__(self, root):
+        """
+        Initialize the manager with the root node of the logger hierarchy.
+        """
+        self.root = root
+        self.disable = 0
+        self.emittedNoHandlerWarning = 0
+        self.loggerDict = {}
+
+    def getLogger(self, name):
+        """
+        Get a logger with the specified name, creating it if it doesn't
+        yet exist. If a PlaceHolder existed for the specified name [i.e.
+        the logger didn't exist but a child of it did], replace it with
+        the created logger and fix up the parent/child references which
+        pointed to the placeholder to now point to the logger.
+        """
+        rv = None
+        _acquireLock()
+        try:
+            if self.loggerDict.has_key(name):
+                rv = self.loggerDict[name]
+                if isinstance(rv, PlaceHolder):
+                    ph = rv
+                    rv = _loggerClass(name)
+                    rv.manager = self
+                    self.loggerDict[name] = rv
+                    self._fixupChildren(ph, rv)
+                    self._fixupParents(rv)
+            else:
+                rv = _loggerClass(name)
+                rv.manager = self
+                self.loggerDict[name] = rv
+                self._fixupParents(rv)
+        finally:
+            _releaseLock()
+        return rv
+
+    def _fixupParents(self, alogger):
+        """
+        Ensure that there are either loggers or placeholders all the way
+        from the specified logger to the root of the logger hierarchy.
+        """
+        name = alogger.name
+        i = string.rfind(name, ".")
+        rv = None
+        while (i > 0) and not rv:
+            substr = name[:i]
+            if not self.loggerDict.has_key(substr):
+                self.loggerDict[substr] = PlaceHolder(alogger)
+            else:
+                obj = self.loggerDict[substr]
+                if isinstance(obj, Logger):
+                    rv = obj
+                else:
+                    assert isinstance(obj, PlaceHolder)
+                    obj.append(alogger)
+            i = string.rfind(name, ".", 0, i - 1)
+        if not rv:
+            rv = self.root
+        alogger.parent = rv
+
+    def _fixupChildren(self, ph, alogger):
+        """
+        Ensure that children of the placeholder ph are connected to the
+        specified logger.
+        """
+        for c in ph.loggers:
+            if string.find(c.parent.name, alogger.name) <> 0:
+                alogger.parent = c.parent
+                c.parent = alogger
+
+#---------------------------------------------------------------------------
+#   Logger classes and functions
+#---------------------------------------------------------------------------
+
+class Logger(Filterer):
+    """
+    Instances of the Logger class represent a single logging channel. A
+    "logging channel" indicates an area of an application. Exactly how an
+    "area" is defined is up to the application developer. Since an
+    application can have any number of areas, logging channels are identified
+    by a unique string. Application areas can be nested (e.g. an area
+    of "input processing" might include sub-areas "read CSV files", "read
+    XLS files" and "read Gnumeric files"). To cater for this natural nesting,
+    channel names are organized into a namespace hierarchy where levels are
+    separated by periods, much like the Java or Python package namespace. So
+    in the instance given above, channel names might be "input" for the upper
+    level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
+    There is no arbitrary limit to the depth of nesting.
+    """
+    def __init__(self, name, level=ALL):
+        """
+        Initialize the logger with a name and an optional level.
+        """
+        Filterer.__init__(self)
+        self.name = name
+        self.level = level
+        self.parent = None
+        self.propagate = 1
+        self.handlers = []
+        self.disabled = 0
+
+    def setLevel(self, lvl):
+        """
+        Set the logging level of this logger.
+        """
+        self.level = lvl
+
+#   def getRoot(self):
+#       """
+#       Get the root of the logger hierarchy.
+#       """
+#       return Logger.root
+
+    def debug(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'DEBUG'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
+        """
+        if self.manager.disable >= DEBUG:
+            return
+        if DEBUG >= self.getEffectiveLevel():
+            apply(self._log, (DEBUG, msg, args), kwargs)
+
+    def info(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'INFO'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
+        """
+        if self.manager.disable >= INFO:
+            return
+        if INFO >= self.getEffectiveLevel():
+            apply(self._log, (INFO, msg, args), kwargs)
+
+    def warn(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'WARN'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.warn("Houston, we have a %s", "bit of a problem", exc_info=1)
+        """
+        if self.manager.disable >= WARN:
+            return
+        if self.isEnabledFor(WARN):
+            apply(self._log, (WARN, msg, args), kwargs)
+
+    def error(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'ERROR'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.error("Houston, we have a %s", "major problem", exc_info=1)
+        """
+        if self.manager.disable >= ERROR:
+            return
+        if self.isEnabledFor(ERROR):
+            apply(self._log, (ERROR, msg, args), kwargs)
+
+    def exception(self, msg, *args):
+        """
+        Convenience method for logging an ERROR with exception information
+        """
+        apply(self.error, (msg,) + args, {'exc_info': 1})
+
+    def critical(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'CRITICAL'. To pass exception
+        information, use the keyword argument exc_info with a true value, e.g.
+
+        logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
+        """
+        if self.manager.disable >= CRITICAL:
+            return
+        if CRITICAL >= self.getEffectiveLevel():
+            apply(self._log, (CRITICAL, msg, args), kwargs)
+
+    fatal = critical
+
+    def log(self, lvl, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with the severity 'lvl'. To pass exception
+        information, use the keyword argument exc_info with a true value, e.g.
+        logger.log(lvl, "We have a %s", "mysterious problem", exc_info=1)
+        """
+        if self.manager.disable >= lvl:
+            return
+        if self.isEnabledFor(lvl):
+            apply(self._log, (lvl, msg, args), kwargs)
+
+    def findCaller(self):
+        """
+        Find the stack frame of the caller so that we can note the source
+        file name and line number.
+        """
+        rv = (None, None)
+        frame = inspect.currentframe().f_back
+        while frame:
+            sfn = inspect.getsourcefile(frame)
+            if sfn:
+                sfn = os.path.normcase(sfn)
+            if sfn != _srcfile:
+                #print frame.f_code.co_code
+                lineno = inspect.getlineno(frame)
+                rv = (sfn, lineno)
+                break
+            frame = frame.f_back
+        return rv
+
+    def makeRecord(self, name, lvl, fn, lno, msg, args, exc_info):
+        """
+        A factory method which can be overridden in subclasses to create
+        specialized LogRecords.
+        """
+        return LogRecord(name, lvl, fn, lno, msg, args, exc_info)
+
+    def _log(self, lvl, msg, args, exc_info=None):
+        """
+        Low-level logging routine which creates a LogRecord and then calls
+        all the handlers of this logger to handle the record.
+        """
+        if inspect and _srcfile:
+            _acquireLock()
+            try:
+                fn, lno = self.findCaller()
+            finally:
+                _releaseLock()
+        else:
+            fn, lno = "<unknown file>", 0
+        if exc_info:
+            exc_info = sys.exc_info()
+        record = self.makeRecord(self.name, lvl, fn, lno, msg, args, exc_info)
+        self.handle(record)
+
+    def handle(self, record):
+        """
+        Call the handlers for the specified record. This method is used for
+        unpickled records received from a socket, as well as those created
+        locally. Logger-level filtering is applied.
+        """
+        if (not self.disabled) and self.filter(record):
+            self.callHandlers(record)
+
+    def addHandler(self, hdlr):
+        """
+        Add the specified handler to this logger.
+        """
+        if not (hdlr in self.handlers):
+            self.handlers.append(hdlr)
+
+    def removeHandler(self, hdlr):
+        """
+        Remove the specified handler from this logger.
+        """
+        if hdlr in self.handlers:
+            hdlr.close()
+            self.handlers.remove(hdlr)
+
+    def callHandlers(self, record):
+        """
+        Loop through all handlers for this logger and its parents in the
+        logger hierarchy. If no handler was found, output a one-off error
+        message to sys.stderr. Stop searching up the hierarchy whenever a
+        logger with the "propagate" attribute set to zero is found - that
+        will be the last logger whose handlers are called.
+        """
+        c = self
+        found = 0
+        while c:
+            for hdlr in c.handlers:
+                found = found + 1
+                if record.levelno >= hdlr.level:
+                    hdlr.handle(record)
+            if not c.propagate:
+                c = None    #break out
+            else:
+                c = c.parent
+        if (found == 0) and not self.manager.emittedNoHandlerWarning:
+            sys.stderr.write("No handlers could be found for logger"
+                             " \"%s\"\n" % self.name)
+            self.manager.emittedNoHandlerWarning = 1
+
+    def getEffectiveLevel(self):
+        """
+        Loop through this logger and its parents in the logger hierarchy,
+        looking for a non-zero logging level. Return the first one found.
+        """
+        logger = self
+        while logger:
+            if logger.level:
+                return logger.level
+            logger = logger.parent
+        return ALL
+
+    def isEnabledFor(self, lvl):
+        """
+        Is this logger enabled for level lvl?
+        """
+        if self.manager.disable >= lvl:
+            return 0
+        return lvl >= self.getEffectiveLevel()
+
+class RootLogger(Logger):
+    """
+    A root logger is not that different to any other logger, except that
+    it must have a logging level and there is only one instance of it in
+    the hierarchy.
+    """
+    def __init__(self, lvl):
+        """
+        Initialize the logger with the name "root".
+        """
+        Logger.__init__(self, "root", lvl)
+
+_loggerClass = Logger
+
+root = RootLogger(DEBUG)
+Logger.root = root
+Logger.manager = Manager(Logger.root)
+
+#---------------------------------------------------------------------------
+# Configuration classes and functions
+#---------------------------------------------------------------------------
+
+BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
+
+def basicConfig():
+    """
+    Do basic configuration for the logging system by creating a
+    StreamHandler with a default Formatter and adding it to the
+    root logger.
+    """
+    if len(root.handlers) == 0:
+        hdlr = StreamHandler()
+        fmt = Formatter(BASIC_FORMAT)
+        hdlr.setFormatter(fmt)
+        root.addHandler(hdlr)
+
+def fileConfig(fname):
+    """
+    Read the logging configuration from a ConfigParser-format file. This can
+    be called several times from an application, allowing an end user the
+    ability to select from various pre-canned configurations (if the
+    developer provides a mechanism to present the choices and load the chosen
+    configuration).
+    """
+    import ConfigParser
+
+    cp = ConfigParser.ConfigParser()
+    cp.read(fname)
+    #first, do the formatters...
+    flist = cp.get("formatters", "keys")
+    if len(flist):
+        flist = string.split(flist, ",")
+        formatters = {}
+        for form in flist:
+            sectname = "formatter_%s" % form
+            opts = cp.options(sectname)
+            if "format" in opts:
+                fs = cp.get(sectname, "format", 1)
+            else:
+                fs = None
+            if "datefmt" in opts:
+                dfs = cp.get(sectname, "datefmt", 1)
+            else:
+                dfs = None
+            f = Formatter(fs, dfs)
+            formatters[form] = f
+    #next, do the handlers...
+    #critical section...
+    _acquireLock()
+    try:
+        try:
+            #first, lose the existing handlers...
+            _handlers.clear()
+            #now set up the new ones...
+            hlist = cp.get("handlers", "keys")
+            if len(hlist):
+                hlist = string.split(hlist, ",")
+                handlers = {}
+                fixups = [] #for inter-handler references
+                for hand in hlist:
+                    sectname = "handler_%s" % hand
+                    klass = cp.get(sectname, "class")
+                    opts = cp.options(sectname)
+                    if "formatter" in opts:
+                        fmt = cp.get(sectname, "formatter")
+                    else:
+                        fmt = ""
+                    klass = eval(klass)
+                    args = cp.get(sectname, "args")
+                    args = eval(args)
+                    h = apply(klass, args)
+                    if "level" in opts:
+                        lvl = cp.get(sectname, "level")
+                        h.setLevel(_levelNames[lvl])
+                    if len(fmt):
+                        h.setFormatter(formatters[fmt])
+                    #temporary hack for FileHandler and MemoryHandler.
+                    if klass == FileHandler:
+                        maxsize = 0
+                        if "maxsize" in opts:
+                            ms = cp.getint(sectname, "maxsize")
+                            if ms > 0:
+                                maxsize = ms
+                        if maxsize:
+                            backcount = 0
+                            if "backcount" in opts:
+                                bc = cp.getint(sectname, "backcount")
+                                if bc > 0:
+                                    backcount = bc
+                            h.setRollover(maxsize, backcount)
+                    elif klass == MemoryHandler:
+                        if "target" in opts:
+                            target = cp.get(sectname,"target")
+                        else:
+                            target = ""
+                        if len(target): #the target handler may not be loaded yet, so keep for later...
+                            fixups.append((h, target))
+                    handlers[hand] = h
+                #now all handlers are loaded, fixup inter-handler references...
+                for fixup in fixups:
+                    h = fixup[0]
+                    t = fixup[1]
+                    h.setTarget(handlers[t])
+            #at last, the loggers...first the root...
+            llist = cp.get("loggers", "keys")
+            llist = string.split(llist, ",")
+            llist.remove("root")
+            sectname = "logger_root"
+            log = root
+            opts = cp.options(sectname)
+            if "level" in opts:
+                lvl = cp.get(sectname, "level")
+                log.setLevel(_levelNames[lvl])
+            for h in root.handlers:
+                root.removeHandler(h)
+            hlist = cp.get(sectname, "handlers")
+            if len(hlist):
+                hlist = string.split(hlist, ",")
+                for hand in hlist:
+                    log.addHandler(handlers[hand])
+            #and now the others...
+            #we don't want to lose the existing loggers,
+            #since other threads may have pointers to them.
+            #existing is set to contain all existing loggers,
+            #and as we go through the new configuration we
+            #remove any which are configured. At the end,
+            #what's left in existing is the set of loggers
+            #which were in the previous configuration but
+            #which are not in the new configuration.
+            existing = root.manager.loggerDict.keys()
+            #now set up the new ones...
+            for log in llist:
+                sectname = "logger_%s" % log
+                qn = cp.get(sectname, "qualname")
+                opts = cp.options(sectname)
+                if "propagate" in opts:
+                    propagate = cp.getint(sectname, "propagate")
+                else:
+                    propagate = 1
+                logger = getLogger(qn)
+                if qn in existing:
+                    existing.remove(qn)
+                if "level" in opts:
+                    lvl = cp.get(sectname, "level")
+                    logger.setLevel(_levelNames[lvl])
+                for h in logger.handlers:
+                    logger.removeHandler(h)
+                logger.propagate = propagate
+                logger.disabled = 0
+                hlist = cp.get(sectname, "handlers")
+                if len(hlist):
+                    hlist = string.split(hlist, ",")
+                    for hand in hlist:
+                        logger.addHandler(handlers[hand])
+            #Disable any old loggers. There's no point deleting
+            #them as other threads may continue to hold references
+            #and by disabling them, you stop them doing any logging.
+            for log in existing:
+                root.manager.loggerDict[log].disabled = 1
+        except:
+            import traceback
+            ei = sys.exc_info()
+            traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
+            del ei
+    finally:
+        _releaseLock()
+
+#---------------------------------------------------------------------------
+# Utility functions at module level.
+# Basically delegate everything to the root logger.
+#---------------------------------------------------------------------------
+
+def getLogger(name=None):
+    """
+    Return a logger with the specified name, creating it if necessary.
+    If no name is specified, return the root logger.
+    """
+    if name:
+        return Logger.manager.getLogger(name)
+    else:
+        return root
+
+def getRootLogger():
+    """
+    Return the root logger. Note that getLogger('') now does the same thing,
+    so this function is deprecated and may disappear in the future.
+    """
+    return root
+
+def critical(msg, *args, **kwargs):
+    """
+    Log a message with severity 'CRITICAL' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.critical, (msg,)+args, kwargs)
+
+fatal = critical
+
+def error(msg, *args, **kwargs):
+    """
+    Log a message with severity 'ERROR' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.error, (msg,)+args, kwargs)
+
+def exception(msg, *args):
+    """
+    Log a message with severity 'ERROR' on the root logger,
+    with exception information.
+    """
+    apply(error, (msg,)+args, {'exc_info': 1})
+
+def warn(msg, *args, **kwargs):
+    """
+    Log a message with severity 'WARN' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.warn, (msg,)+args, kwargs)
+
+def info(msg, *args, **kwargs):
+    """
+    Log a message with severity 'INFO' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.info, (msg,)+args, kwargs)
+
+def debug(msg, *args, **kwargs):
+    """
+    Log a message with severity 'DEBUG' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.debug, (msg,)+args, kwargs)
+
+def disable(level):
+    """
+    Disable all logging calls less severe than 'level'.
+    """
+    root.manager.disable = level
+
+def shutdown():
+    """
+    Perform any cleanup actions in the logging system (e.g. flushing
+    buffers). Should be called at application exit.
+    """
+    for h in _handlers.keys():
+        h.flush()
+        h.close()
+
+#
+#   The following code implements a socket listener for on-the-fly
+#   reconfiguration of logging.
+#
+#   _listener holds the server object doing the listening
+_listener = None
+
+def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
+    """
+    Start up a socket server on the specified port, and listen for new
+    configurations. These will be sent as a file suitable for processing
+    by fileConfig(). Returns a Thread object on which you can call start()
+    to start the server, and which you can join() when appropriate.
+    To stop the server, call stopListening().
+    """
+    if not thread:
+        raise NotImplementedError, "listen() needs threading to work"
+
+    import threading
+
+    class ConfigStreamHandler(StreamRequestHandler):
+        """
+        Handler for a logging configuration request. It expects a
+        completely new logging configuration and uses fileConfig to
+        install it.
+        """
+        def handle(self):
+            """
+            Each request is expected to be a 2-byte length,
+            followed by the config file. Uses fileConfig() to do the
+            needful.
+            """
+            import tempfile
+            try:
+                conn = self.connection
+                chunk = conn.recv(2)
+                if len(chunk) == 2:
+                    slen = (ord(chunk[0]) << 8) | ord(chunk[1])
+                    chunk = self.connection.recv(slen)
+                    while len(chunk) < slen:
+                        chunk = chunk + conn.recv(slen - len(chunk))
+                    #Apply new configuration. We'd like to be able to
+                    #create a StringIO and pass that in, but unfortunately
+                    #1.5.2 ConfigParser does not support reading file
+                    #objects, only actual files. So we create a temporary
+                    #file and remove it later.
+                    file = tempfile.mktemp(".ini")
+                    f = open(file, "w")
+                    f.write(chunk)
+                    f.close()
+                    fileConfig(file)
+                    os.remove(file)
+            except socket.error, e:
+                if type(e.args) != types.TupleType:
+                    raise
+                else:
+                    errcode = e.args[0]
+                    if errcode != RESET_ERROR:
+                        raise
+
+    class ConfigSocketReceiver(ThreadingTCPServer):
+        """
+        A simple TCP socket-based logging config receiver.
+        """
+
+        allow_reuse_address = 1
+
+        def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
+                handler=None):
+            ThreadingTCPServer.__init__(self, (host, port), handler)
+            _acquireLock()
+            self.abort = 0
+            _releaseLock()
+            self.timeout = 1
+
+        def serve_until_stopped(self):
+            import select
+            abort = 0
+            while not abort:
+                rd, wr, ex = select.select([self.socket.fileno()],
+                                           [], [],
+                                           self.timeout)
+                if rd:
+                    self.handle_request()
+                _acquireLock()
+                abort = self.abort
+                _releaseLock()
+
+    def serve(rcvr, hdlr):
+        server = rcvr(handler=hdlr)
+        global _listener
+        _acquireLock()
+        _listener = server
+        _releaseLock()
+        server.serve_until_stopped()
+
+    return threading.Thread(target=serve, args=(ConfigSocketReceiver, ConfigStreamHandler))
+
+def stopListening():
+    """
+    Stop the listening server which was created with a call to listen().
+    """
+    if _listener:
+        _acquireLock()
+        _listener.abort = 1
+        _listener = None
+        _releaseLock()
+
+
+# bicycle repair man stuff
+
+bike_logger_initialised = 0
+
+def init():
+    global bike_logger_initialised
+    if not bike_logger_initialised:
+        log = getLogger("bike")
+        h = StreamHandler()
+        h.setFormatter(Formatter(
+            fmt="%(pathname)s:%(lineno)s:%(levelname)s   %(message)s"))
+        log.addHandler(h)
+        bike_logger_initialised = 1
+
+if __name__ == "__main__":
+    print __doc__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/mock.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,143 @@
+#
+# (c) Dave Kirby 2001
+# dkirby@bigfoot.com
+#
+# Call interceptor code by Phil Dawes (pdawes@users.sourceforge.net)
+
+'''
+The Mock class emulates any other class for testing purposes.
+All method calls are stored for later examination.
+The class constructor takes a dictionary of method names and the values
+they return.  Methods that are not in the dictionary will return None.
+'''
+import inspect
+
+
+class Mock:
+    def __init__(self, returnValues=None ):
+        self.mockCalledMethods = {}
+        self.mockAllCalledMethods = []
+        self.mockReturnValues = returnValues or {}
+        self.setupMethodInterceptors()
+        
+    def setupMethodInterceptors(self):
+        if self.__class__ != Mock: # check we've been subclassed
+            methods =  inspect.getmembers(self.__class__,inspect.ismethod)
+            for m in methods:
+                name = m[0]
+                self.__dict__[name] = MethodCallInterceptor(name,self)        
+            
+    def __getattr__( self, name ):
+        return MockCaller( name, self )
+    
+    def getAllCalls(self):
+        '''return a list of MockCall objects,
+        representing all the methods in the order they were called'''
+        return self.mockAllCalledMethods
+
+    def getNamedCalls(self, methodName ):
+        '''return a list of MockCall objects,
+        representing all the calls to the named method in the order they were called'''
+        return self.mockCalledMethods.get(methodName, [] )
+    
+    def assertNamedCall(self,methodName,*args):
+        # assert call was made once
+        assert(len(self.getNamedCalls(methodName)) == 1)
+        # assert args are correct
+        argsdict = inspect.getargvalues(inspect.currentframe())[3]
+        i=0
+        for arg in argsdict['args']:
+            assert(self.getNamedCalls(methodName)[0].getParam(i) == arg)
+            i += 1
+
+    def assertCallInOrder(self,methodName,*args):
+        ''' Convenience method to allow client to check that calls were
+        made in the right order. Call once for each methodcall'''
+
+        # initialise callIndex. (n.b. __getattr__ method complicates
+        # this since attrs are MockCaller instances by default)
+        if type(self.callIndex) != type(1):
+            self.callIndex=0
+        
+        call = self.getAllCalls()[self.callIndex]
+        # assert method name is correct
+        assert(call.getName() == methodName)
+        # assert args are correct
+        argsdict = inspect.getargvalues(inspect.currentframe())[3]
+        i=0
+        for arg in argsdict['args']:
+            assert(call.getParam(i) == arg)
+            i += 1
+        # assert num args are correct
+        assert(call.getNumParams() == i)
+        self.callIndex += 1
+        
+    def assertNoMoreCalls(self):
+        assert(len(self.getAllCalls()) == self.callIndex)
+        
+class MockCall:
+    def __init__(self, name, params, kwparams ):
+        self.name = name
+        self.params = params
+        self.kwparams = kwparams
+    def getParam( self, n ):
+        if type(n) == type(1):
+            return self.params[n]
+        elif type(n) == type(''):
+            return self.kwparams[n]
+        else:
+            raise IndexError, 'illegal index type for getParam'
+
+    def getNumParams(self):
+        return len(self.params)
+
+
+    def getName(self):
+        return self.name
+    
+    #pretty-print the method call
+    def __str__(self):
+        s = self.name + "("
+        sep = ''
+        for p in self.params:
+            s = s + sep + repr(p)
+            sep = ', '
+        for k,v in self.kwparams.items():
+            s = s + sep + k+ '='+repr(v)
+            sep = ', '
+        s = s + ')'
+        return s
+    def __repr__(self):
+        return self.__str__()
+
+class MockCaller:
+    def __init__( self, name, mock):
+        self.name = name
+        self.mock = mock
+    def __call__(self,  *params, **kwparams ):
+        self.recordCall(params,kwparams)
+        return self.mock.mockReturnValues.get(self.name)
+
+    def recordCall(self,params,kwparams):
+        thisCall = MockCall( self.name, params, kwparams )
+        calls = self.mock.mockCalledMethods.get(self.name, [] )
+        if calls == []:
+            self.mock.mockCalledMethods[self.name] = calls 
+        calls.append(thisCall)
+        self.mock.mockAllCalledMethods.append(thisCall)
+
+
+# intercepts the call and records it, then delegates to the real call
+class MethodCallInterceptor(MockCaller):
+    
+    def __call__(self,  *params, **kwparams ):
+        self.recordCall(params,kwparams)
+        return self.makeCall(params)
+        
+    def makeCall(self,params):
+        argsstr="(self.mock"
+        for i in range(len(params)):
+            argsstr += ",params["+`i`+"]"
+        argsstr+=")"
+        return eval("self.mock.__class__."+self.name+argsstr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,3 @@
+#from addtypeinfo import addtypeinfo
+#from load import load
+#from brmtransformer import parse
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/constants.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,3 @@
+messages={"PARSING":"Parsing","ADDTYPEINFO":"Deducing Type Information"}
+
+MAXCALLDEPTH = 10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/fastparser.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+from bike.parsing.fastparserast import *
+from bike.parsing.parserutils import *
+from parser import ParserError
+#import exceptions
+
+indentRE = re.compile("^\s*(\w+)")
+
+# returns a tree of objects representing nested classes and functions
+# in the source
+def fastparser(src,modulename="",filename=""):
+    try:
+        return fastparser_impl(src,modulename,filename)
+    except RuntimeError, ex:   # if recursive call exceeds maximum depth
+        if str(ex) == "maximum recursion limit exceeded":
+            raise ParserError,"maximum recursion depth exceeded when fast-parsing src "+filename
+        else:
+            raise
+
+def fastparser_impl(src,modulename,filename):
+    lines = src.splitlines(1)
+    maskedSrc = maskPythonKeywordsInStringsAndComments(src)
+    maskedLines = maskedSrc.splitlines(1)
+    root = Module(filename,modulename,lines,maskedSrc)
+    parentnode = root
+    lineno = 0
+    for line in maskedLines:
+        lineno+=1
+        #print "line",lineno,":",line
+        m = indentRE.match(line)
+        if m:
+            indent = m.start(1)
+            tokenstr = m.group(1)
+            if tokenstr == "import" or tokenstr == "from":
+                while indent <= parentnode.indent:   # root indent is -TABWIDTH
+                    parentnode = parentnode.getParent()
+                try:
+                    parentnode.importlines.append(lineno)
+                except AttributeError:
+                    parentnode.importlines = [lineno]
+            elif tokenstr == "class":
+                m2 = classNameRE.match(line)
+                if m2:
+                    n = Class(m2.group(1), filename, root, lineno, indent, lines, maskedSrc)
+                    root.flattenedNodes.append(n)
+
+                    while indent <= parentnode.indent:
+                        parentnode = parentnode.getParent()
+                    parentnode.addChild(n)
+                    parentnode = n
+
+            elif tokenstr == "def":
+                m2 = fnNameRE.match(line)
+                if m2:
+                    n = Function(m2.group(1), filename, root, lineno, indent, lines, maskedSrc)
+                    root.flattenedNodes.append(n)
+
+                    while indent <= parentnode.indent:
+                        parentnode = parentnode.getParent()
+                    parentnode.addChild(n)
+                    parentnode = n
+
+            elif indent <= parentnode.indent and \
+                     tokenstr in ['if','for','while','try']:
+                parentnode = parentnode.getParent()
+                while indent <= parentnode.indent:
+                    parentnode = parentnode.getParent()
+
+    return root
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/fastparserast.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,327 @@
+from __future__ import generators
+from parserutils import generateLogicalLines, maskStringsAndComments, maskStringsAndRemoveComments
+import re
+import os
+import compiler
+from bike.transformer.save import resetOutputQueue
+
+TABWIDTH = 4
+
+classNameRE = re.compile("^\s*class\s+(\w+)")
+fnNameRE = re.compile("^\s*def\s+(\w+)")
+
+_root = None
+
+def getRoot():
+    global _root
+    if _root is None:
+        resetRoot()
+    return _root 
+
+def resetRoot(root = None):
+    global _root
+    _root = root or Root()
+    _root.unittestmode = False
+    resetOutputQueue()
+
+
+def getModule(filename_path):
+    from bike.parsing.load import CantLocateSourceNodeException, getSourceNode
+    try:
+        sourcenode = getSourceNode(filename_path)
+        return sourcenode.fastparseroot
+    except CantLocateSourceNodeException:
+        return None
+
+def getPackage(directory_path):
+    from bike.parsing.pathutils import getRootDirectory
+    rootdir = getRootDirectory(directory_path)
+    if rootdir == directory_path:
+        return getRoot()
+    else:
+        return Package(directory_path,
+                       os.path.basename(directory_path))
+
+
+
+
+            
+class Root:
+    def __init__(self, pythonpath = None):
+        # singleton hack to allow functions in query package to appear
+        # 'stateless'
+        resetRoot(self)
+
+        # this is to get round a python optimisation which reuses an
+        # empty list as a default arg. unfortunately the client of
+        # this method may fill that list, so it's not empty
+        if not pythonpath:
+            pythonpath = []
+        self.pythonpath = pythonpath
+
+    def __repr__(self):
+        return "Root()"
+        #return "Root(%s)"%(self.getChildNodes())
+
+
+    # dummy method
+    def getChild(self,name):
+        return None
+
+class Package:
+    def __init__(self, path, name):
+        self.path = path
+        self.name = name
+
+    def getChild(self,name):
+        from bike.parsing.newstuff import getModule
+        return getModule(os.path.join(self.path,name+".py"))
+
+    def __repr__(self):
+        return "Package(%s,%s)"%(self.path, self.name)
+
+# used so that linenum can be an attribute
+class Line(str):
+    pass
+
+class StructuralNode:
+    def __init__(self, filename, srclines, modulesrc):
+        self.childNodes = []
+        self.filename = filename
+        self._parent = None
+        self._modulesrc = modulesrc
+        self._srclines = srclines
+        self._maskedLines = None
+
+    def addChild(self, node):
+        self.childNodes.append(node)
+        node.setParent(self)
+
+    def setParent(self, parent):
+        self._parent = parent
+
+    def getParent(self):
+        return self._parent
+
+    def getChildNodes(self):
+        return self.childNodes
+
+    def getChild(self,name):
+        matches = [c for c in self.getChildNodes() if c.name == name]
+        if matches != []:
+            return matches[0]
+
+    def getLogicalLine(self,physicalLineno):
+        return generateLogicalLines(self._srclines[physicalLineno-1:]).next()
+
+    # badly named: actually returns line numbers of import statements
+    def getImportLineNumbers(self):
+        try:
+            return self.importlines
+        except AttributeError:
+            return[]
+
+    def getLinesNotIncludingThoseBelongingToChildScopes(self):
+        srclines = self.getMaskedModuleLines()
+        lines = []
+        lineno = self.getStartLine()
+        for child in self.getChildNodes():
+            lines+=srclines[lineno-1: child.getStartLine()-1]
+            lineno = child.getEndLine()
+        lines+=srclines[lineno-1: self.getEndLine()-1]
+        return lines
+
+
+    def generateLinesNotIncludingThoseBelongingToChildScopes(self):
+        srclines = self.getMaskedModuleLines()
+        lines = []
+        lineno = self.getStartLine()
+        for child in self.getChildNodes():
+            for line in srclines[lineno-1: child.getStartLine()-1]:
+                yield self.attachLinenum(line,lineno)
+                lineno +=1
+            lineno = child.getEndLine()
+        for line in srclines[lineno-1: self.getEndLine()-1]:
+            yield self.attachLinenum(line,lineno)
+            lineno +=1
+
+    def generateLinesWithLineNumbers(self,startline=1):
+        srclines = self.getMaskedModuleLines()
+        for lineno in range(startline,len(srclines)+1):
+            yield self.attachLinenum(srclines[lineno-1],lineno)
+
+    def attachLinenum(self,line,lineno):
+        line = Line(line)
+        line.linenum = lineno
+        return line
+
+    def getMaskedModuleLines(self):
+        from bike.parsing.load import Cache
+        try:
+            maskedlines = Cache.instance.maskedlinescache[self.filename]
+        except:
+            # make sure src is actually masked
+            # (could just have keywords masked)
+            maskedsrc = maskStringsAndComments(self._modulesrc)
+            maskedlines = maskedsrc.splitlines(1)
+            Cache.instance.maskedlinescache[self.filename] = maskedlines
+        return maskedlines
+
+
+class Module(StructuralNode):
+    def __init__(self, filename, name, srclines, maskedsrc):
+        StructuralNode.__init__(self, filename, srclines, maskedsrc)
+        self.name = name
+        self.indent = -TABWIDTH
+        self.flattenedNodes = []
+        self.module = self
+
+    def getMaskedLines(self):
+        return self.getMaskedModuleLines()
+
+    def getFlattenedListOfChildNodes(self):
+        return self.flattenedNodes
+
+    def getStartLine(self):
+        return 1
+
+    def getEndLine(self):
+        return len(self.getMaskedModuleLines())+1
+
+    def getSourceNode(self):
+        return self.sourcenode
+
+    def setSourceNode(self, sourcenode):
+        self.sourcenode = sourcenode
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Module) and \
+               node.name == self.name
+
+    def getParent(self):
+        if self._parent is not None:
+            return self._parent
+        else:
+            from newstuff import getPackage
+            return getPackage(os.path.dirname(self.filename))
+
+
+    def __str__(self):
+        return "bike:Module:"+self.filename
+
+indentRE = re.compile("^(\s*)\S")
+class Node:
+    # module = the module node
+    # linenum = starting line number
+    def __init__(self, name, module, linenum, indent):
+        self.name = name
+        self.module = module
+        self.linenum = linenum
+        self.endline = None
+        self.indent = indent
+
+    def getMaskedLines(self):
+        return self.getMaskedModuleLines()[self.getStartLine()-1:self.getEndLine()-1]
+
+    def getStartLine(self):
+        return self.linenum
+
+    def getEndLine(self):
+        if self.endline is None:
+            physicallines = self.getMaskedModuleLines()
+            lineno = self.linenum
+            logicallines = generateLogicalLines(physicallines[lineno-1:])
+
+            # skip the first line, because it's the declaration
+            line = logicallines.next()
+            lineno+=line.count("\n")
+
+            # scan to the end of the fn
+            for line in logicallines:
+                #print lineno,":",line,
+                match = indentRE.match(line)
+                if match and match.end()-1 <= self.indent:
+                    break
+                lineno+=line.count("\n")
+            self.endline = lineno
+        return self.endline
+
+    # linenum starts at 0
+    def getLine(self, linenum):
+        return self._srclines[(self.getStartLine()-1) + linenum]
+
+
+baseClassesRE = re.compile("class\s+[^(]+\(([^)]+)\):")
+
+class Class(StructuralNode, Node):
+    def __init__(self, name, filename, module, linenum, indent, srclines, maskedmodulesrc):
+        StructuralNode.__init__(self, filename, srclines, maskedmodulesrc)
+        Node.__init__(self, name, module, linenum, indent)
+        self.type = "Class"
+
+    
+    def getBaseClassNames(self):
+        #line = self.getLine(0)
+        line = self.getLogicalLine(self.getStartLine())
+        match = baseClassesRE.search(line)
+        if match:
+            return [s.strip()for s in match.group(1).split(",")]
+        else:
+            return []
+
+    def getColumnOfName(self):
+        match = classNameRE.match(self.getLine(0))
+        return match.start(1)
+
+    def __repr__(self):
+        return "<bike:Class:%s>" % self.name
+
+    def __str__(self):
+        return "bike:Class:"+self.filename+":"+\
+               str(self.getStartLine())+":"+self.name
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Class) and \
+               node.name == self.name
+
+    def __eq__(self,other):
+        return isinstance(other,Class) and \
+               self.filename == other.filename and \
+               self.getStartLine() == other.getStartLine()
+
+# describes an instance of a class
+class Instance:
+    def __init__(self, type):
+        assert type is not None
+        self._type = type
+
+    def getType(self):
+        return self._type
+
+    def __str__(self):
+        return "Instance(%s)"%(self.getType())
+
+
+class Function(StructuralNode, Node):
+    def __init__(self, name, filename, module, linenum, indent,
+                 srclines, maskedsrc):
+        StructuralNode.__init__(self, filename, srclines, maskedsrc)
+        Node.__init__(self, name, module, linenum, indent)
+        self.type = "Function"
+
+    def getColumnOfName(self):
+        match = fnNameRE.match(self.getLine(0))
+        return match.start(1)
+
+    def __repr__(self):
+        return "<bike:Function:%s>" % self.name
+
+    def __str__(self):
+        return "bike:Function:"+self.filename+":"+\
+               str(self.getStartLine())+":"+self.name
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Function) and \
+               node.name == self.name
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/load.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+from bike.globals import *
+import os
+from bike.parsing.fastparser import fastparser
+
+class Cache:
+    def __init__(self):
+        self.reset()
+    def reset(self):
+        self.srcnodecache = {}
+        self.typecache = {}
+        self.maskedlinescache = {}
+
+    instance = None
+
+Cache.instance = Cache()
+
+class CantLocateSourceNodeException(Exception): pass
+
+def getSourceNode(filename_path):
+    #print "getSourceNode:",filename_path
+    sourcenode = None
+    
+    try:
+        sourcenode = Cache.instance.srcnodecache[filename_path]
+    except KeyError:
+        pass
+    
+    if sourcenode is None:
+        from bike.parsing.newstuff import translateFnameToModuleName
+        sourcenode = SourceFile.createFromFile(filename_path,
+                              translateFnameToModuleName(filename_path))
+    if sourcenode is None:
+        raise CantLocateSourceNodeException(filename_path)
+
+    Cache.instance.srcnodecache[filename_path]=sourcenode
+    return sourcenode
+
+class SourceFile:
+
+    def createFromString(filename, modulename, src):
+        return SourceFile(filename,modulename,src)
+    createFromString = staticmethod(createFromString)
+
+    def createFromFile(filename,modulename):
+        try:
+            f = file(filename)
+            src = f.read()
+            f.close()
+        except IOError:
+            return None
+        else:
+            return SourceFile(filename,modulename,src)
+                
+    createFromFile = staticmethod(createFromFile)
+    
+    def __init__(self, filename, modulename, src):
+
+        if os.path.isabs(filename):
+            self.filename = filename
+        else:
+            self.filename = os.path.abspath(filename)
+        self.modulename = modulename
+
+        self.resetWithSource(src)
+
+    def resetWithSource(self, source):
+        # fastparser ast
+        self.fastparseroot = fastparser(source,self.modulename,self.filename)
+        self.fastparseroot.setSourceNode(self)
+        self._lines = source.splitlines(1)
+        self.sourcenode = self
+
+    def __repr__(self):
+        return "Source(%s,%s)"%('source', self.filename)
+
+    def getChildNodes(self):
+        return self.fastparseroot.getChildNodes()        
+        
+    def getSource(self):
+        return  "".join(self.getLines())
+
+    def getLine(self,linenum):
+        return self.getLines()[linenum-1]
+
+    # TODO: rename me!
+    def getFlattenedListOfFastParserASTNodes(self):
+        return self.fastparseroot.getFlattenedListOfChildNodes()
+        
+    def getLines(self):
+        return self._lines
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/newstuff.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+from __future__ import generators 
+# Holding module for scaffolding needed to transition parsing package
+# into stateless design
+import os
+import re
+from bike.parsing.pathutils import getRootDirectory, getPackageBaseDirectory, \
+     filenameToModulePath, getPathOfModuleOrPackage, getFilesForName
+from bike.parsing.fastparserast import Module, Package, getRoot, getPackage, getModule 
+import sys
+from bike.parsing.load import getSourceNode, CantLocateSourceNodeException
+
+
+def translateFnameToModuleName(filename_path):
+    return filenameToModulePath(filename_path)
+
+
+
+# scope is the scope to search from
+def getModuleOrPackageUsingFQN(fqn, dirpath=None):
+    pythonpath = getPythonPath()
+    #print "getModuleOrPackageUsingFQN",pythonpath,fqn
+    if dirpath is not None:
+        assert os.path.isdir(dirpath)
+        pythonpath = [dirpath] + pythonpath
+    filename = getPathOfModuleOrPackage(fqn,pythonpath)
+    #print "getModuleOrPackageUsingFQN - filename",filename
+    if filename is not None:
+        if os.path.isdir(filename):
+            return getPackage(filename)
+        else:
+            return getModule(filename)
+    else:
+        return None
+
+def getPythonPath():
+    return getRoot().pythonpath
+
+
+def generateModuleFilenamesInPythonPath(contextFilename):
+    files = []
+    rootdir = getRootDirectory(contextFilename)
+    if rootdir in getPythonPath():
+        # just search the pythonpath
+        for path in getPythonPath():
+            for file in getFilesForName(path):
+                if file not in files:   # check for duplicates
+                    files.append(file)
+                    yield file
+    else:
+        # search the package hierarchy containing contextFilename
+        # in addition to pythonpath
+        basedir = getPackageBaseDirectory(contextFilename)
+        for path in [basedir] + getPythonPath():
+            for file in getFilesForName(path):
+                if file not in files:   # check for duplicates
+                    files.append(file)
+                    yield file
+
+        # and search the files immediately above the package hierarchy
+        for file in getFilesForName(os.path.join(rootdir,"*.py")):
+            if file not in files:   # check for duplicates
+                files.append(file)
+                yield file
+
+def generateModuleFilenamesInPackage(filenameInPackage):
+    basedir = getPackageBaseDirectory(filenameInPackage)
+    for file in getFilesForName(basedir):
+        yield file
+
+
+
+# search all sourcenodes globally from the perspective of file 'contextFilename'
+def getSourceNodesContainingRegex(regexstr,contextFilename):
+    regex = re.compile(regexstr)
+    for fname in generateModuleFilenamesInPythonPath(contextFilename):
+        try:
+            f = file(fname)
+            src = f.read()
+        finally:
+            f.close()
+        if regex.search(src) is not None:
+            yield getSourceNode(fname)
+
+
+
+
+fromRegex = re.compile("^\s*from\s+(\w+)\s+import")
+importregex = re.compile("^\s*import\s+(\w+)")
+
+# fileInPackage is the filename of a file in the package hierarchy
+# generates file and directory paths
+def generatePackageDependencies(fileInPackage):
+    rejectPackagePaths = [getPackageBaseDirectory(fileInPackage)]
+    for fname in generateModuleFilenamesInPackage(fileInPackage):
+
+        try:
+            f = file(fname)
+            src = f.read()
+        finally:
+            f.close()
+
+        packagepath = None
+
+        for line in src.splitlines():
+            match = fromRegex.search(line) or importregex.search(line)
+            if match is not None:
+                modulepath = match.group(1)
+                packagename = modulepath.split('.')[0]
+                packagepath = getPathOfModuleOrPackage(packagename,
+                                                       getPythonPath())
+            if packagepath is not None and \
+                   packagepath not in rejectPackagePaths:
+                rejectPackagePaths.append(packagepath) # avoid duplicates
+                yield packagepath
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/parserutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,194 @@
+from __future__ import generators
+import re
+
+escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
+
+# changess \" \' and \\ into ** so that text searches
+# for " and ' won't hit escaped ones
+def maskEscapedQuotes(src):
+    return escapedQuotesRE.sub("**", src)
+
+stringsAndCommentsRE =  \
+      re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
+
+import string
+#transtable = string.maketrans('classdefifforwhiletry', "*********************")
+
+# performs a transformation on all of the comments and strings so that
+# text searches for python keywords won't accidently find a keyword in
+# a string or comment
+def maskPythonKeywordsInStringsAndComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        allstrings[i] = allstrings[i].upper()
+        #allstrings[i] = allstrings[i].translate(transtable)
+    return "".join(allstrings)
+
+
+allchars = string.maketrans("", "")
+allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
+allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
+
+
+# replaces all chars in a string or a comment with * (except newlines).
+# this ensures that text searches don't mistake comments for keywords, and that all
+# matches are in the same line/comment as the original
+def maskStringsAndComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
+            allstrings[i] = allstrings[i][:3]+ \
+                           allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-3:]
+        else:
+            allstrings[i] = allstrings[i][0]+ \
+                           allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-1]
+
+    return "".join(allstrings)
+
+
+# replaces all chars in a string or a comment with * (except newlines).
+# this ensures that text searches don't mistake comments for keywords, and that all
+# matches are in the same line/comment as the original
+def maskStringsAndRemoveComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
+            allstrings[i] = allstrings[i][:3]+ \
+                           allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-3:]
+        elif allstrings[i].startswith("#"):
+            allstrings[i] = '\n'
+        else:
+            allstrings[i] = allstrings[i][0]+ \
+                           allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-1]
+    return "".join(allstrings)
+        
+
+implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
+emptyHangingBraces = [0,0,0,0,0]
+linecontinueRE = re.compile(r"\\\s*(#.*)?$")
+multiLineStringsRE =  \
+      re.compile("(^.*?\"\"\".*?\"\"\".*?$|^.*?'''.*?'''.*?$)", re.DOTALL)
+
+#def splitLogicalLines(src):
+#    src = multiLineStringsRE.split(src)
+
+# splits the string into logical lines.  This requires the comments to
+# be removed, and strings masked (see other fns in this module)
+def splitLogicalLines(src):
+    physicallines = src.splitlines(1)
+    return [x for x in generateLogicalLines(physicallines)]
+
+
+class UnbalancedBracesException: pass
+
+# splits the string into logical lines.  This requires the strings
+# masked (see other fns in this module)
+# Physical Lines *Must* start on a non-continued non-in-a-comment line
+# (although detects unbalanced braces)
+def generateLogicalLines(physicallines):
+    tmp = []
+    hangingBraces = list(emptyHangingBraces)
+    hangingComments = 0
+    for line in physicallines:
+        # update hanging braces
+        for i in range(len(implicitContinuationChars)):
+            contchar = implicitContinuationChars[i]
+            numHanging = hangingBraces[i]
+            hangingBraces[i] = numHanging+line.count(contchar[0]) - \
+                               line.count(contchar[1])
+
+        hangingComments ^= line.count('"""') % 2
+        hangingComments ^= line.count("'''") % 2
+
+        if hangingBraces[0] < 0 or \
+           hangingBraces[1] < 0 or \
+           hangingBraces[2] < 0:
+            raise UnbalancedBracesException()
+        
+        if linecontinueRE.search(line):
+            tmp.append(line)
+        elif hangingBraces != emptyHangingBraces:
+            tmp.append(line)
+        elif hangingComments:
+            tmp.append(line)
+        else:
+            tmp.append(line)
+            yield "".join(tmp)
+            tmp = []
+    
+
+# see above but yields (line,linenum)
+#   needs physicallines to have linenum attribute
+#   TODO: refactor with previous function
+def generateLogicalLinesAndLineNumbers(physicallines):
+    tmp = []
+    hangingBraces = list(emptyHangingBraces)
+    hangingComments = 0
+    linenum = None
+    for line in physicallines:
+        if tmp == []:
+            linenum = line.linenum
+
+        # update hanging braces
+        for i in range(len(implicitContinuationChars)):
+            contchar = implicitContinuationChars[i]
+            numHanging = hangingBraces[i]
+            hangingBraces[i] = numHanging+line.count(contchar[0]) - \
+                               line.count(contchar[1])
+
+        hangingComments ^= line.count('"""') % 2
+        hangingComments ^= line.count("'''") % 2
+            
+        if linecontinueRE.search(line):
+            tmp.append(line)
+        elif hangingBraces != emptyHangingBraces:
+            tmp.append(line)
+        elif hangingComments:
+            tmp.append(line)
+        else:
+            tmp.append(line)
+            yield "".join(tmp),linenum
+            tmp = []
+        
+
+
+
+# takes a line of code, and decorates it with noops so that it can be
+# parsed by the python compiler.
+# e.g.  "if foo:"  -> "if foo: pass"
+# returns the line, and the adjustment made to the column pos of the first char
+# line must have strings and comments masked
+#
+# N.B. it only inserts keywords whitespace and 0's
+notSpaceRE = re.compile("\s*(\S)")
+commentRE = re.compile("#.*$")
+
+def makeLineParseable(line):
+    return makeLineParseableWhenCommentsRemoved(commentRE.sub("",line))
+
+def makeLineParseableWhenCommentsRemoved(line):
+    line = line.strip()
+    if ":" in line:
+        if line.endswith(":"):
+            line += " pass"
+        if line.startswith("try"):
+            line += "\nexcept: pass"
+        elif line.startswith("except") or line.startswith("finally"):
+            line = "try: pass\n" + line
+            return line
+        elif line.startswith("else") or line.startswith("elif"):
+            line = "if 0: pass\n" + line
+            return line
+    elif line.startswith("yield"):
+        return ("return"+line[5:])
+    return line
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/pathutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,165 @@
+
+# A some of this code is take from Pythius -
+# Copyright (GPL) 2001 Jurgen Hermann <jh@web.de>
+
+from bike.globals import *
+import os
+
+def containsAny(str, set):
+    """ Check whether 'str' contains ANY of the chars in 'set'
+    """
+    return 1 in [c in str for c in set]
+
+
+
+def getPathOfModuleOrPackage(dotted_name, pathlist = None):
+    """ Get the filesystem path for a module or a package.
+
+        Return the file system path to a file for a module,
+        and to a directory for a package. Return None if
+        the name is not found, or is a builtin or extension module.
+    """
+    from bike.parsing.newstuff import getPythonPath
+    if pathlist is None:
+        pathlist = getPythonPath()
+
+    import imp
+
+    # split off top-most name
+    parts = dotted_name.split('.', 1)
+
+    if len(parts) > 1:
+        # we have a dotted path, import top-level package
+        try:
+            file, pathname, description = imp.find_module(parts[0], pathlist)
+            if file: file.close()
+        except ImportError:
+            return None
+
+        # check if it's indeed a package
+        if description[2] == imp.PKG_DIRECTORY:
+            # recursively handle the remaining name parts
+            pathname = getPathOfModuleOrPackage(parts[1], [pathname])
+        else:
+            pathname = None
+    else:
+        # plain name
+        try:
+            file, pathname, description = imp.find_module(dotted_name, pathlist)
+            if file: file.close()
+            if description[2]not in[imp.PY_SOURCE, imp.PKG_DIRECTORY]:
+                pathname = None
+        except ImportError:
+            pathname = None
+
+    return pathname
+
+
+def getFilesForName(name):
+    """ Get a list of module files for a filename, a module or package name,
+        or a directory.
+    """
+    import imp
+
+    if not os.path.exists(name):
+        # check for glob chars
+        if containsAny(name, "*?[]"):
+            import glob
+            files = glob.glob(name)
+            list = []
+            for file in files:
+                list.extend(getFilesForName(file))
+            return list
+
+        # try to find module or package
+        name = getPathOfModuleOrPackage(name)
+        if not name:
+            return[]
+
+    if os.path.isdir(name):
+        # find all python files in directory
+        list = []
+        os.path.walk(name, _visit_pyfiles, list)
+        return list
+    elif os.path.exists(name) and not name.startswith("."):
+        # a single file
+        return [name]
+
+    return []
+
+def _visit_pyfiles(list, dirname, names):
+    """ Helper for getFilesForName().
+    """
+    # get extension for python source files
+    if not globals().has_key('_py_ext'):
+        import imp
+        global _py_ext
+        _py_ext = [triple[0]for triple in imp.get_suffixes()if triple[2] == imp.PY_SOURCE][0]
+
+    # don't recurse into CVS or Subversion directories
+    if 'CVS'in names:
+        names.remove('CVS')
+    if '.svn'in names:
+        names.remove('.svn')
+
+    names_copy = [] + names
+    for n in names_copy:
+        if os.path.isdir(os.path.join(dirname, n))and \
+           not os.path.exists(os.path.join(dirname, n, "__init__.py")):
+            names.remove(n)
+
+    # add all *.py files to list
+    list.extend(
+    [os.path.join(dirname, file)
+    for file in names
+    if os.path.splitext(file)[1] == _py_ext and not file.startswith(".")])
+
+
+# returns the directory which holds the first package of the package
+# hierarchy under which 'filename' belongs
+def getRootDirectory(filename):
+    if os.path.isdir(filename):
+        dir = filename
+    else:
+        dir = os.path.dirname(filename)
+    while dir != "" and \
+          os.path.exists(os.path.join(dir, "__init__.py")):
+        dir = os.path.dirname(dir)
+    return dir
+
+
+
+# Returns the root package directoryname of the package hierarchy
+# under which 'filename' belongs
+def getPackageBaseDirectory(filename):
+    if os.path.isdir(filename):
+        dir = filename
+    else:
+        dir = os.path.dirname(filename)
+
+    if not os.path.exists(os.path.join(dir, "__init__.py")):
+        # parent dir is not a package
+        return dir
+
+    while dir != "" and \
+          os.path.exists(os.path.join(os.path.dirname(dir), "__init__.py")):
+        dir = os.path.dirname(dir)
+    return dir
+
+
+
+def filenameToModulePath(fname):
+    directoriesPreceedingRoot = getRootDirectory(fname)
+    import os
+    # strip off directories preceeding root package directory
+    if directoriesPreceedingRoot != "":
+        mpath = fname.replace(directoriesPreceedingRoot, "")
+    else:
+        mpath = fname
+
+    if(mpath[0] == os.path.normpath("/")):
+        mpath = mpath[1:]
+    mpath, ext = os.path.splitext(mpath)
+    mpath = mpath.replace(os.path.normpath("/"), ".")
+    return mpath
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("../..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath("../.."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_fastparser.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+import unittest
+from fastparser import*
+from bike.parsing.load import*
+from bike.parsing.fastparserast import*
+from bike.testutils import *
+
+class TestFastParser(BRMTestCase):
+    def test_doesntGetClassDeclsInMLStrings(self):
+        src = trimLines('''
+        """
+        class foo bah
+        """
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() == []
+
+    def test_evaluatesMLStringWithQuoteInIt(self):
+        src = trimLines('''
+        """some ml comment inclosing a " """
+        def foo:
+            pass 
+        " hello "
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+
+    def test_handlesClassDefsWithTwoSpacesInDecl(self):
+        src = trimLines('''
+        class  foo: pass
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+        
+    def test_handlesFnDefsWithTwoSpacesInDecl(self):
+        src = trimLines('''
+        def  foo: pass
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+
+
+MLStringWithQuoteInIt = """
+\"\"\"some ml comment inclosing a \" \"\"\"
+def foo:
+    pass
+\" hello \"
+"""
+
+def load(path):
+    files = getFilesForName(path)
+    for fname in files:
+        src = file(fname).read()
+        fastparser(src)
+        #print fname
+        #myroot = parseFile(fname)
+
+
+
+def fastparsetreeToString(root):
+    class stringholder: pass
+    s = stringholder()
+    s.mystr = ""
+    s.tabstr = ""
+    def t2s(node):
+        if isinstance(node, Class):
+            s.mystr+=s.tabstr+"class "+node.name+"\n"
+            s.tabstr+="\t"
+            for n in node.getChildNodes():
+                t2s(n)
+            s.tabstr = s.tabstr[:-1]
+
+        elif isinstance(node, Function):
+            s.mystr+=s.tabstr+"function "+node.name+"\n"
+            s.tabstr+="\t"
+            for n in node.getChildNodes():
+                t2s(n)
+            s.tabstr = s.tabstr[:-1]
+
+
+    for n in root.getChildNodes():
+        t2s(n)
+    return s.mystr
+
+
+def compilerParseTreeToString(root):
+    try:
+        class TreeVisitor:
+            def __init__(self):
+                self.mystr = ""
+                self.tabstr = ""
+
+            def visitClass(self, node):
+                self.mystr+=self.tabstr+"class "+node.name+"\n"
+                self.tabstr+="\t"
+                for child in node.getChildNodes():
+                    self.visit(child)
+                self.tabstr = self.tabstr[:-1]
+
+            def visitFunction(self, node):
+                self.mystr+=self.tabstr+"function "+node.name+"\n"
+                self.tabstr+="\t"
+                for child in node.getChildNodes():
+                    self.visit(child)
+                self.tabstr = self.tabstr[:-1]
+
+        return compiler.walk(root, TreeVisitor()).mystr
+
+    except:
+        log.exception("ex")
+        import sys
+        sys.exit(0)
+
+
+def compareCompilerWithFastparserOverPath(path):
+    from bike.parsing.load import getFilesForName
+    files = getFilesForName(path)
+    for fname in files:
+        if fname.endswith("bdist_wininst.py"): continue
+        log.info(fname)
+        src = file(fname).read()
+        try:
+            compiler_root = compiler.parse(src)
+        except SyntaxError:
+            continue
+        fastparse_root = fastparser(src)
+        str1 = fastparsetreeToString(fastparse_root)
+        str2 = compilerParseTreeToString(compiler_root)
+        assert str1 == str2, "\n"+"-"*70+"\n"+str1+"-"*70+"\n"+str2
+
+
+def timeParseOfPythonLibrary(path):
+    import time
+    t1 = time.time()
+    files = getFilesForName(path)
+    import sys
+    for fname in files:
+        if fname.endswith("bdist_wininst.py"): continue
+        src = file(fname).read()
+        fastparser(src)
+    print "\n", time.time()-t1
+
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.INFO)
+    # add soak tests to end of test
+    class Z_SoakTestFastparser(BRMTestCase):
+
+        def test_A_timeParseOfPythonLibrary(self):
+            timeParseOfPythonLibrary("/usr/local/lib/python2.2")
+
+        def test_parsesPythonLibraryCorrectly(self):
+            print ""
+            compareCompilerWithFastparserOverPath("/usr/local/lib/python2.2")
+
+    unittest.main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_fastparserast.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+import unittest
+from fastparserast import *
+from fastparser import fastparser
+from bike.query.getTypeOf import getTypeOf
+from bike.testutils import *
+
+class TestGetModule(BRMTestCase):
+
+    def test_getRootWorksAfterDefinedByCreateSourceNodeAt(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        assert root == getRoot()
+
+    def test_returnsNoneIfModuleDoesntExist(self):
+        assert getModule(tmpfile) == None
+
+
+class TestGetEndLine(BRMTestCase):
+    def test_returnsEndLineWithSimpleFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        root = fastparser(src)
+        fn = getTypeOf(root,"foo")
+        self.assertEqual(fn.getEndLine(),7)
+
+    def test_worksWithFunctionsThatHaveEmptyLinesInThem(self):
+        src = fnWithEmptyLineInIt
+        root = fastparser(src)
+        fn = getTypeOf(root,"TheClass.theFunction")
+        self.assertEqual(fn.getEndLine(),8)
+
+class TestGetBaseClassNames(BRMTestCase):
+    def test_worksForClassHierarchy(self):
+        src = trimLines("""
+        class root:
+            def theMethod():
+                pass
+
+        class a(root):
+            def theMethod():
+                pass    
+
+        class b(root):
+            pass
+
+        class TheClass(a,b):
+            def theMethod():
+                pass
+
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+        #classes = getASTNodeFromSrc(src,"Source").fastparseroot.getChildNodes()
+        classes = createAST(src).fastparseroot.getChildNodes()
+        self.assertEqual(classes[3].getBaseClassNames(),['a','b'])
+
+    def test_returnsEmptyListForClassWithNoBases(self):
+        src = trimLines("""
+        class root:
+            pass
+        """)
+        #classes = getASTNodeFromSrc(src,"Source").fastparseroot.getChildNodes()
+        classes = createAST(src).fastparseroot.getChildNodes()        
+        self.assertEqual(classes[0].getBaseClassNames(),[])
+
+
+class TestGetMaskedLines(BRMTestCase):
+    def test_doit(self):
+        src =trimLines("""
+        class foo: #bah
+            pass
+        """)
+        mod = createAST(src).fastparseroot
+        lines = mod.getMaskedModuleLines()
+        assert lines[0] == "class foo: #***\n"
+
+
+class TestGetLinesNotIncludingThoseBelongingToChildScopes(BRMTestCase):
+    def test_worksForModule(self):
+        src =trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        mod = createAST(src).fastparseroot
+        self.assertEqual(''.join(mod.getLinesNotIncludingThoseBelongingToChildScopes()),
+                         trimLines("""
+                         a = foo()
+                         a.theMethod()
+                         """))
+
+    def test_worksForModuleWithSingleLineFunctions(self):
+        src=trimLines("""
+        a = blah()
+        def foo(): pass
+        b = 1
+        """)
+        mod = createAST(src).fastparseroot
+        lines = mod.getLinesNotIncludingThoseBelongingToChildScopes()
+        self.assertEqual(''.join(lines),
+                         trimLines("""
+                         a = blah()
+                         b = 1
+                         """))
+
+
+    def test_worksForSingleLineFunction(self):
+        src=trimLines("""
+        a = blah()
+        def foo(): pass
+        b = 1
+        """)
+        fn = createAST(src).fastparseroot.getChildNodes()[0]
+        lines = fn.getLinesNotIncludingThoseBelongingToChildScopes()
+        self.assertEqual(''.join(lines),
+                         trimLines("""
+                         def foo(): pass
+                         """))
+
+
+fnWithEmptyLineInIt = """
+class TheClass:
+    def theFunction():
+        a = foo()
+
+        print 'a'
+
+    # end of function
+"""
+
+if __name__ == "__main__":
+    unittest.main()
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_load.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import compiler
+import os
+
+from bike import testdata
+from bike.testutils import *
+from bike.mock import Mock
+
+from pathutils import getPathOfModuleOrPackage
+from load import *
+import load as loadmodule
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_newstuff.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+import setpath
+import os
+import unittest
+from bike.testutils import *
+from bike.parsing.fastparserast import getRoot
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN,\
+     generateModuleFilenamesInPythonPath, getSourceNodesContainingRegex,\
+     generatePackageDependencies
+     
+
+class TestGetModuleOrPackageUsingFQN(BRMTestCase):
+    def test_worksForFullPath(self):
+        try:
+            createPackageStructure("pass","pass")
+            self.assertEqual(getModuleOrPackageUsingFQN("a.b.bah").filename,
+                             pkgstructureFile2)
+        finally:
+            removePackageStructure()
+        
+    def test_worksForPackage(self):
+        try:
+            createPackageStructure("pass","pass")
+            self.assertEqual(getModuleOrPackageUsingFQN("a.b").path,
+                             pkgstructureChilddir)
+        finally:
+            removePackageStructure()
+
+
+class TestGenerateModuleFilenamesInPythonPath(BRMTestCase):
+    def test_works(self):
+        try:
+            createPackageStructure("pass","pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+
+
+            assert os.path.join(pkgstructureBasedir,"__init__.py") in fnames
+            assert pkgstructureFile1 in fnames
+            assert os.path.join(pkgstructureChilddir,"__init__.py") in fnames
+            assert pkgstructureFile2 in fnames
+            assert len(fnames) == 5
+        finally:
+            removePackageStructure()
+
+        
+
+    def test_doesntTraverseIntoNonPackages(self):
+        try:
+            createPackageStructure("pass","pass")
+            nonPkgDir = os.path.join(pkgstructureChilddir,"c")
+            newfile = os.path.join(nonPkgDir,"baz.py")
+            # N.B. don't put an __init__.py in it, so isnt a package
+            os.makedirs(nonPkgDir)
+            writeFile(newfile,"pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert newfile not in fnames
+        finally:
+            #os.remove(initfile)
+            os.remove(newfile)
+            os.removedirs(nonPkgDir)
+            removePackageStructure()
+
+
+    def test_doesScanFilesInTheRootDirectory(self):
+        try:
+            createPackageStructure("pass","pass","pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert pkgstructureFile0 in fnames
+        finally:
+            #os.remove(initfile)
+            removePackageStructure()
+
+    def test_returnsOtherFilesInSameNonPackageDirectory(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            writeTmpTestFile("")
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, "")
+            fnames = [f for f in \
+                      generateModuleFilenamesInPythonPath(tmpfile)]
+            assert newtmpfile in fnames
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+            getRoot().pythonpath = oldpath
+            
+
+
+    def test_doesntTraverseIntoNonPackagesUnderRoot(self):
+        try:
+            os.makedirs(pkgstructureBasedir)
+            writeFile(pkgstructureFile1,"pass")
+            fnames = [f for f in \
+                      generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert pkgstructureFile1 not in fnames
+        finally:
+            os.remove(pkgstructureFile1)
+            os.removedirs(pkgstructureBasedir)
+
+
+    def test_doesntGenerateFilenamesMoreThanOnce(self):
+        try:
+            createPackageStructure("pass","pass")
+            newfile = os.path.join(pkgstructureChilddir,"baz.py")
+            writeFile(newfile,"pass")
+            fnames = [f for f in \
+                generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            matched = [f for f in fnames if f == newfile]
+            self.assertEqual(1, len(matched))
+        finally:
+            os.remove(newfile)
+            removePackageStructure()
+
+class TestGetSourceNodesContainingRegex(BRMTestCase):
+    def test_works(self):
+        try:
+            createPackageStructure("# testregexfoobah","pass")
+            srcfiles = [s for s in 
+                        getSourceNodesContainingRegex("testregexfoobah",
+                                                      pkgstructureFile2)]
+            self.assertEqual(pkgstructureFile1,srcfiles[0].filename)
+        finally:
+            removePackageStructure()
+
+class TestGenerateModuleFilenamesInPythonPath2(BRMTestCase):
+    def test_getsAllFilenamesInSameHierarchyAsContextFile(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile1)]
+            self.assert_(pkgstructureFile0 in fnames)
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            removePackageStructure()
+
+    def test_getsFilenamesInSubPackagesIfCtxFilenameIsInTheRoot(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile0)]
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            removePackageStructure()
+
+    def test_doesntTraverseOtherPackagesOffOfTheRoot(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            os.makedirs(os.path.join(pkgstructureRootDir, "c"))
+            writeFile(os.path.join(pkgstructureRootDir, "c", "__init__.py"), "# ")
+            bazfile = os.path.join(pkgstructureRootDir, "c", "baz.py")
+            writeFile(bazfile, "pass")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile1)]
+            self.assert_(pkgstructureFile0 in fnames)
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+            self.assert_(bazfile not in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            os.remove(os.path.join(pkgstructureRootDir, "c", "baz.py"))
+            os.remove(os.path.join(pkgstructureRootDir, "c", "__init__.py"))
+            os.removedirs(os.path.join(pkgstructureRootDir, "c"))
+            removePackageStructure()
+
+
+class TestGetPackageDependencies(BRMTestCase):
+
+    def test_followsImportModule(self):
+        try:
+            createPackageStructure("","import c.bing")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_followsFromImportPackage(self):
+        try:
+            createPackageStructure("","import c")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+
+    def test_followsFromImportStar(self):
+        try:
+            createPackageStructure("","from c import *")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+    def test_followsFromImportModule(self):
+        try:
+            createPackageStructure("","from c import bing")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntBreakIfImportIsInAMultilineString(self):
+        try:
+            createPackageStructure("",trimLines("""
+            '''
+            from aoeuaoeu import aocxaoieicxoe
+            '''
+            """))
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+    def test_doesntBreakIfImportIsCommented(self):
+        try:
+            createPackageStructure("","#from aoeuaoeu import aocxaoieicxoe")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntBreakIfCantFindImport(self):
+        try:
+            createPackageStructure("","from aoeuaoeu import aocxaoieicxoe")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntIncludeCurrentPackage(self):
+        try:
+            createPackageStructure("","import a.foo")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_parserutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+import unittest
+from parserutils import *
+from bike.testutils import *
+
+class TestRemoveEscapedQuotes(BRMTestCase):
+
+    def testMaskEscapedQuotes_MasksEscapedQuotes(self):
+        src = '\" \\\\\\\" \' \\\\\\\\\"  \'  \''
+        self.assertEqual(maskEscapedQuotes(src),'" **** \' ****"  \'  \'')
+
+class TestMungePythonKeywordsInStrings(BRMTestCase):
+    def test_mungesKeywords(self):
+        src = '\"\"\"class try while\"\"\" class2 try2 while2 \'\'\' def if for \'\'\' def2 if2 for2'
+        self.assertEqual(maskPythonKeywordsInStringsAndComments(src),
+                      '"""CLASS TRY WHILE""" class2 try2 while2 \'\'\' DEF IF FOR \'\'\' def2 if2 for2')
+
+
+class TestSplitLines(BRMTestCase):
+    def test_handlesExplicitlyContinuedLineWithComment(self):
+        self.assertEqual(splitLogicalLines(explicitlyContinuedLineWithComment),
+              ['\n', 'z = a + b + \\  # comment\n  c + d\n', 'pass\n'])
+
+    def test_handlesImplicitlyContinuedLine(self):
+        self.assertEqual(splitLogicalLines(implicitlyContinuedLine), 
+                         ['\n', 'z = a + b + (\n  c + d)\n', 'pass\n'])
+
+    def test_handlesNestedImplicitlyContinuedLine(self):
+        self.assertEqual(splitLogicalLines(implicitlyContinuedLine2), 
+                         ['\n', 'z = a + b + ( c + [d\n  + e]\n  + f)   # comment\n', 'pass\n'])
+
+
+    def test_handlesMultiLineStrings(self):
+        self.assertEqual(splitLogicalLines(multilineComment),
+                         ['\n', "''' this is an mlc\nso is this\n'''\n", 'pass\n'])
+                         
+
+class TestMakeLineParseable(BRMTestCase):
+    def test_worksWithIfStatement(self):
+        src = "if foo:"
+        self.assertEqual(makeLineParseable(src),("if foo: pass"))
+
+    def test_worksWithTryStatement(self):
+        src = "try :"
+        self.assertEqual(makeLineParseable(src),("try : pass\nexcept: pass"))
+
+    def test_worksOnTryStatementWithCodeInlined(self):
+        src = "try : a = 1"
+        self.assertEqual(makeLineParseable(src),("try : a = 1\nexcept: pass"))
+
+    def test_worksWithExceptStatement(self):
+        src = "except :"
+        self.assertEqual(makeLineParseable(src),("try: pass\nexcept : pass"))
+
+    def test_worksWithFinallyStatement(self):
+        src = "finally:"
+        self.assertEqual(makeLineParseable(src),("try: pass\nfinally: pass"))
+
+    def test_worksWithIfStatement(self):
+        src = "if foo:"
+        self.assertEqual(makeLineParseable(src),("if foo: pass"))
+
+    def test_worksWithElseStatement(self):
+        src = "else :"
+        self.assertEqual(makeLineParseable(src),("if 0: pass\nelse : pass"))
+
+    def test_worksWithElifStatement(self):
+        src = "elif foo:"
+        self.assertEqual(makeLineParseable(src),("if 0: pass\nelif foo: pass"))
+
+
+def runOverPath(path):
+    import compiler
+    from parser import ParserError
+    from bike.parsing.load import getFilesForName
+    files = getFilesForName(path)
+    for fname in files:
+        print fname
+        src = file(fname).read()
+        #print src
+        src = maskStringsAndRemoveComments(src)
+
+        for logicalline in splitLogicalLines(src):
+            #print "logicalline=",logicalline    
+            logicalline = logicalline.strip()
+            logicalline = makeLineParseable(logicalline)
+            try:
+                compiler.parse(logicalline)
+            except ParserError:
+                print "ParserError on logicalline:",logicalline
+            except:
+                log.exception("caught exception")
+                
+
+explicitlyContinuedLineWithComment = """
+z = a + b + \  # comment
+  c + d
+pass
+"""
+
+implicitlyContinuedLine = """
+z = a + b + (
+  c + d)
+pass
+"""
+
+
+implicitlyContinuedLine2 = """
+z = a + b + ( c + [d
+  + e]
+  + f)   # comment
+pass
+"""
+
+multilineComment = """
+''' this is an mlc
+so is this
+'''
+pass
+"""
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.INFO)
+    
+    # add soak tests to end of test
+    class Z_SoakTest(BRMTestCase):
+        def test_linesRunThroughPythonParser(self):
+            print ""
+            #print splitLogicalLines(file('/usr/local/lib/python2.2/aifc.py').read())
+            #runOverPath('/usr/local/lib/python2.2/test/badsyntax_nocaret.py')
+            runOverPath('/usr/local/lib/python2.2/')
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_pathutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import compiler
+import os
+
+from bike import testdata
+from bike.testutils import *
+from bike.mock import Mock
+
+from pathutils import getPathOfModuleOrPackage
+from pathutils import *
+import pathutils as loadmodule
+
+class TestGetFilesForName(BRMTestCase):
+    def testGetFilesForName_recursivelyReturnsFilesInBreadthFirstOrder(self):
+        createPackageStructure("pass", "pass")
+
+        files = getFilesForName(pkgstructureBasedir)
+        for f in files:
+            assert f in \
+                  [os.path.join(pkgstructureBasedir, '__init__.py'), 
+                    os.path.join(pkgstructureBasedir, 'foo.py'), 
+                    os.path.join(pkgstructureChilddir, '__init__.py'), 
+                    os.path.join(pkgstructureChilddir, 'bah.py')]
+
+    def testGetFilesForName_globsStars(self):
+        createPackageStructure("pass", "pass")
+        assert getFilesForName(os.path.join(pkgstructureBasedir, "fo*")) == [os.path.join(pkgstructureBasedir, 'foo.py')]
+        removePackageStructure()
+
+    def testGetFilesForName_doesntListFilesWithDotAtFront(self):
+        writeFile(os.path.join(".foobah.py"),"")
+        files = getFilesForName("a")
+        self.assertEqual([],files)
+        
+
+
+
+class TestGetRootDirectory(BRMTestCase):
+    def test_returnsParentDirectoryIfFileNotInPackage(self):
+        try:
+            # this doesnt have __init__.py file, so
+            # isnt package
+            os.makedirs("a")
+            writeFile(os.path.join("a", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("a", "foo.py"))
+            assert dir == "a"
+        finally:
+            os.remove(os.path.join("a", "foo.py"))
+            os.removedirs(os.path.join("a"))
+
+    def test_returnsFirstNonPackageParentDirectoryIfFileInPackage(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("root", "a", "b", "foo.py"))
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+    def test_returnsFirstNonPackageParentDirectoryIfPathIsAPackage(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("root", "a", "b"))
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+    def test_returnsDirIfDirIsTheRootDirectory(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory("root")
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+
+class getPackageBaseDirectory(BRMTestCase):
+    def test_returnsBasePackageIfFileInPackageHierarchy(self):
+        try:
+            createPackageStructure("","")
+            dir = loadmodule.getPackageBaseDirectory(pkgstructureFile2)
+            self.assertEqual(pkgstructureBasedir, dir)
+        finally:
+            removePackageStructure()
+
+    def test_returnsFileDirectoryIfFileNotInPackage(self):
+        try:
+            createPackageStructure("","")
+            dir = loadmodule.getPackageBaseDirectory(pkgstructureFile0)
+            self.assertEqual(pkgstructureRootDir, dir)
+        finally:
+            removePackageStructure()
+
+
+class TestGetPathOfModuleOrPackage(BRMTestCase):
+    def test_worksForFullPath(self):
+        try:
+            createPackageStructure("pass","pass")
+            import sys
+            self.assertEqual(getPathOfModuleOrPackage("a.b.bah",
+                                                      [pkgstructureRootDir]),
+                             pkgstructureFile2)
+        finally:
+            removePackageStructure()
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from utils import *
+
+class Test_CarCdrEtc(unittest.TestCase):
+    def test_carReturnsTheFirstElementOfTheFqn(self):
+        fqn = "apple.pear.foo"
+        assert fqn_car(fqn) == "apple"
+        
+    def test_carReturnsElementInOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_car(fqn) == "apple"
+
+    def test_cdrReturnsTheAllElementsOfTheFqnExceptFirst(self):
+        fqn = "apple.pear.foo"
+        assert fqn_cdr(fqn) == "pear.foo"
+        
+    def test_cdrReturnsEmptyStringForOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_cdr(fqn) == ""
+
+    def test_rcarReturnsTheLastElementOfTheFqn(self):
+        fqn = "apple.pear.foo"
+        assert fqn_rcar(fqn) == "foo"
+        
+    def test_rcarReturnsElementInOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_rcar(fqn) == "apple"
+
+    def test_rdrReturnsTheAllElementsOfTheFqnExceptLast(self):
+        fqn = "apple.pear.foo"
+        assert fqn_rcdr(fqn) == "apple.pear"
+        
+    def test_rdrReturnsEmptyStringForOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_rcdr(fqn) == ""
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_visitor.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+from __future__ import generators
+import setpath
+import unittest
+import visitor
+from bike.testutils import *
+
+class TestVisitor(BRMTestCase):
+    def test_callsVistorFunctions(self):
+        tree = createTree()
+
+        class TreeVisitor:
+            def __init__(self):
+                self.txt = []
+
+            def visitAClass(self,node):
+                self.txt.append("visitAClass")
+                self.txt.append(node.txt)
+                return self.visitChildren(node)
+                
+            def visitCClass(self,node):
+                self.txt.append("visitCClass")
+                self.txt.append(node.txt)
+
+            def getTxt(self):
+                return ",".join(self.txt)
+        
+        self.assertEqual(visitor.walk(tree,TreeVisitor()).getTxt(),
+                         "visitAClass,aclass,visitCClass,cclass0,visitCClass,cclass1,visitCClass,cclass2")
+
+
+    def test_callsVisitorFunctionsWithYield(self):
+        tree = createTree()
+        
+        class TreeVisitor:
+            def __init__(self):
+                self.txt = []
+
+            def visitAClass(self,node):
+                self.txt.append("visitAClass")
+                self.txt.append(node.txt)
+                yield node
+                for i in self.visitChildren(node):
+                    yield i
+                
+            def visitCClass(self,node):
+                self.txt.append("visitCClass")
+                self.txt.append(node.txt)
+                if 0: yield 1
+
+            def getTxt(self):
+                return ",".join(self.txt)
+
+        for node in visitor.walkAndGenerate(tree,TreeVisitor()):
+            assert node.txt == "aclass"
+        
+
+def createTree():
+    n = AClass("aclass")
+    for i in xrange(3):
+        b = n.addChildNode(BClass("bclass%d" % i))
+        for j in xrange(20):
+            b = b.addChildNode(BClass("bclass%d" % i))
+        b.addChildNode(CClass("cclass%d" % i))
+    return n
+
+class node(object):
+    def __init__(self,txt):
+        self._childNodes=[]
+        self.txt = txt
+    
+    def addChildNode(self,node):
+        self._childNodes.append(node)
+        return node
+    
+    def getChildNodes(self):
+        return [x for x in self._childNodes]
+
+
+class AClass(node):
+    pass
+
+class BClass(node):
+    pass
+
+class CClass(node):
+    pass
+
+if __name__ == "__main__":
+
+    # add perf test at end of tests
+    class Z_SoakTestFastparser(BRMTestCase):
+        def test_parsesPythonLibraryCorrectly(self):
+
+            class TreeVisitor:
+                pass
+            
+            import time
+
+            tree = createTree()
+
+            t1 = time.time()
+            for i in xrange(1000):
+                visitor.walk(tree,TreeVisitor())
+            print "tree without yield",time.time()-t1
+
+            t1 = time.time()
+            for i in xrange(1000):
+                for node in visitor.walkAndGenerate(tree,TreeVisitor()):
+                    pass
+            print "tree with yield",time.time()-t1
+
+
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+import setpath
+
+import unittest
+
+#import all the tests
+from test_load import *
+from test_newstuff import *
+from test_parserutils import *
+from test_fastparser import *
+from test_fastparserast import *
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.WARN)
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,30 @@
+# get the first element of a fully qualified python path
+#(e.g. _car('a.b.c.d') = 'a')
+def fqn_car(fqn):
+    try:
+        return fqn[:fqn.index(".")]
+    except ValueError:   # i.e. no dots in fqn
+        return fqn
+
+# get the other elements of a fully qualified python path
+#(e.g. _cdr('a.b.c.d') = 'b.c.d')
+def fqn_cdr(fqn):
+    try:
+        return fqn[fqn.index(".")+1:]
+    except ValueError:   # i.e. no dots in fqn
+        return ""
+
+# reverse of above _rcar("a.b.c.d") = "d"
+def fqn_rcar(fqn):
+    try:
+        return fqn[fqn.rindex(".")+1:]
+    except ValueError:   # i.e. no dots in fqn
+        return fqn
+
+
+# reverse of above _rcdr("a.b.c.d") = "a.b.c"
+def fqn_rcdr(fqn):
+    try:
+        return fqn[:fqn.rindex(".")]
+    except ValueError:   # i.e. no dots in fqn
+        return ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/visitor.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,49 @@
+from __future__ import generators
+
+class TreeWalker(object):
+    VERBOSE = 0
+
+    def __init__(self):
+        self.node = None
+        self._cache = {}
+
+    def default(self, node, *args):
+        for child in node.getChildNodes():
+            self.dispatch(child, *args)
+
+    def dispatch(self, node, *args):
+        self.node = node
+        klass = node.__class__
+        meth = self._cache.get(klass, None)
+        if meth is None:
+            className = klass.__name__
+            meth = getattr(self.visitor, 'visit' + className, self.default)
+            self._cache[klass] = meth
+        return meth(node, *args)
+
+    def preorder(self, tree, visitor, *args):
+        """Do preorder walk of tree using visitor"""
+        self.visitor = visitor
+        visitor.visit = self.dispatch
+        visitor.visitChildren = self.default
+        return self.dispatch(tree, *args)
+
+class GeneratingTreeWalker(TreeWalker):
+
+    def default(self, node, *args):
+        for child in node.getChildNodes():
+            for i in self.dispatch(child, *args):
+                yield i
+
+
+def walk(tree, visitor):
+    walker = TreeWalker()
+    walker.preorder(tree, visitor)
+    return walker.visitor
+    
+
+def walkAndGenerate(tree,visitor):
+    walker = GeneratingTreeWalker()
+    return walker.preorder(tree, visitor)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+#
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/common.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,333 @@
+from __future__ import generators
+from bike.globals import *
+from bike.parsing.fastparserast import getRoot, Function, Class, Module, getModule
+from bike.parsing.parserutils import generateLogicalLines, makeLineParseable, UnbalancedBracesException, generateLogicalLinesAndLineNumbers
+from bike.parsing.newstuff import getSourceNodesContainingRegex
+from bike.parsing import visitor
+from bike import log
+import compiler
+from compiler.ast import Getattr, Name
+import re
+
+class Match:
+    def __repr__(self):
+        return ",".join([self.filename, str(self.lineno), str(self.colno),
+                         str(self.confidence)])
+    def __eq__(self,other):
+        if self is None or other is None:
+            return False
+        return self.filename == other.filename and \
+               self.lineno == other.lineno and \
+               self.colno == other.colno
+
+def getScopeForLine(sourceNode, lineno):
+    scope = None
+    childnodes = sourceNode.getFlattenedListOfFastParserASTNodes()
+    if childnodes == []:
+        return sourceNode.fastparseroot #module node
+
+    scope = sourceNode.fastparseroot
+
+    for node in childnodes:
+        if node.linenum > lineno: break
+        scope = node
+
+    if scope.getStartLine() != scope.getEndLine(): # is inline
+        while scope.getEndLine() <= lineno:
+            scope = scope.getParent()
+    return scope
+
+
+
+# global from the perspective of 'contextFilename'
+def globalScanForMatches(contextFilename, matchFinder, targetname):
+    for sourcenode in getSourceNodesContainingRegex(targetname, contextFilename):
+        print >> log.progress, "Scanning", sourcenode.filename
+        searchscope = sourcenode.fastparseroot
+        for match in scanScopeForMatches(sourcenode,searchscope,
+                                         matchFinder,targetname):
+            yield match
+
+
+def scanScopeForMatches(sourcenode,scope,matchFinder,targetname):
+    lineno = scope.getStartLine()
+    for line in generateLogicalLines(scope.getMaskedLines()):
+        if line.find(targetname) != -1:
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            scope = getScopeForLine(sourcenode, lineno)
+            matchFinder.reset(line)
+            matchFinder.setScope(scope)
+            matches = visitor.walk(ast, matchFinder).getMatches()
+            for index, confidence in matches:
+                match = Match()
+                match.filename = sourcenode.filename
+                match.sourcenode = sourcenode
+                x, y = indexToCoordinates(line, index)
+                match.lineno = lineno+y
+                match.colno = x
+                match.colend = match.colno+len(targetname)
+                match.confidence = confidence
+                yield match
+        lineno+=line.count("\n")
+    
+
+def walkLinesContainingStrings(scope,astWalker,targetnames):
+    lineno = scope.getStartLine()
+    for line in generateLogicalLines(scope.getMaskedLines()):
+        if lineContainsOneOf(line,targetnames):
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            astWalker.lineno = lineno
+            matches = visitor.walk(ast, astWalker)
+        lineno+=line.count("\n")
+
+
+def lineContainsOneOf(line,targetnames):
+    for name in targetnames:
+        if line.find(name) != -1:
+            return True
+    return False
+
+
+# translates an idx in a logical line into physical line coordinates
+# returns x and y coords
+def indexToCoordinates(src, index):
+    y = src[: index].count("\n")
+    startOfLineIdx = src.rfind("\n", 0, index)+1
+    x = index-startOfLineIdx
+    return x, y
+
+
+
+# interface for MatchFinder classes
+# implement the visit methods
+class MatchFinder:
+    def setScope(self, scope):
+        self.scope = scope
+
+    def reset(self, line):
+        self.matches = []
+        self.words = re.split("(\w+)", line) # every other one is a non word
+        self.positions = []
+        i = 0
+        for word in self.words:
+            self.positions.append(i)
+            #if '\n' in word:  # handle newlines
+            #    i = len(word[word.index('\n')+1:])
+            #else:
+            i+=len(word)
+        self.index = 0
+
+    def getMatches(self):
+        return self.matches
+
+    # need to visit childnodes in same order as they appear
+    def visitPrintnl(self,node):
+        if node.dest:
+            self.visit(node.dest)
+        for n in node.nodes:
+            self.visit(n)
+    
+    def visitName(self, node):
+        self.popWordsUpTo(node.name)
+
+    def visitClass(self, node):
+        self.popWordsUpTo(node.name)
+        for base in node.bases:
+            self.visit(base)
+
+    def zipArgs(self, argnames, defaults):
+        """Takes a list of argument names and (possibly a shorter) list of
+        default values and zips them into a list of pairs (argname, default).
+        Defaults are aligned so that the last len(defaults) arguments have
+        them, and the first len(argnames) - len(defaults) pairs have None as a
+        default.
+        """
+        fixed_args = len(argnames) - len(defaults)
+        defaults = [None] * fixed_args + list(defaults)
+        return zip(argnames, defaults)
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def visitGetattr(self,node):
+        self.visit(node.expr)
+        self.popWordsUpTo(node.attrname)
+
+    def visitAssName(self, node):
+        self.popWordsUpTo(node.name)
+
+    def visitAssAttr(self, node):
+        self.visit(node.expr)
+        self.popWordsUpTo(node.attrname)
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+        for name, alias in node.names:
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitLambda(self, node):
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def visitGlobal(self, node):
+        for name in node.names:
+            self.popWordsUpTo(name)
+
+    def popWordsUpTo(self, word):
+        if word == "*":
+            return        # won't be able to find this
+        posInWords = self.words.index(word)
+        idx = self.positions[posInWords]
+        self.words = self.words[posInWords+1:]
+        self.positions = self.positions[posInWords+1:]
+
+    def appendMatch(self,name,confidence=100):
+        idx = self.getNextIndexOfWord(name)
+        self.matches.append((idx, confidence))
+
+    def getNextIndexOfWord(self,name):
+        return self.positions[self.words.index(name)]
+
+class CouldNotLocateNodeException(Exception): pass
+
+def translateSourceCoordsIntoASTNode(filename,lineno,col):
+    module = getModule(filename)
+    maskedlines = module.getMaskedModuleLines()
+    lline,backtrackchars = getLogicalLine(module, lineno)
+    doctoredline = makeLineParseable(lline)
+    ast = compiler.parse(doctoredline)
+    idx = backtrackchars+col
+    nodefinder = ASTNodeFinder(lline,idx)
+    node = compiler.walk(ast, nodefinder).node
+    if node is None:
+        raise CouldNotLocateNodeException("Could not translate editor coordinates into source node")
+    return node
+
+def getLogicalLine(module, lineno):
+    # we know that the scope is the start of a logical line, so
+    # we search from there
+    scope = getScopeForLine(module.getSourceNode(), lineno)
+    linegenerator = \
+            module.generateLinesWithLineNumbers(scope.getStartLine())
+    for lline,llinenum in \
+            generateLogicalLinesAndLineNumbers(linegenerator):
+        if llinenum > lineno:
+            break
+        prevline = lline
+        prevlinenum = llinenum
+
+    backtrackchars = 0
+    for i in range(prevlinenum,lineno):
+        backtrackchars += len(module.getSourceNode().getLines()[i-1])
+    return prevline, backtrackchars
+
+
+
+class ASTNodeFinder(MatchFinder):
+    # line is a masked line of text
+    # lineno and col are coords
+    def __init__(self,line,col):
+        self.line = line
+        self.col = col
+        self.reset(line)
+        self.node = None
+
+    def visitName(self,node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+
+    def visitGetattr(self,node):
+        self.visit(node.expr)
+        if self.checkIfNameMatchesColumn(node.attrname):
+            self.node = node
+        self.popWordsUpTo(node.attrname)
+
+    def visitFunction(self, node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if self.checkIfNameMatchesColumn(arg):
+                self.node = Name(arg)
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+
+    visitAssName = visitName
+    visitAssAttr = visitGetattr
+
+    def visitClass(self, node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+        for base in node.bases:
+            self.visit(base)
+
+
+    def checkIfNameMatchesColumn(self,name):
+        idx = self.getNextIndexOfWord(name)
+        #print "name",name,"idx",idx,"self.col",self.col
+        if idx <= self.col and idx+len(name) > self.col:
+            return 1
+        return 0
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+        for name, alias in node.names:
+            if self.checkIfNameMatchesColumn(name):
+                self.node = self._manufactureASTNodeFromFQN(name)
+                return
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    # gets round the fact that imports etc dont contain nested getattr
+    # nodes for fqns (e.g. import a.b.bah) by converting the fqn
+    # string into a getattr instance
+    def _manufactureASTNodeFromFQN(self,fqn):
+        if "." in fqn:
+            assert 0, "getattr not supported yet"
+        else:
+            return Name(fqn)
+
+def isAMethod(scope,node):
+    return isinstance(node,compiler.ast.Function) and \
+           isinstance(scope,Class)
+
+def convertNodeToMatchObject(node,confidence=100):
+    m = Match()
+    m.sourcenode = node.module.getSourceNode()
+    m.filename = node.filename
+    if isinstance(node,Module):
+        m.lineno = 1
+        m.colno = 0
+    elif isinstance(node,Class) or isinstance(node,Function):
+        m.lineno = node.getStartLine()
+        m.colno = node.getColumnOfName()
+    m.confidence = confidence
+    return m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/findDefinition.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,277 @@
+from __future__ import generators
+from bike.query.common import Match, MatchFinder, \
+     getScopeForLine, indexToCoordinates, \
+     translateSourceCoordsIntoASTNode, scanScopeForMatches, \
+     isAMethod, convertNodeToMatchObject, walkLinesContainingStrings
+from bike.parsing.parserutils import generateLogicalLines,\
+     generateLogicalLinesAndLineNumbers, \
+     splitLogicalLines, makeLineParseable
+import compiler
+from compiler.ast import Getattr, Name, AssName, AssAttr
+from bike.parsing.fastparserast import getRoot, Package, Class, \
+                                       Module, Function, Instance
+import re
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType, \
+     isWordInLine, resolveImportedModuleOrPackage
+from bike.parsing import visitor
+from bike.parsing.visitor import walkAndGenerate
+
+from bike.parsing.parserutils import makeLineParseable,splitLogicalLines
+from bike.parsing.newstuff import getSourceNodesContainingRegex
+from bike.parsing.load import getSourceNode
+from bike import log
+
+
+class CantFindDefinitionException:
+    pass
+
+
+def findAllPossibleDefinitionsByCoords(filepath,lineno,col):
+    
+    #try:
+    node = translateSourceCoordsIntoASTNode(filepath,lineno,col)
+    #except:
+    #    import traceback
+    #    traceback.print_exc()
+
+    if node is None:
+        raise "selected node type not supported"
+    scope = getScopeForLine(getSourceNode(filepath),lineno)
+    match = findDefinitionFromASTNode(scope,node)
+    if match is not None:
+        yield match
+    if isinstance(node,Getattr) and (match is None or match.confidence != 100):
+        root = getRoot()
+        name = node.attrname
+        for match in scanPythonPathForMatchingMethodNames(name,filepath):
+            yield match
+    print >>log.progress,"done"
+
+
+def findDefinitionFromASTNode(scope,node):
+    assert node is not None
+    if isinstance(node,Name) or isinstance(node,AssName):
+        while 1:
+            # try scope children
+            childscope = scope.getChild(node.name)
+            if childscope is not None:
+                return convertNodeToMatchObject(childscope,100)
+
+            if isinstance(scope,Package):
+                scope = scope.getChild("__init__")
+
+            # try arguments and assignments
+            match = scanScopeAST(scope,node.name,
+                                 AssignmentAndFnArgsSearcher(node.name))
+            if match is not None:
+                return match
+            
+            # try imports
+            match = searchImportedModulesForDefinition(scope,node)
+            if match is not None:
+                return match
+
+
+            if not isinstance(scope,Module):
+                # try parent scope
+                scope = scope.getParent()
+            else:
+                break
+        assert isinstance(scope,Module)
+
+    elif isinstance(node,Getattr) or isinstance(node,AssAttr):
+        exprtype = getTypeOfExpr(scope,node.expr)
+        if not (exprtype is None or isinstance(exprtype,UnfoundType)):
+            if isinstance(exprtype,Instance):
+                exprtype = exprtype.getType()
+                match = findDefinitionOfAttributeFromASTNode(exprtype,
+                                                         node.attrname)
+            else:
+                match = findDefinitionFromASTNode(exprtype,
+                                                  Name(node.attrname))
+            if match is not None:
+                return match
+
+    elif isinstance(node,compiler.ast.Function) or \
+             isinstance(node,compiler.ast.Class):
+        if isAMethod(scope,node): 
+            match = findDefinitionOfAttributeFromASTNode(scope,
+                                                        node.name)
+        else:
+            match = findDefinitionFromASTNode(scope,Name(node.name))
+        if match is not None:
+            return match
+
+
+    type = getTypeOfExpr(scope,node)
+    if type is not None and (not isinstance(type,UnfoundType)) and \
+                             (not isinstance(type,Instance)):
+        return  convertNodeToMatchObject(type,100)
+    else:
+        return None
+
+
+def findDefinitionOfAttributeFromASTNode(type,name):
+    assert isinstance(type,Class)
+    attrfinder = AttrbuteDefnFinder([type],name)
+
+    # first scan the method names:
+    for child in type.getChildNodes():
+        if child.name == name:
+            return convertNodeToMatchObject(child,100)
+    # then scan the method source for attribues
+    for child in type.getChildNodes():
+        if isinstance(child,Function):
+            try:
+                return scanScopeForMatches(child.module.getSourceNode(),
+                                        child, attrfinder,
+                                        name).next()
+            except StopIteration:
+                continue
+
+
+class AttrbuteDefnFinder(MatchFinder):
+    def __init__(self,targetClasses,targetAttribute):
+        self.targetClasses = targetClasses
+        self.targetAttributeName = targetAttribute
+
+    def visitAssAttr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+
+        if node.attrname == self.targetAttributeName:
+            exprtype = getTypeOfExpr(self.scope,node.expr)
+            if isinstance(exprtype,Instance) and \
+               exprtype.getType() in self.targetClasses:
+                self.appendMatch(self.targetAttributeName)
+            #else:
+            #    self.appendMatch(self.targetAttributeName,50)
+        self.popWordsUpTo(node.attrname)
+
+
+    
+
+def searchImportedModulesForDefinition(scope,node):
+    lines = scope.module.getSourceNode().getLines()
+    for lineno in scope.getImportLineNumbers():
+        logicalline = getLogicalLine(lines,lineno)
+        logicalline = makeLineParseable(logicalline)
+        ast = compiler.parse(logicalline)
+        class ImportVisitor:
+            def __init__(self,node):
+                self.target = node
+                self.match = None
+                assert isinstance(self.target,Name), \
+                       "Getattr not supported"
+                
+            def visitFrom(self, node):
+                module = resolveImportedModuleOrPackage(scope,node.modname)
+                if module is None: # couldn't find module
+                    return 
+                
+                if node.names[0][0] == '*': # e.g. from foo import *
+                    match = findDefinitionFromASTNode(module,self.target)
+                    if match is not None:
+                        self.match = match
+                    return
+                    
+                for name, alias in node.names:
+                    if alias is None and name == self.target.name:
+                        match = findDefinitionFromASTNode(module,self.target)
+                        if match is not None:
+                            self.match = match
+                        return
+
+
+        match = visitor.walk(ast, ImportVisitor(node)).match
+        if match:
+            return match
+    # loop
+
+
+def getLogicalLine(lines,lineno):
+    return generateLogicalLines(lines[lineno-1:]).next()
+
+class AssignmentAndFnArgsSearcher(MatchFinder):
+    def __init__(self,name):
+        self.targetname = name
+        self.match = None
+
+    def visitAssName(self, node):
+        if node.name == self.targetname:
+            idx = self.getNextIndexOfWord(self.targetname)
+            self.match = idx
+            return 
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if arg == self.targetname:
+                idx = self.getNextIndexOfWord(self.targetname)
+                self.match = idx
+                return
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def getMatch(self):
+        return self.match
+
+
+
+# scans for lines containing keyword, and then runs the visitor over
+# the parsed AST for that line
+def scanScopeAST(scope,keyword,matchfinder):
+    lines = scope.generateLinesNotIncludingThoseBelongingToChildScopes()
+    match = None
+    for line,linenum in generateLogicalLinesAndLineNumbers(lines):
+        if isWordInLine(keyword, line):
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            matchfinder.reset(line)
+            match = visitor.walk(ast,matchfinder).getMatch()
+            if match is not None:
+                column,yoffset = indexToCoordinates(line,match)
+                m = createMatch(scope,linenum + yoffset,column)
+                return m
+    return None
+
+def createMatch(scope,lineno,x):
+    m = Match()
+    m.sourcenode = scope.module.getSourceNode()
+    m.filename = m.sourcenode.filename
+    m.lineno = lineno
+    m.colno = x
+    m.confidence = 100
+    return m
+
+# scan for methods globally (from perspective of 'perspectiveFilename')
+def scanPythonPathForMatchingMethodNames(name, contextFilename):
+    class MethodFinder:
+        def __init__(self,srcnode):
+            self.matches = []
+            self.srcnode = srcnode
+        def visitFunction(self,node):
+            node = getScopeForLine(self.srcnode, self.lineno)
+            if isinstance(node.getParent(),Class):
+                if node.name == name:
+                    self.matches.append(convertNodeToMatchObject(node,50))
+
+    for srcnode in getSourceNodesContainingRegex(name,contextFilename):
+        m = MethodFinder(srcnode)
+        walkLinesContainingStrings(srcnode.fastparseroot,m,[name])
+        for match in m.matches:
+            yield match
+
+
+def getIndexOfWord(line,targetword):
+    words = re.split("(\w+)", line)
+    idx = 0
+    for word in words:
+        if word == targetword:
+            break
+        idx += len(word)
+    return idx
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/findReferences.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,224 @@
+from __future__ import generators
+from bike.globals import *
+from bike.parsing.fastparserast import Module, Class, Function, getRoot, Instance
+from bike.query.common import Match, MatchFinder,\
+     getScopeForLine, indexToCoordinates, \
+     translateSourceCoordsIntoASTNode, scanScopeForMatches,\
+     globalScanForMatches, isAMethod, convertNodeToMatchObject
+from compiler.ast import AssName,Name,Getattr,AssAttr
+import compiler
+from findDefinition import findDefinitionFromASTNode
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
+from bike.query.relationships import getRootClassesOfHierarchy
+from bike import log
+from bike.parsing.load import getSourceNode
+
+
+class CouldntFindDefinitionException(Exception):
+    pass
+
+def findReferencesIncludingDefn(filename,lineno,col):
+    return findReferences(filename,lineno,col,1)
+
+
+def findReferences(filename,lineno,col,includeDefn=0):
+    sourcenode = getSourceNode(filename)
+    node = translateSourceCoordsIntoASTNode(filename,lineno,col)
+    assert node is not None
+    scope,defnmatch = getDefinitionAndScope(sourcenode,lineno,node)
+
+    try:
+        for match in findReferencesIncludingDefn_impl(sourcenode,node,
+                                                      scope,defnmatch):
+            if not includeDefn and match == defnmatch: 
+                continue        # don't return definition
+            else:
+                yield match
+    except CouldntFindDefinitionException:
+        raise CouldntFindDefinitionException("Could not find definition. Please locate manually (maybe using find definition) and find references from that")
+
+def findReferencesIncludingDefn_impl(sourcenode,node,scope,defnmatch):
+    if isinstance(node,Name) or isinstance(node,AssName):
+        return generateRefsToName(node.name,scope,sourcenode,defnmatch)
+    elif isinstance(node,Getattr) or isinstance(node,AssAttr):
+        exprtype = getTypeOfExpr(scope,node.expr)
+        if exprtype is None or isinstance(exprtype,UnfoundType):
+            raise CouldntFindDefinitionException()
+
+        if isinstance(exprtype,Instance):
+            exprtype = exprtype.getType()
+            return generateRefsToAttribute(exprtype,node.attrname)
+        
+        else:
+            targetname = node.attrname
+            return globalScanForMatches(sourcenode.filename,
+                                        NameRefFinder(targetname, defnmatch),
+                                        targetname, )
+        if match is not None:
+            return match
+    elif isinstance(node,compiler.ast.Function) or \
+                             isinstance(node,compiler.ast.Class):
+        return handleClassOrFunctionRefs(scope, node, defnmatch)
+    else:
+        assert 0,"Seed to references must be Name,Getattr,Function or Class"
+
+def handleClassOrFunctionRefs(scope, node, defnmatch):
+    if isAMethod(scope,node):        
+        for ref in generateRefsToAttribute(scope,node.name):
+            yield ref
+    else:
+        #yield convertNodeToMatchObject(node,100)
+        yield defnmatch
+        for ref in generateRefsToName(node.name,scope,
+                                    scope.module.getSourceNode(),
+                                    defnmatch):
+            yield ref
+
+def getDefinitionAndScope(sourcenode,lineno,node):
+    scope = getScopeForLine(sourcenode,lineno)
+    if scope.getStartLine() == lineno and \
+           scope.matchesCompilerNode(node):  # scope is the node
+        return scope.getParent(), convertNodeToMatchObject(scope,100)
+    defnmatch = findDefinitionFromASTNode(scope,node)
+    if defnmatch is None:
+        raise CouldntFindDefinitionException()
+    scope = getScopeForLine(sourcenode,defnmatch.lineno)
+    return scope,defnmatch
+
+def generateRefsToName(name,scope,sourcenode,defnmatch):
+    assert scope is not None
+    if isinstance(scope,Function):
+        # search can be limited to scope
+        return scanScopeForMatches(sourcenode,scope,
+                                   NameRefFinder(name,defnmatch),
+                                   name)
+    else:        
+        return globalScanForMatches(sourcenode.filename,
+                                    NameRefFinder(name,defnmatch),
+                                    name)
+
+
+class NameRefFinder(MatchFinder):
+    def __init__(self, targetstr,targetMatch):
+        self.targetstr = targetstr
+        self.targetMatch = targetMatch
+        
+    def visitName(self, node):
+        if node.name == self.targetstr:
+            potentualMatch = findDefinitionFromASTNode(self.scope, node)
+            if  potentualMatch is not None and \
+                   potentualMatch == self.targetMatch:
+                self.appendMatch(node.name)
+        self.popWordsUpTo(node.name)
+
+    visitAssName = visitName
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if arg == self.targetstr:
+                self.appendMatch(arg)
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+            
+        for name, alias in node.names:
+            if name == self.targetstr:
+                if alias is not None:
+                    pretendNode = Name(alias)
+                else:
+                    pretendNode = Name(name)
+                if findDefinitionFromASTNode(self.scope, pretendNode) \
+                                                    == self.targetMatch:
+                    self.appendMatch(name)
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+
+    def visitGetattr(self, node):        
+        for c in node.getChildNodes():
+            self.visit(c)
+        if node.attrname == self.targetstr:
+            defn = findDefinitionFromASTNode(self.scope, node)
+            if defn is not None and defn == self.targetMatch:
+                self.appendMatch(node.attrname)
+        self.popWordsUpTo(node.attrname)
+
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            if name.split(".")[-1] == self.targetstr:
+                getattr = self.createGetattr(name)
+                if findDefinitionFromASTNode(self.scope, getattr) == self.targetMatch:
+                    self.appendMatch(self.targetstr)
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    
+    def createGetattr(self,fqn):
+        node = Name(fqn[0])
+        for name in fqn.split(".")[1:]:
+            node = Getattr(node,name)
+        return node
+                           
+def generateRefsToAttribute(classobj,attrname):
+    rootClasses = getRootClassesOfHierarchy(classobj)
+    attrRefFinder = AttrbuteRefFinder(rootClasses,attrname)
+    for ref in globalScanForMatches(classobj.filename, attrRefFinder, attrname):
+        yield ref
+    print >>log.progress,"Done"
+    
+
+class AttrbuteRefFinder(MatchFinder):
+    def __init__(self,rootClasses,targetAttribute):
+        self.rootClasses = rootClasses
+        self.targetAttributeName = targetAttribute
+
+    
+    def visitGetattr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+
+        if node.attrname == self.targetAttributeName:
+            exprtype = getTypeOfExpr(self.scope,node.expr)            
+
+            if isinstance(exprtype,Instance) and \
+                 self._isAClassInTheSameHierarchy(exprtype.getType()):
+                self.appendMatch(self.targetAttributeName)
+            elif isinstance(exprtype,UnfoundType) or \
+                 exprtype is None:   # couldn't find type, so not sure
+                self.appendMatch(self.targetAttributeName,50)
+            else:
+                pass # definately not a match
+        self.popWordsUpTo(node.attrname)
+
+    visitAssAttr = visitGetattr
+
+    def visitFunction(self,node):  # visit methods
+        if node.name == self.targetAttributeName:
+            parentScope = self.scope.getParent()
+            #print parentScope
+            #print self.targetClasses
+            if isinstance(parentScope,Class) and \
+                   self._isAClassInTheSameHierarchy(parentScope):
+                self.appendMatch(node.name)
+
+        for c in node.getChildNodes():
+            self.visit(c)
+        
+    def _isAClassInTheSameHierarchy(self,classobj):
+        #return classobj in self.targetClasses
+        targetRootClasses = getRootClassesOfHierarchy(classobj)
+        for rootclass in self.rootClasses:
+            if rootclass in targetRootClasses:
+                return True
+        return False
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getAllRelatedClasses.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,47 @@
+
+
+"""
+
+def getAllRelatedClasses(root,classfqn):
+    classobj = getTypeOf(root,classfqn)
+    rootClasses = _getRootClasses(classobj)
+    #print rootClasses
+    relatedClasses = [] + rootClasses
+    for rootClass in rootClasses:
+        relatedClasses += _getAllSubClasses(rootClass,root)
+    return relatedClasses
+
+def _getRootClasses(klass):
+    if klass is None:  # i.e. dont have base class in our ast
+        return None
+    if klass.getBaseClassNames() == []:  # i.e. is a root class
+        return[klass]
+    else:
+        rootclasses = []
+        for base in klass.getBaseClassNames():
+            baseclass = getTypeOf(klass,base)
+            rootclass = _getRootClasses(baseclass)
+            if rootclass is None:  # base class not in our ast
+                rootclass = [klass]
+            rootclasses+=rootclass
+        return rootclasses
+
+
+def _getAllSubClasses(baseclass, root, subclasses = []):
+    class ClassVisitor:
+        def visitSource(self,node):
+            self.visit(node.fastparseroot)
+            
+        def visitClass(self, node):
+            for basename in node.getBaseClassNames():
+                if basename.find(baseclass.name) != -1 and \
+                       getTypeOf(node,basename) == baseclass:
+                    subclasses.append(node)
+                    _getAllSubClasses(node,root,subclasses)
+            for child in node.getChildNodes():
+                self.visit(child)
+                
+    walk(root, ClassVisitor())
+    return subclasses
+
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getPackageDependencies.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+# fileInPackage is the filename of a file in the package hierarchy
+def getPackageDependencies(fileInPackage):
+    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getReferencesToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,62 @@
+from __future__ import generators
+from bike.query.common import Match, globalScanForMatches, getScopeForLine, MatchFinder
+from getTypeOf import getTypeOf, getTypeOfExpr
+import compiler
+import re
+
+def getReferencesToModule(root, fqn):
+    
+    modulename = fqn.split(".")[-1]
+    moduleobj = getTypeOf(root, fqn)
+    moduleRefFinder = ModuleRefFinder(moduleobj)
+    
+    for ref in globalScanForMatches(moduleRefFinder, modulename):
+        yield ref
+
+        
+class ModuleRefFinder(MatchFinder):
+    def __init__(self, targetmodule):
+        self.targetmodule = targetmodule
+
+    def visitName(self, node):
+        if node.name == self.targetmodule.name:
+            if getTypeOfExpr(self.scope, node) == self.targetmodule:
+                self.appendMatch(node.name)
+        self.popWordsUpTo(node.name)
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            if name.split(".")[-1] == self.targetmodule.name:
+                if getTypeOf(self.scope, name) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitGetattr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+        if node.attrname == self.targetmodule.name:
+            if getTypeOfExpr(self.scope, node) == self.targetmodule:
+                self.appendMatch(self.targetmodule.name)
+        self.popWordsUpTo(node.attrname)
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            if elem == self.targetmodule.name:
+                getTypeOf(self.scope, elem) == self.targetmodule
+                self.appendMatch(self.targetmodule.name)
+            self.popWordsUpTo(elem)
+            
+        for name, alias in node.names:
+            if name == self.targetmodule.name:
+                if alias and \
+                   getTypeOf(self.scope, alias) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+                elif getTypeOf(self.scope, name) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+            if name != "*":
+                self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getTypeOf.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,377 @@
+# getTypeOf(scope,fqn) and getTypeOfExpr(scope,ast)
+
+from bike.parsing.fastparserast import Class, Function, Module, Root, getRoot, Package, Instance, getModule
+from bike.parsing.parserutils import generateLogicalLines, makeLineParseable,splitLogicalLines, makeLineParseable
+from bike.parsing import visitor
+from bike import log
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from bike.parsing.pathutils import getPackageBaseDirectory
+from bike.parsing.load import Cache
+import os
+import re
+import compiler
+
+# used if an assignment exists, but cant find type
+# e.g. a = SomeFunctionNotLoaded()
+# (as opposed to 'None' if cant find an assignment)
+class UnfoundType: pass
+
+
+getTypeOfStack = []
+
+# name is the fqn of the reference, scope is the scope ast object from
+# which the question is being asked.
+# returns an fastparser-ast object representing the type
+# or None if type not found
+def getTypeOf(scope, fqn):
+    if isinstance(scope, Root):
+        assert False, "Can't use getTypeOf to resolve from Root. Use getModuleOrPackageUsingFQN instead"
+
+
+    #print "getTypeOf:"+fqn+" -- "+str(scope)
+    #print 
+    #print str(getTypeOfStack)
+    #print 
+    if (fqn,scope) in getTypeOfStack:   # loop protection
+        return None
+
+    # this is crap!
+    hashcode = str(scope)+fqn
+
+    try:
+        getTypeOfStack.append((fqn,scope))
+
+        try:
+            type = Cache.instance.typecache[hashcode]
+        except KeyError:
+            type = getTypeOf_impl(scope, fqn)
+            Cache.instance.typecache[hashcode] = type
+        return type
+    finally:
+        del getTypeOfStack[-1]
+        
+
+
+def getTypeOf_impl(scope, fqn):
+    #print "getTypeOf_impl",scope,fqn
+    if fqn == "None":
+        return None
+
+    if "."in fqn:
+        rcdr = ".".join(fqn.split(".")[:-1])
+        rcar = fqn.split(".")[-1]
+        newscope = getTypeOf(scope,rcdr)
+        if newscope is not None:
+            return getTypeOf(newscope, rcar)
+        else: 
+            #print "couldnt find "+rcdr+" in "+str(scope)
+            pass
+
+    assert scope is not None
+    #assert not ("." in fqn) 
+    
+    if isinstance(scope,UnfoundType):
+        return UnfoundType()
+    
+    if isinstance(scope, Package):
+        #assert 0,scope
+        return handlePackageScope(scope, fqn)
+    elif isinstance(scope,Instance):
+        return handleClassInstanceAttribute(scope, fqn)
+    else:
+        return handleModuleClassOrFunctionScope(scope,fqn)
+
+
+
+def handleModuleClassOrFunctionScope(scope,name):
+    if name == "self" and isinstance(scope,Function) and \
+           isinstance(scope.getParent(),Class):
+        return Instance(scope.getParent())
+    
+    matches = [c for c in scope.getChildNodes()if c.name == name]
+    if matches != []:
+        return matches[0]
+    
+    type = scanScopeSourceForType(scope, name)
+    if type != None:
+        return type
+    
+    #print "name = ",name,"scope = ",scope
+    type = getImportedType(scope, name)   # try imported types
+    #print "type=",type
+    if type != None:
+        return type
+    parentScope = scope.getParent()
+    while isinstance(parentScope,Class):
+        # don't search class scope, since this is not accessible except
+        # through self   (is this true?)
+        parentScope = parentScope.getParent()
+
+    if not (isinstance(parentScope,Package) or isinstance(parentScope,Root)):
+        return getTypeOf(parentScope, name)
+
+
+def handleClassInstanceAttribute(instance, attrname):
+    theClass = instance.getType()
+
+    # search methods and inner classes
+    match = theClass.getChild(attrname)
+    if match:
+        return match
+
+    #search methods for assignments with self.foo getattrs
+    for child in theClass.getChildNodes():
+        if not isinstance(child,Function):
+            continue
+        res = scanScopeAST(child,attrname,
+                          SelfAttributeAssignmentVisitor(child,attrname))
+        if res is not None:
+            return res
+
+def handlePackageScope(package, fqn):
+    #print "handlePackageScope",package,fqn
+    child = package.getChild(fqn)
+    if child:
+        return child
+
+    if isinstance(package,Root):
+        return getModuleOrPackageUsingFQN(fqn)
+
+    # try searching the fs
+    node = getModuleOrPackageUsingFQN(fqn,package.path)
+    if node:
+        return node
+    
+    
+
+
+    # try the package init module
+    initmod = package.getChild("__init__")
+    if initmod is not None:
+        type = getImportedType(initmod, fqn)
+        if type:
+            return type
+    # maybe fqn is absolute
+    return getTypeOf(getRoot(), fqn)
+
+
+wordRE = re.compile("\w+")
+def isWordInLine(word, line):
+    if line.find(word) != -1:
+        words = wordRE.findall(line)
+        if word in words:
+            return 1
+    return 0
+
+def getImportedType(scope, fqn):
+    lines = scope.module.getSourceNode().getLines()
+    for lineno in scope.getImportLineNumbers():
+        logicalline = generateLogicalLines(lines[lineno-1:]).next()
+        logicalline = makeLineParseable(logicalline)
+        ast = compiler.parse(logicalline)
+        match = visitor.walk(ast, ImportVisitor(scope,fqn)).match
+        if match:
+            return match
+        #else loop
+
+class ImportVisitor:
+    def __init__(self,scope,fqn):
+        self.match = None
+        self.targetfqn = fqn
+        self.scope = scope
+
+    def visitImport(self, node):
+        # if target fqn is an import, then it must be a module or package
+        for name, alias in node.names:
+            if name == self.targetfqn:
+                self.match = resolveImportedModuleOrPackage(self.scope,name)
+            elif alias is not None and alias == self.targetfqn:
+                self.match = resolveImportedModuleOrPackage(self.scope,name)
+
+    def visitFrom(self, node):
+        if node.names[0][0] == '*': # e.g. from foo import *
+            if not "."in self.targetfqn:
+                module = resolveImportedModuleOrPackage(self.scope,
+                                                        node.modname)
+                if module:
+                    self.match = getTypeOf(module, self.targetfqn)
+        else:
+            for name, alias in node.names:
+                if alias == self.targetfqn or \
+                   (alias is None and name == self.targetfqn):
+                    scope = resolveImportedModuleOrPackage(self.scope,
+                                                            node.modname)
+                    if scope is not None:
+                        if isinstance(scope,Package):
+                            self.match = getModuleOrPackageUsingFQN(name,scope.path)
+                        else:  
+                            assert isinstance(scope,Module)
+                            self.match = getTypeOf(scope, name)
+
+
+
+
+class TypeNotSupportedException:
+    def __init__(self,msg):
+        self.msg = msg
+
+    def __str__(self):
+        return self.msg
+
+# attempts to evaluate the type of the expression
+def getTypeOfExpr(scope, ast):
+    if isinstance(ast, compiler.ast.Name):
+        return getTypeOf(scope, ast.name)
+
+    elif isinstance(ast, compiler.ast.Getattr) or \
+             isinstance(ast, compiler.ast.AssAttr):
+
+        # need to do this in order to match foo.bah.baz as
+        # a string in import statements
+        fqn = attemptToConvertGetattrToFqn(ast)
+        if fqn is not None:
+            return getTypeOf(scope,fqn)
+
+        expr = getTypeOfExpr(scope, ast.expr)
+        if expr is not None:
+            attrnametype = getTypeOf(expr, ast.attrname)
+            return attrnametype
+        return None
+
+    elif isinstance(ast, compiler.ast.CallFunc):
+        node = getTypeOfExpr(scope,ast.node)
+        if isinstance(node,Class):
+            return Instance(node)
+        elif isinstance(node,Function):
+            return getReturnTypeOfFunction(node)
+    else:
+        #raise TypeNotSupportedException, \
+        #      "Evaluation of "+str(ast)+" not supported. scope="+str(scope)
+        print >> log.warning, "Evaluation of "+str(ast)+" not supported. scope="+str(scope)
+        return None
+
+
+def attemptToConvertGetattrToFqn(ast):
+    fqn = ast.attrname
+    ast = ast.expr
+    while isinstance(ast,compiler.ast.Getattr):
+        fqn = ast.attrname + "." + fqn
+        ast = ast.expr
+    if isinstance(ast,compiler.ast.Name):
+        return ast.name + "." + fqn
+    else:
+        return None
+
+
+getReturnTypeOfFunction_stack = []
+def getReturnTypeOfFunction(function):
+    if function in getReturnTypeOfFunction_stack:   # loop protection
+        return None
+    try:
+        getReturnTypeOfFunction_stack.append(function)
+        return getReturnTypeOfFunction_impl(function)
+    finally:
+        del getReturnTypeOfFunction_stack[-1]
+
+def getReturnTypeOfFunction_impl(function):
+    return scanScopeAST(function,"return",ReturnTypeVisitor(function))
+    
+
+# does parse of scope sourcecode to deduce type
+def scanScopeSourceForType(scope, name):
+    return scanScopeAST(scope,name,AssignmentVisitor(scope,name))
+
+
+# scans for lines containing keyword, and then runs the visitor over
+# the parsed AST for that line
+def scanScopeAST(scope,keyword,astvisitor):
+    lines = scope.getLinesNotIncludingThoseBelongingToChildScopes()
+    src = ''.join(lines)
+    match = None
+    #print "scanScopeAST:"+str(scope)
+    for line in splitLogicalLines(src):
+        if isWordInLine(keyword, line):
+            #print "scanning for "+keyword+" in line:"+line[:-1]
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            match = visitor.walk(ast,astvisitor).getMatch()
+            if match:
+                return match
+    return match
+    
+
+class AssignmentVisitor:
+    def __init__(self,scope,targetName):
+        self.match=None
+        self.scope = scope
+        self.targetName = targetName
+
+    def getMatch(self):
+        return self.match
+
+    def visitAssign(self,node):
+        if isinstance(node.expr,compiler.ast.CallFunc):
+            for assnode in node.nodes:
+                if isinstance(assnode,compiler.ast.AssName) and \
+                   assnode.name == self.targetName:
+                    self.match = getTypeOfExpr(self.scope,node.expr)
+                    if self.match is None:
+                        self.match = UnfoundType()
+                    
+                    
+
+class SelfAttributeAssignmentVisitor:
+    def __init__(self,scope,targetName):
+        self.match=None
+        self.scope = scope
+        self.targetName = targetName
+
+    def getMatch(self):
+        return self.match
+
+    def visitAssign(self,node):
+        if isinstance(node.expr,compiler.ast.CallFunc):
+            for assnode in node.nodes:
+                if isinstance(assnode,compiler.ast.AssAttr) and \
+                   isinstance(assnode.expr,compiler.ast.Name) and \
+                   assnode.expr.name == "self" and \
+                   assnode.attrname == self.targetName:
+                    self.match = getTypeOfExpr(self.scope,node.expr)
+                    #print "here!",self.match.getType().fqn
+
+
+class ReturnTypeVisitor:
+    def __init__(self,fn):
+        self.match=None
+        self.fn = fn
+
+    def getMatch(self):
+        return self.match
+    
+    def visitReturn(self,node):
+        try:
+            self.match = getTypeOfExpr(self.fn,node.value)
+        except TypeNotSupportedException, ex:
+            pass
+
+
+def resolveImportedModuleOrPackage(scope,fqn):
+    # try searching from directory containing scope module
+    path = os.path.dirname(scope.module.filename)
+    node = getModuleOrPackageUsingFQN(fqn,path)
+    if node is not None:
+        return node
+
+    # try searching in same package hierarchy
+    basedir = getPackageBaseDirectory(scope.module.filename)
+    if fqn.split('.')[0] == os.path.split(basedir)[-1]:
+        # base package in fqn matches base directory
+        restOfFqn = ".".join(fqn.split('.')[1:])
+        node = getModuleOrPackageUsingFQN(restOfFqn,basedir)
+    if node is not None:
+        return node
+
+    # try searching the python path
+    node = getModuleOrPackageUsingFQN(fqn)
+    if node is not None:
+        return node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/relationships.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,26 @@
+# queries to do with module/class/function relationships
+from __future__ import generators
+from bike.globals import *
+from getTypeOf import getTypeOf, getTypeOfExpr
+from bike.parsing.newstuff import generateModuleFilenamesInPythonPath, generateModuleFilenamesInPackage, getPythonPath
+from bike.parsing.pathutils import getPackageBaseDirectory
+from bike.query.common import MatchFinder, walkLinesContainingStrings, getScopeForLine
+from bike import log
+from bike.parsing.fastparserast import Module
+import re
+
+def getRootClassesOfHierarchy(klass):
+    if klass is None:  # i.e. dont have base class in our ast
+        return None
+    if klass.getBaseClassNames() == []:  # i.e. is a root class
+        return [klass]
+    else:
+        rootclasses = []
+        for base in klass.getBaseClassNames():
+            baseclass = getTypeOf(klass,base)
+            rootclass = getRootClassesOfHierarchy(baseclass)
+            if rootclass is None:  # base class not in our ast
+                rootclass = [klass]
+            rootclasses+=rootclass
+        return rootclasses
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath(".."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_common.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+import compiler
+from bike.testutils import *
+from bike.parsing.load import getSourceNode
+from bike.parsing.fastparser import fastparser
+from bike.parsing.fastparserast import Module, Class
+from common import indexToCoordinates, getScopeForLine, walkLinesContainingStrings, translateSourceCoordsIntoASTNode
+
+
+class TestGetScopeForLine(BRMTestCase):
+
+    def test_worksWithFunctionScope(self):
+        src = trimLines("""
+        class a:
+            def foo():
+                pass
+        """)
+        node = createAST(src)
+        self.assertEqual(getScopeForLine(node,3).name,"foo")
+
+    def test_worksWithModuleScope(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        node = createAST(src)
+        assert isinstance(getScopeForLine(node,3),Module)
+
+    def test_worksWithInlineClass(self):
+        src = trimLines("""
+        class TheClass: pass""")
+        node = createAST(src)
+        assert isinstance(getScopeForLine(node,1),Class)
+
+
+class TestIndexToCoordinates(BRMTestCase):
+
+    def test_worksOnSingleLineString(self):
+        src = trimLines('''
+        foo bah
+        ''')
+        x,y = indexToCoordinates(src,src.index("bah"))
+        self.assertEqual(x,4)
+        self.assertEqual(y,0)
+        x,y = indexToCoordinates(src,src.index("foo"))
+        self.assertEqual(x,0)
+        self.assertEqual(y,0)
+
+    def test_worksOnMultilLineString(self):
+        src = trimLines('''
+        foo bah
+        baz boh
+        ''')
+        x,y = indexToCoordinates(src,src.index("boh"))
+        self.assertEqual(x,4)
+        self.assertEqual(y,1)
+
+
+class TestTranslateSourceCoordsIntoASTNode(BRMTestCase):
+
+    def test_worksOnImport(self):
+        src = trimLines('''
+        from foo import bar, baz
+        ''')
+        createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        node = translateSourceCoordsIntoASTNode(filename, 1, 17)
+        assert node.name == 'bar'
+
+    def test_worksOnMultiline(self):
+        src = trimLines("""
+        def foo(x,
+                y,
+                z):
+            return x*y*z
+        """)
+        createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        node = translateSourceCoordsIntoASTNode(filename, 3, 8)
+        assert node.name == 'z'
+
+        
+
+
+class TestMatchFinder(BRMTestCase):
+
+    def test_visitLambda(self):
+        from common import MatchFinder
+        finder = MatchFinder()
+        src = '''x = lambda a, b, c=None, d=None: (a + b) and c or d'''
+        ast = compiler.parse(src)
+        finder.reset(src)
+        compiler.walk(ast, finder)
+
+
+class TestWalkLinesContainingStrings(BRMTestCase):
+    def test_walksClasses(self):
+        src=trimLines("""
+        class TestClass(a,
+                        baseclass):
+            pass
+        """)
+        class MyWalker:            
+            def visitClass(self, node):
+                self.basenames = []
+                for name in node.bases:
+                    self.basenames.append(name.name)
+        
+        writeTmpTestFile(src)
+        srcnode = getSourceNode(tmpfile)
+        walker = MyWalker()
+        walkLinesContainingStrings(srcnode.fastparseroot,walker,
+                                   "baseclass")
+        self.assertEqual(["a","baseclass"],walker.basenames)
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_findDefinition.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,632 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+
+from bike import testdata
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.query.getTypeOf import getTypeOf,resolveImportedModuleOrPackage
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from bike.parsing.fastparserast import getRoot
+from bike.testutils import *
+        
+class TestFindDefinitionByCoords(BRMTestCase):
+
+    def test_findsClassRef(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,6)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def tests_findsMethodRef(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),5,3)]
+
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+        
+
+    def test_returnsOtherMethodsWithSameName(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = SomeOtherClass()
+        a.theMethod()
+        """)
+
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),5,3)]
+
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 50
+
+
+
+
+    def test_findsTemporaryDefinition(self):
+        src=trimLines("""
+        a = 3
+        b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),2,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsArgumentDefinition(self):
+        src=trimLines("""
+        def someFunction(a):
+            b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),2,8)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 17
+        assert defn[0].confidence == 100
+
+    def test_findsClassInstanceDefinition(self):
+        src=trimLines("""
+        class TheClass():
+            pass
+        a = TheClass()
+        print a
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,6)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionInParentScope(self):
+        src=trimLines("""
+        a = 3
+        def foo(self):
+            b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,8)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionWithinFunction(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = someFunction()
+            print a
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,10)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+        
+
+    def test_findsDefinitionFromSubsequentAssignment(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = 3
+            print a
+            a = 5
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionFromDefinition(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = 3
+            print a
+            a = 5
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+
+
+    def test_findsClassRefUsingFromImportStatement(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(classsrc, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,1,21)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingImportStatement(self):
+        importsrc=trimLines("""
+        import a.b.bah
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,14)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStarStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import *
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        createSourceNodeAt(importsrc,"a.foo")
+        createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsVariableRefUsingFromPackageImportModuleStatement(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        print bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,10)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsImportedVariableRefInAFunctionArg(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,17)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStatementInFunction(self):
+        importsrc=trimLines("""
+        def foo:
+            from a.b.bah import mytext
+            print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,3,10)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsVariableRefByImportingModule(self):
+        importsrc=trimLines("""
+        import a.b.bah
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        defn = self.helper(importsrc, src, 2, 14)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefByImportingModuleWithFrom(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+
+        defn = self.helper(importsrc, src, 2, 17)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            #Root(None,None,[pkgstructureRootDir])
+            defn = [x for x in findAllPossibleDefinitionsByCoords(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return defn
+
+    def test_doesntfindVariableRefOfUnimportedModule(self):
+        importsrc=trimLines("""
+        # a.b.bah not imported
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,14)]
+        self.assertEqual(defn,[])
+
+
+
+    def test_findsSelfAttributeDefinition(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,5,18)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 12
+        assert defn[0].confidence == 100
+
+    def test_findsSelfAttributeDefinitionFromSamePlace(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,3,12)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 12
+        assert defn[0].confidence == 100
+
+
+    def test_findsSelfAttributeDefinition(self):
+        src=trimLines("""
+        class MyClass:
+            def someOtherFn(self):
+                pass
+            def load(self, source):
+                # fastparser ast
+                self.fastparseroot = fastparser(source,self.modulename)
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,6,14)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 6
+        assert defn[0].colno == 13
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefnOfInnerClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,4,14)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 10
+        assert defn[0].confidence == 100
+
+    def test_findsDefnOfOuterClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsClassDeclaredIn__init__Module(self):
+        importsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        src=trimLines("""
+        from a import TheClass
+        c = TheClass()
+        """)
+
+
+
+        root = createSourceNodeAt(importsrc,"a.__init__")
+        root = createSourceNodeAt(src, "mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a",
+                                                                "__init__.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+class TestFindDefinitionUsingFiles(BRMTestCase):
+    def test_findsASimpleDefinitionUsingFiles(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        writeTmpTestFile(src)
+        defn = [x for x in findAllPossibleDefinitionsByCoords(tmpfile,3,6)]
+        assert defn[0].filename == tmpfile
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefinitionInAnotherModuleUsingFiles(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        defn = self.helper(src, classsrc, 1, 21)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+
+    def test_findsDefinitionInAnotherRelativeModuleUsingFiles(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        defn = self.helper(src, classsrc,1,21)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def test_findsMethodDefinitionInAnotherModuleUsingFiles(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        defn = self.helper(src, classsrc, 3, 2)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitonOfMethodWhenUseIsOnAMultiLine(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        i,j = (32,
+               a.theMethod())  # <--- find me!
+        something=somethingelse
+        """)
+        defn = self.helper(src, classsrc, 4, 9)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefinitionWhenUseIsOnAMultilineAndNextLineBalancesBrace(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        c = TheClass()
+        f1, f2 = (c.func1, 
+                c.theMethod)
+        f1, f2 = (c.func1, 
+                c.theMethod)
+        """)
+        defn = self.helper(src, classsrc, 4, 10)
+        self.assertEqual(pkgstructureFile2,defn[0].filename)
+        self.assertEqual(2,defn[0].lineno)
+        self.assertEqual(8,defn[0].colno)
+        self.assertEqual(100,defn[0].confidence)
+
+    def test_worksIfFindingDefnOfRefInSlashMultiline(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        c = TheClass()
+        f1, f2 = c.func1 \\
+               ,c.theMethod
+        """)
+        defn = self.helper(src, classsrc, 4, 10)
+        self.assertEqual(pkgstructureFile2,defn[0].filename)
+        self.assertEqual(2,defn[0].lineno)
+        self.assertEqual(8,defn[0].colno)
+        self.assertEqual(100,defn[0].confidence)
+
+    def test_findsDefnInSameNonPackageDirectory(self):
+        try:
+            getRoot().pythonpath = []   # clear the python path
+            classsrc = trimLines("""
+            def testFunction():
+                print 'hello'
+            """)
+            src = trimLines("""
+            from baz import testFunction
+            """)
+            writeTmpTestFile(src)
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, classsrc)
+            refs = [x for x in findAllPossibleDefinitionsByCoords(tmpfile,1,16)]
+            assert refs[0].filename == newtmpfile
+            assert refs[0].lineno == 1
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+
+
+    def test_findsDefnInPackageSubDirectoryAndRootNotInPath(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        getRoot().pythonpath = []   # clear the python path
+        defn = self.helper(src, classsrc, 1, 18)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def test_findsDefnInSamePackageHierarchyAndRootNotInPath(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        getRoot().pythonpath = []   # clear the python path
+        defn = self.helper(src, classsrc, 1, 20)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            #Root(None,None,[pkgstructureRootDir])
+            defn = [x for x in findAllPossibleDefinitionsByCoords(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return defn
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_findReferences.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,516 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+#from bike.testutils import trimLines, createSourceNodeAt, \
+#     createSourceNodeAt_old, BRMTestCase
+from bike import testdata
+from findReferences import findReferences, findReferencesIncludingDefn
+from bike.query.getTypeOf import getTypeOf
+
+class helpers:
+    def helper(self,src,lineno,colno):
+        writeTmpTestFile(src)
+        refs =  [x for x in findReferences(tmpfile,lineno,colno)]
+        return refs
+
+    def helper2(self,src,lineno,colno):
+        writeTmpTestFile(src)
+        refs =  [x for x in findReferencesIncludingDefn(tmpfile,lineno,
+                                                           colno)]
+        return refs
+        
+    def helper3(self, src, importedsrc, line, col):
+        createPackageStructure(src,importedsrc)
+        filename = pkgstructureFile2
+        refs =  [x for x in findReferences(filename,line,col)
+                 if x.confidence == 100]
+        return refs
+
+    def helper4(self, src, importedsrc, line, col):
+        createPackageStructure(src,importedsrc)
+        filename = pkgstructureFile1
+        refs =  [x for x in findReferences(filename,line,col)
+                 if x.confidence == 100]
+        return refs
+
+    
+
+class TestFindReferences(BRMTestCase,helpers):
+    def test_findsSimpleReferencesGivenAssignment(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        refs = self.helper(src,3,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+
+
+
+    def test_findsSimpleReferencesGivenReference(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+
+        refs = self.helper2(src,3,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 4
+        assert refs[0].confidence == 100
+
+
+    def test_findsReferencesToOtherAssignments(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            a = 4
+        """)
+        refs = self.helper(src,2,4)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 4
+        assert refs[0].confidence == 100
+
+    def test_findsFunctionArg(self):
+        src=trimLines("""
+        def foo(a):
+            print a
+        """)
+        refs = self.helper2(src,2,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 8
+        assert refs[0].confidence == 100
+
+    def test_findsFunctionArgWithDefault(self):
+        src=trimLines("""
+        def foo(a=None, b=None):
+            print a, b
+        """)
+        refs = self.helper(src,1,4)
+        self.assertEquals(refs, [])
+
+    def test_findsFunctionArgWithDefault2(self):
+        src=trimLines("""
+        def foo(a=None, b=None):
+            print a, b
+        """)
+        refs = self.helper2(src,2,13)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 16
+        assert refs[0].confidence == 100
+
+
+    def test_findsReferencesGivenFunctionArg(self):
+        src=trimLines("""
+        def foo(a):
+            print a
+        """)
+        refs = self.helper(src,1,8)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+
+
+    def test_findsVariableRefInImportStatementUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 20
+        assert refs[0].confidence == 100
+
+
+
+    def test_findsVariableRefUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[1].lineno == 2
+        assert refs[1].colno == 6
+        assert refs[1].confidence == 100
+
+    def test_findsImportedVariableRefInAFunctionArg(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 17
+        assert refs[0].confidence == 100
+
+    def test_getsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        refs = self.helper4(src,testdata.TheClass,3,2)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+
+
+    def test_findsRefToSelfAttribute(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        refs = self.helper(src,3,12)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 5
+        assert refs[0].colno == 18
+        assert refs[0].confidence == 100
+
+
+class FindReferencesToMethod(BRMTestCase,helpers):
+    def test_findsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallFromClassImportedWithAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceOfMethodCallWhenInstanceReturnedByFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            return TheClass()
+        a = foo()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,6)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallInSameClass(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+        refs = self.helper4(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,13)
+
+    def test_getsReferenceOfMethodOnBaseClassInstance(self):
+        src = trimLines("""
+        class root:
+            def theMethod(self):
+                pass
+                
+        class a(root):
+            def theMethod(self):
+                pass
+                
+        class b(root):
+            pass
+            
+        class TheClass(b):
+            def theMethod(self):
+                pass
+                
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[2].filename,pkgstructureFile1)
+        self.assertEqual(refs[2].lineno,17)
+        self.assertEqual(refs[2].colno,13)
+        
+    def test_doesntGetReferenceToMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs == []
+        
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,10)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceInMiddleOfBiggerCompoundCall(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,11)
+        self.assertEqual(refs[0].colend,20)
+
+    def test_doesntBarfWhenObjectIsArrayMember(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a[0] = TheClass()
+        a[0].theMethod()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        # should get to here without exception
+
+class FindReferencesToClass(BRMTestCase, helpers):
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        assert refs == []
+
+
+    def test_findsSimpleReferenceInSameModule(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_doesntBarfOnSingleLineSourceWithInlineClass(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        """)
+        refs = self.helper3(src,"class TheClass: pass",1,6)
+        assert refs != []
+
+    def test_findsReferenceToClassImportedInSameClassScope(self):
+        src=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        refs = self.helper3(src,"class TheClass: pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,22)
+
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,4)
+
+    def testFindsClassReferenceWhenScopeIsSameNameAsClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        refs = self.helper4(src,"pass",2,10)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,13)
+        self.assertEqual(refs[0].confidence,100)
+
+    def testFindsClassReferenceWhenChildIsSameNameAsClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+
+class TestFindReferencesIncludingDefn(BRMTestCase,helpers):
+    def test_findsMethodDecl(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        refs = self.helper2(src,2,8)
+        self.assertEqual(refs[0].filename,tmpfile)
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,8)
+        self.assertEqual(refs[0].confidence,100)
+
+
+
+class TestFindReferencesUsingFiles(BRMTestCase):
+    def test_findsSimpleReferencesUsingFiles(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        refs = self.helper("pass",src,2,4)
+        assert refs[0].filename == pkgstructureFile2
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+        
+    def test_findsReferenceInModuleWhichImportsClassWithFromAndAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+        """)
+        refs = self.helper(src,testClass,1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_doesntBarfWhenCantLocatePackageWhenTryingToFindBaseClass(self):
+        src = trimLines("""
+        from doesntexist import baseclass
+        class foo(baseclass):
+            def myMethod(self):
+                pass
+        """)
+        refs = self.helper("",src,3,8)
+
+    def test_doesntBarfWhenComesAcrossAPrintNl(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+
+        print >>foo, TheClass
+        """)
+        refs = self.helper("",src,1,6)
+
+
+    def test_returnsOtherFilesInSameNonPackageDirectory(self):
+        try:
+            getRoot().pythonpath = []   # clear the python path
+            classsrc = trimLines("""
+            def testFunction():
+                print 'hello'
+            """)
+            src = trimLines("""
+            from baz import testFunction
+            """)
+            writeTmpTestFile(src)
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, classsrc)
+            refs = [x for x in findReferences(newtmpfile,1,4)]
+
+            assert refs[0].filename == tmpfile
+            assert refs[0].lineno == 1
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+
+
+
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile2
+            refs = [x for x in findReferences(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return refs
+
+
+
+
+testClass = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getPackageDependencies.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+
+class TestGetPackageDependencies(BRMTestCase):
+    def test_foo(self):
+        assert 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToClass.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,280 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.findReferences import findReferences
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToClass(BRMTestCase):
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        refs = [x for x in findReferences(os.path.abspath("mymodule.py"),1,6)]
+        self.assertEqual(refs,[])
+
+    def test_findsSimpleReferenceInSameModule(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        refs = [x for x in findReferences(os.path.abspath("mymodule.py"),1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath("mymodule.py"))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferencesInModuleWhichImportsClass(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        refs = [x for x in findReferences(os.path.abspath("a/b/bah.py"),1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsReferenceInModuleWhichImportsClassWithFrom(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a/foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,8)
+        self.assertEqual(refs[1].confidence,100)
+
+    def test_findsReferenceToClassImportedInSameClassScope(self):
+        src=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        assert refs != []
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromAndAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsReferenceInModuleWhichImportsClassWithImportAs(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar(self):
+        src = trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar2(self):
+        src = trimLines("""
+        from a.b.bah import *
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsClassReferenceInInstanceCreation(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        root = createSourceNodeAt(src, "a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,0)
+        self.assertEqual(refs[0].confidence,100)
+
+    
+    def test_findsClassReferenceInInstanceCreationWithFQN(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_doesntfindReferenceInModuleWhichDoesntImportClass(self):
+        src = trimLines("""
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        assert refs == []
+
+    def test_findsReferenceInClassBases(self):
+        src =trimLines("""
+        from b.bah import TheClass
+        class DerivedClass(TheClass):
+            pass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,2)
+        self.assertEqual(refs[1].colno,19)
+        self.assertEqual(refs[1].confidence,100)
+        
+
+    
+    def test_findsReferenceInMultiLineImportStatement(self):
+        src =trimLines("""
+        from b.bah import foo, \\
+                  TheFooBah, TheClass, Foobah, SomethingElse
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,21)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceWhenModulenameSameAsClassMethodName(self):
+        # asserts that brm doesnt search class scope after not finding name
+        # in method scope (since class scope is invisible unless called on 'self'
+        src =trimLines("""
+        from a.b import bah
+        class baz:
+            def bah(self):
+                print bah.TheClass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_doesntBarfOnFromImportStarWhenNameIsInFromClause(self):
+        src = trimLines("""
+        from a.b.bah import TheClass
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+
+ClassTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.findReferences import findReferences
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToMethod(BRMTestCase):
+
+    def test_getsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallFromClassImportedWithAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceOfMethodCallWhenInstanceReturnedByFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            return TheClass()
+        a = foo()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,6)
+        self.assertEqual(refs[0].colno,2)
+        
+    def test_getsReferenceOfMethodCallInSameClass(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,13)
+
+    def test_getsReferenceOfMethodOnBaseClassInstance(self):
+        src = trimLines("""
+        class root:
+            def theMethod():
+                pass
+                
+        class a(root):
+            def theMethod():
+                pass
+                
+        class b(root):
+            pass
+            
+        class TheClass(b):
+            def theMethod(self):
+                pass
+                
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+
+        refs =self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[2].filename,pkgstructureFile1)
+        self.assertEqual(refs[2].lineno,17)
+        self.assertEqual(refs[2].colno,13)
+
+    def helper4(self, src, importedsrc, line, col):
+        try:
+            createPackageStructure(src,importedsrc)
+            filename = pkgstructureFile1
+            refs =  [x for x in findReferences(filename,line,col)
+                     if x.confidence == 100]
+        finally:
+            removePackageStructure()
+        return refs
+        
+    def test_doesntGetReferenceToMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        assert len(refs) == 0
+        
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,10)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceInMiddleOfBiggerCompoundCall(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,11)
+        self.assertEqual(refs[0].colend,20)
+
+
+MethodTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getReferencesToModule import *
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToModule(BRMTestCase):
+    
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        self.assertEqual([x for x in getReferencesToModule(root,"myothermodule")],[])
+
+    def test_findsReferencesInModuleWhichImportsModule(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,9)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,10)
+        self.assertEqual(refs[0].confidence,100)
+        
+    def test_findsReferenceInModuleWhichImportsModuleWithFrom(self):
+        src = trimLines("""
+        from b import bah
+        def foo():
+            a = bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a/foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,8)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsModuleWithFromAndAlias(self):
+        src = trimLines("""
+        from b import bah as mymodule
+        def foo():
+            a = mymodule.MyTheClass()
+            a.theMethod()
+        """)
+
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+        """ # mymodule.MyTheClass
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,10)
+        self.assertEqual(refs[1].confidence,100)
+        """
+
+    def test_findsReferenceInModuleWhichImportsModuleWithFromImportStar(self):
+        src = trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,7)
+        self.assertEqual(refs[0].confidence,100)
+
+    ''' Dont think this is a valid test, since cant import a module with
+        from package import *
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar2(self):
+        src = trimLines("""
+        from a.b import * 
+        a = bah.TheClass()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+    '''
+    
+    def test_findsReferenceInClassBases(self):
+        src =trimLines("""
+        from b import bah
+        class DerivedClass(bah.TheClass):
+            pass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,2)
+        self.assertEqual(refs[1].colno,19)
+        self.assertEqual(refs[1].confidence,100)
+            
+    def test_findsReferenceInMultiLineImportStatement(self):
+        src =trimLines("""
+        from b import foo, \\
+                  TheFooBah, TheClass, TheBastard, SomethingElse, bah
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,58)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceWhenModulenameSameAsClassMethodName(self):
+        # asserts that brm doesnt search class scope after not finding name
+        # in method scope (since class scope is invisible unless called on 'self'
+        src =trimLines("""
+        from a.b import bah
+        class baz:
+            def bah(self):
+                print bah.TheClass
+        """)        
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,16)
+        self.assertEqual(refs[0].confidence,100)
+        
+        assert (len(refs))==2
+
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getTypeOf.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getTypeOf import getTypeOf, UnfoundType,\
+     attemptToConvertGetattrToFqn
+from bike.parsing.fastparserast import Class, Function, Instance
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from compiler.ast import Getattr,CallFunc,Name
+
+class TestGetTypeOf(BRMTestCase):
+    def test_getsTypeOfSimpleClassInstanceReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfImportedClassReference(self):
+        src = trimLines("""
+        import b.bah
+        a = b.bah.TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfClassReferenceFromImportedPackage(self):
+        src = trimLines("""
+        import b
+        a = b.bah.TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfInstanceThatIsAnAttributeOfSelf(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        module = getModuleOrPackageUsingFQN('a.foo')
+        theclass = getTypeOf(module,"TheClass")
+        fn = getTypeOf(module,"AnotherClass.anotherFn")
+        self.assertEqual(getTypeOf(fn,"self.a").getType().name, "TheClass")
+        #self.assertEqual(getTypeOf(fn,"self.a").getType(), theclass)
+        
+        
+
+    def test_doesntGetTypeDefinedInChildFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        assert isinstance(getTypeOf(themodule,"a"),UnfoundType)
+    
+
+    def test_getsTypeOfClassReferencedViaAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as FooBah
+        FooBah()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        self.assertEqual(getTypeOf(themodule,"FooBah").name,"TheClass")
+        self.assertEqual(getTypeOf(themodule,"FooBah").filename,
+                         os.path.abspath(os.path.join("a","b","bah.py")))
+        
+
+    def test_getsTypeOfClassImportedFromPackageScope(self):
+        initfile = trimLines("""
+        from bah import TheClass
+        """)
+        src = trimLines("""
+        from a import b
+        b.TheClass()
+        """)
+        createSourceNodeAt(src,"a.foo")
+        createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        createSourceNodeAt(initfile,"a.b.__init__")
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        self.assertEqual(getTypeOf(themodule,"b.TheClass").name,"TheClass")
+        self.assertEqual(getTypeOf(themodule,"b.TheClass").filename,
+                         os.path.abspath(os.path.join("a","b","bah.py")))
+
+
+    def test_attemptToConvertGetattrToFqn_returnsNoneIfFails(self):
+        ast = Getattr(CallFunc(Name("foo"),[],[],[]),"hello")
+        assert attemptToConvertGetattrToFqn(ast) is None
+
+    def test_attemptToConvertGetattrToFqn_works(self):
+        ast = Getattr(Getattr(Name("foo"),"bah"),"hello")
+        assert attemptToConvertGetattrToFqn(ast) == "foo.bah.hello"
+
+    
+    def test_handlesRecursionProblem(self):
+        src = trimLines("""
+        def fn(root):
+            node = root
+            node = node.getPackage('something')
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        m = getModuleOrPackageUsingFQN("a.foo")
+        fn = getTypeOf(m,"fn")
+        getTypeOf(fn,"node")   # stack overflow!
+
+
+    def test_doesntGotIntoRecursiveLoopWhenEvaluatingARecursiveFunction(self):
+        src = trimLines("""
+        def fn(v):
+            if v < 45:
+                return fn(root+1)
+        val = fn(3)
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        mod = getModuleOrPackageUsingFQN("a.foo")
+        getTypeOf(mod,"val")   # stack overflow!
+
+    def test_getsModuleImportedWithFrom(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)        
+        type = self.helper(importsrc,src,'bah')
+        self.assertEqual(pkgstructureFile2,type.filename)
+
+    def helper(self,importsrc,src,name):
+        try:
+            createPackageStructure(importsrc,src)
+            from bike.parsing.newstuff import getModule
+            scope = getModule(pkgstructureFile1)
+            return getTypeOf(scope,name)
+        finally:
+            removePackageStructure()
+    
+
+    def test_getsTypeOfClassImportedAsAlias(self):
+        importsrc = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        type = self.helper(importsrc,src,'MyTheClass')
+        self.assertEqual("TheClass",type.name)
+
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_relationships.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getTypeOf import getTypeOf
+from bike.parsing.fastparserast import Module
+from bike.query.relationships import getRootClassesOfHierarchy
+from bike.parsing.newstuff import getModule
+
+
+class TestGetRootClassesOfHierarchy(BRMTestCase):
+    def test_getsRootClassFromDerivedClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        """)
+        rootclasses = self.helper(src,"DerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual(len(rootclasses),1)        
+        
+    def test_getsRootClassFromDerivedDerivedClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual(len(rootclasses),1)
+
+
+    def test_getsRootClassFromDiamondOfClasses(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+
+    def test_getsRootClassesFromMultipleInheritance(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass:
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("DerivedClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+    def test_getsRootClassesFromMultipleInheritanceWithNewStyleClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(Object):
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("DerivedClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+
+    def helper(self,src,classname):
+        try:
+            createPackageStructure(src,testdata.TheClass)
+            classobj = getTypeOf(getModule(pkgstructureFile1),classname)
+            return getRootClassesOfHierarchy(classobj)
+        finally:
+            removePackageStructure()
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import setpath
+
+from test_common import *
+from test_getReferencesToClass import *
+from test_getReferencesToMethod import *
+#from test_getReferencesToModule import *
+from test_findDefinition import *
+from test_findReferences import *
+from test_relationships import *
+from test_getTypeOf import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/extractMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,363 @@
+import re
+import compiler
+from bike.parsing import visitor
+from bike.query.common import getScopeForLine
+from bike.parsing.parserutils import generateLogicalLines, \
+                makeLineParseable, maskStringsAndRemoveComments
+from parser import ParserError
+from bike.parsing.fastparserast import Class
+from bike.transformer.undo import getUndoStack
+from bike.refactor.utils import getTabWidthOfLine, getLineSeperator, \
+                reverseCoordsIfWrongWayRound
+from bike.transformer.save import queueFileToSave
+from bike.parsing.load import getSourceNode
+TABSIZE = 4
+
+class coords:
+    def __init__(self, line, column):
+        self.column = column
+        self.line = line
+    def __str__(self):
+        return "("+str(self.column)+","+str(self.line)+")"
+
+commentRE = re.compile(r"#.*?$")
+
+class ParserException(Exception): pass
+
+def extractMethod(filename, startcoords, endcoords, newname):
+    ExtractMethod(getSourceNode(filename),
+                  startcoords, endcoords, newname).execute()
+
+class ExtractMethod(object):
+    def __init__(self,sourcenode, startcoords, endcoords, newname):
+        self.sourcenode = sourcenode
+
+        startcoords, endcoords = \
+               reverseCoordsIfWrongWayRound(startcoords,endcoords)
+
+        self.startline = startcoords.line
+        self.endline = endcoords.line
+        self.startcol = startcoords.column
+        self.endcol= endcoords.column
+
+        self.newfn = NewFunction(newname)
+
+        self.getLineSeperator()
+        self.adjustStartColumnIfLessThanTabwidth()
+        self.adjustEndColumnIfStartsANewLine()
+        self.fn = self.getFunctionObject()
+        self.getRegionToBuffer()
+        #print "-"*80
+        #print self.extractedLines
+        #print "-"*80
+        self.deduceIfIsMethodOrFunction()
+
+    def execute(self):
+        self.deduceArguments()
+        getUndoStack().addSource(self.sourcenode.filename,
+                                 self.sourcenode.getSource())
+        srclines = self.sourcenode.getLines()
+        newFnInsertPosition = self.fn.getEndLine()-1
+        self.insertNewFunctionIntoSrcLines(srclines, self.newfn,
+                                           newFnInsertPosition)
+        self.writeCallToNewFunction(srclines)
+
+        src = "".join(srclines)
+        queueFileToSave(self.sourcenode.filename,src)        
+
+    def getLineSeperator(self):
+        line = self.sourcenode.getLines()[self.startline-1]
+        linesep = getLineSeperator(line)
+        self.linesep = linesep        
+
+    def adjustStartColumnIfLessThanTabwidth(self):
+        tabwidth = getTabWidthOfLine(self.sourcenode.getLines()[self.startline-1])
+        if self.startcol < tabwidth: self.startcol = tabwidth
+
+    def adjustEndColumnIfStartsANewLine(self):
+        if self.endcol == 0:
+            self.endline -=1
+            nlSize = len(self.linesep)
+            self.endcol = len(self.sourcenode.getLines()[self.endline-1])-nlSize
+
+
+    def getFunctionObject(self):
+        return getScopeForLine(self.sourcenode,self.startline)
+
+
+    def getTabwidthOfParentFunction(self):
+        line = self.sourcenode.getLines()[self.fn.getStartLine()-1]
+        match = re.match("\s+",line)
+        if match is None:
+            return 0
+        else:
+            return match.end(0)
+
+    # should be in the transformer module
+    def insertNewFunctionIntoSrcLines(self,srclines,newfn,insertpos):
+        tabwidth = self.getTabwidthOfParentFunction()
+
+        while re.match("\s*"+self.linesep,srclines[insertpos-1]):
+            insertpos -= 1
+
+        srclines.insert(insertpos, self.linesep)
+        insertpos +=1
+
+        fndefn = "def "+newfn.name+"("
+
+        if self.isAMethod:
+            fndefn += "self"
+            if newfn.args != []:
+                fndefn += ", "+", ".join(newfn.args)
+        else:
+            fndefn += ", ".join(newfn.args)
+
+        fndefn += "):"+self.linesep
+
+
+        srclines.insert(insertpos,tabwidth*" "+fndefn)
+        insertpos +=1
+
+        tabwidth += TABSIZE
+
+
+        if self.extractedCodeIsAnExpression(srclines):
+            assert len(self.extractedLines) == 1
+
+            fnbody = [tabwidth*" "+ "return "+self.extractedLines[0]]
+
+
+        else:
+            fnbody = [tabwidth*" "+line for line in self.extractedLines]
+            if newfn.retvals != []:
+                fnbody.append(tabwidth*" "+"return "+
+                             ", ".join(newfn.retvals) + self.linesep)
+
+        for line in fnbody:
+            srclines.insert(insertpos,line)
+            insertpos +=1
+
+
+    def writeCallToNewFunction(self, srclines):
+        startline = self.startline
+        endline = self.endline
+        startcol = self.startcol
+        endcol= self.endcol
+
+        fncall = self.constructFunctionCallString(self.newfn.name, self.newfn.args,
+                                                  self.newfn.retvals)
+
+        self.replaceCodeWithFunctionCall(srclines, fncall,
+                                         startline, endline, startcol, endcol)
+
+
+    def replaceCodeWithFunctionCall(self, srclines, fncall,
+                                    startline, endline, startcol, endcol):
+        if startline == endline:  # i.e. extracted code part of existing line
+            line = srclines[startline-1]
+            srclines[startline-1] = self.replaceSectionOfLineWithFunctionCall(line,
+                                                         startcol, endcol, fncall)
+        else:
+            self.replaceLinesWithFunctionCall(srclines, startline, endline, fncall)
+
+
+    def replaceLinesWithFunctionCall(self, srclines, startline, endline, fncall):
+        tabwidth = getTabWidthOfLine(srclines[startline-1])
+        line = tabwidth*" " + fncall + self.linesep
+        srclines[startline-1:endline] = [line]
+
+
+
+    def replaceSectionOfLineWithFunctionCall(self, line, startcol, endcol, fncall):
+        line = line[:startcol] + fncall + line[endcol:]
+        if not line.endswith(self.linesep):
+            line+=self.linesep
+        return line
+
+
+
+    def constructFunctionCallString(self, fnname, fnargs, retvals):
+        fncall = fnname + "("+", ".join(fnargs)+")"
+        if self.isAMethod:
+            fncall = "self." + fncall
+
+        if retvals != []:
+            fncall = ", ".join(retvals) + " = "+fncall
+        return fncall
+
+
+    def deduceArguments(self):
+        lines = self.fn.getLinesNotIncludingThoseBelongingToChildScopes()
+
+        # strip off comments
+        lines = [commentRE.sub(self.linesep,line) for line in lines]
+        extractedLines = maskStringsAndRemoveComments("".join(self.extractedLines)).splitlines(1)
+
+        linesbefore = lines[:(self.startline - self.fn.getStartLine())]
+        linesafter = lines[(self.endline - self.fn.getStartLine()) + 1:]
+
+        # split into logical lines
+        linesbefore = [line for line in generateLogicalLines(linesbefore)]        
+        extractedLines = [line for line in generateLogicalLines(extractedLines)]
+        linesafter = [line for line in generateLogicalLines(linesafter)]
+
+        if self.startline == self.endline:
+            # need to include the line code is extracted from
+            line = generateLogicalLines(lines[self.startline - self.fn.getStartLine():]).next()
+            linesbefore.append(line[:self.startcol] + "dummyFn()" + line[self.endcol:])
+        assigns = getAssignments(linesbefore)
+        fnargs = getFunctionArgs(linesbefore)
+        candidateArgs = assigns + fnargs            
+        refs = getVariableReferencesInLines(extractedLines)
+        self.newfn.args = [ref for ref in refs if ref in candidateArgs]
+
+        assignsInExtractedBlock = getAssignments(extractedLines)
+        usesAfterNewFunctionCall = getVariableReferencesInLines(linesafter)
+        usesInPreceedingLoop = getVariableReferencesInLines(
+            self.getPreceedingLinesInLoop(linesbefore,line))
+        self.newfn.retvals = [ref for ref in usesInPreceedingLoop+usesAfterNewFunctionCall
+                                   if ref in assignsInExtractedBlock]
+
+    def getPreceedingLinesInLoop(self,linesbefore,firstLineToExtract):
+        if linesbefore == []: return []
+        tabwidth = getTabWidthOfLine(firstLineToExtract)
+        rootTabwidth = getTabWidthOfLine(linesbefore[0])
+        llines = [line for line in generateLogicalLines(linesbefore)]
+        startpos = len(llines)-1
+        loopTabwidth = tabwidth
+        for idx in range(startpos,0,-1):
+            line = llines[idx]
+            if re.match("(\s+)for",line) is not None or \
+               re.match("(\s+)while",line) is not None:
+                candidateLoopTabwidth = getTabWidthOfLine(line)
+                if candidateLoopTabwidth < loopTabwidth:
+                    startpos = idx
+        return llines[startpos:]
+
+    
+
+
+
+
+    def getRegionToBuffer(self):
+        startline = self.startline
+        endline = self.endline
+        startcol = self.startcol
+        endcol= self.endcol
+
+
+        self.extractedLines = self.sourcenode.getLines()[startline-1:endline]
+
+        match = re.match("\s*",self.extractedLines[0])
+        tabwidth = match.end(0)
+
+        self.extractedLines = [line[startcol:] for line in self.extractedLines]
+
+        # above cropping can take a blank line's newline off.
+        # this puts it back
+        for idx in range(len(self.extractedLines)):
+            if self.extractedLines[idx] == '':
+                self.extractedLines[idx] = self.linesep
+
+        if startline == endline:
+            # need to crop the end
+            # (n.b. if region is multiple lines, then whole lines are taken)
+            self.extractedLines[-1] = self.extractedLines[-1][:endcol-startcol]
+
+        if self.extractedLines[-1][-1] != '\n':
+            self.extractedLines[-1] += self.linesep
+
+    def extractedCodeIsAnExpression(self,lines):
+        if len(self.extractedLines) == 1:
+            charsBeforeSelection = lines[self.startline-1][:self.startcol]
+            if re.match("^\s*$",charsBeforeSelection) is not None:
+                return 0
+            if re.search(":\s*$",charsBeforeSelection) is not None:
+                return 0
+            return 1
+        return 0
+
+    def deduceIfIsMethodOrFunction(self):
+        if isinstance(self.fn.getParent(),Class):
+            self.isAMethod = 1
+        else:
+            self.isAMethod = 0
+
+
+# holds information about the new function
+class NewFunction:
+    def __init__(self,name):
+        self.name = name
+
+
+# lines = list of lines.
+# Have to have strings masked and comments removed
+def getAssignments(lines):
+    class AssignVisitor:
+        def __init__(self):
+            self.assigns = []
+
+        def visitAssTuple(self, node):
+            for a in node.nodes:
+                if a.name not in self.assigns:
+                    self.assigns.append(a.name)
+
+        def visitAssName(self, node):
+            if node.name not in self.assigns:
+                self.assigns.append(node.name)
+
+        def visitAugAssign(self, node):
+            if isinstance(node.node, compiler.ast.Name):
+                if node.node.name not in self.assigns:
+                    self.assigns.append(node.node.name)
+
+    assignfinder = AssignVisitor()
+    for line in lines:
+        doctoredline = makeLineParseable(line)
+        try:
+            ast = compiler.parse(doctoredline)
+        except ParserError:
+            raise ParserException("couldnt parse:"+doctoredline)
+        visitor.walk(ast, assignfinder)
+    return assignfinder.assigns
+
+
+# lines = list of lines.
+# Have to have strings masked and comments removed
+def getFunctionArgs(lines):
+    if lines == []: return []
+
+    class FunctionVisitor:
+        def __init__(self):
+            self.result = []
+        def visitFunction(self, node):
+            for n in node.argnames:
+                if n != "self":
+                    self.result.append(n)
+    fndef = generateLogicalLines(lines).next()
+    doctoredline = makeLineParseable(fndef)
+    try:
+        ast = compiler.parse(doctoredline)
+    except ParserError:
+        raise ParserException("couldnt parse:"+doctoredline)
+    return visitor.walk(ast, FunctionVisitor()).result
+
+
+
+# lines = list of lines. Have to have strings masked and comments removed
+def getVariableReferencesInLines(lines):
+    class NameVisitor:
+        def __init__(self):
+            self.result = []
+        def visitName(self, node):
+            if node.name not in self.result:
+                self.result.append(node.name)
+    reffinder = NameVisitor()
+    for line in lines:
+        doctoredline = makeLineParseable(line)
+        try:
+            ast = compiler.parse(doctoredline)
+        except ParserError:
+            raise ParserException("couldnt parse:"+doctoredline)
+        visitor.walk(ast, reffinder)
+    return reffinder.result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/extractVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,32 @@
+from bike.parsing.parserutils import maskStringsAndRemoveComments
+from bike.transformer.undo import getUndoStack
+from parser import ParserError
+import compiler
+from bike.refactor.extractMethod import coords
+from bike.refactor.utils import getTabWidthOfLine, getLineSeperator,\
+     reverseCoordsIfWrongWayRound
+from bike.transformer.save import queueFileToSave
+from bike.parsing.load import getSourceNode
+
+
+def extractLocalVariable(filename, startcoords, endcoords, varname):
+    sourceobj = getSourceNode(filename)
+    if startcoords.line != endcoords.line:
+        raise "Can't do multi-line extracts yet"
+    startcoords, endcoords = \
+                 reverseCoordsIfWrongWayRound(startcoords,endcoords)
+    line = sourceobj.getLine(startcoords.line)
+    tabwidth = getTabWidthOfLine(line)
+    linesep = getLineSeperator(line)
+    region = line[startcoords.column:endcoords.column]
+    
+    getUndoStack().addSource(sourceobj.filename,sourceobj.getSource())
+    sourceobj.getLines()[startcoords.line-1] = \
+          line[:startcoords.column] + varname + line[endcoords.column:]
+
+    defnline = tabwidth*" " + varname + " = " + region + linesep
+    
+    sourceobj.getLines().insert(startcoords.line-1,defnline)
+
+    queueFileToSave(sourceobj.filename,"".join(sourceobj.getLines()))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/inlineVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.query.findReferences import findReferences
+from bike.parsing.parserutils import maskStringsAndRemoveComments, linecontinueRE
+from bike.transformer.undo import getUndoStack
+from bike.transformer.save import queueFileToSave
+from parser import ParserError
+from bike.parsing.load import getSourceNode
+import compiler
+import re
+
+
+def inlineLocalVariable(filename, lineno,col):
+    sourceobj = getSourceNode(filename)
+    return inlineLocalVariable_old(sourceobj, lineno,col)
+
+def inlineLocalVariable_old(sourcenode,lineno,col):
+    definition, region, regionlinecount = getLocalVariableInfo(sourcenode, lineno, col)
+    addUndo(sourcenode)
+    replaceReferences(sourcenode, findReferences(sourcenode.filename, definition.lineno, definition.colno), region)
+    delLines(sourcenode, definition.lineno-1, regionlinecount)
+    updateSource(sourcenode)
+
+def getLocalVariableInfo(sourcenode, lineno, col):
+    definition = findDefinition(sourcenode, lineno, col)
+    region, linecount = getRegionToInline(sourcenode, definition)
+    return definition, region, linecount
+
+def findDefinition(sourcenode, lineno, col):
+    definition = findAllPossibleDefinitionsByCoords(sourcenode.filename,
+                                                    lineno,col).next()
+    assert definition.confidence == 100    
+    return definition
+
+def getRegionToInline(sourcenode, defn):
+    line, linecount = getLineAndContinues(sourcenode, defn.lineno)
+    start, end = findRegionToInline(maskStringsAndRemoveComments(line))
+    return line[start:end], linecount
+
+def findRegionToInline(maskedline):
+    match = re.compile("[^=]+=\s*(.+)$\n", re.DOTALL).match(maskedline)
+    assert match
+    return match.start(1), match.end(1)
+
+# Possible refactoring: move to class of sourcenode
+def getLineAndContinues(sourcenode, lineno):
+    line = sourcenode.getLine(lineno)
+    
+    linecount = 1
+    while linecontinueRE.search(line):
+        line += sourcenode.getLine(lineno + linecount)
+        linecount += 1
+
+    return line, linecount
+
+def addUndo(sourcenode):
+    getUndoStack().addSource(sourcenode.filename,sourcenode.getSource())
+
+def replaceReferences(sourcenode, references, replacement):
+    for reference in safeReplaceOrder( references ):
+        replaceReference(sourcenode, reference, replacement)
+
+def safeReplaceOrder( references ):
+    """ 
+    When inlining a variable, if multiple instances occur on the line, then the
+    last reference must be replaced first. Otherwise the remaining intra-line
+    references will be incorrect.
+    """
+    def safeReplaceOrderCmp(self, other):
+        return -cmp(self.colno, other.colno)
+
+    result = list(references)
+    result.sort(safeReplaceOrderCmp)
+    return result
+
+
+def replaceReference(sourcenode, ref, replacement):
+    """ sourcenode.getLines()[ref.lineno-1][ref.colno:ref.colend] = replacement
+    But strings don't support slice assignment as they are immutable. :(
+    """
+    sourcenode.getLines()[ref.lineno-1] = \
+        replaceSubStr(sourcenode.getLines()[ref.lineno-1],
+            ref.colno, ref.colend, replacement)
+
+def replaceSubStr(str, start, end, replacement):
+    return str[:start] + replacement + str[end:]
+
+# Possible refactoring: move to class of sourcenode
+def delLines(sourcenode, lineno, linecount=1):
+    del sourcenode.getLines()[lineno:lineno+linecount]
+    
+def updateSource(sourcenode):
+    queueFileToSave(sourcenode.filename,"".join(sourcenode.getLines()))
+    
+                    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/moveToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,148 @@
+import bike.globals
+from bike.parsing.load import getSourceNode
+from bike.parsing.fastparserast import Module
+from bike.query.common import getScopeForLine, convertNodeToMatchObject
+from bike.transformer.save import queueFileToSave, save
+from bike.transformer.undo import getUndoStack
+from bike.refactor.extractMethod import getVariableReferencesInLines
+from bike.refactor.utils import getLineSeperator
+from bike.query.findDefinition import findDefinitionFromASTNode
+from bike.query.findReferences import findReferences
+from bike.parsing.pathutils import filenameToModulePath
+from compiler.ast import Name
+import re
+
+def moveClassToNewModule(origfile,line,newfile):
+    srcnode = getSourceNode(origfile)
+    targetsrcnode = getSourceNode(newfile)
+    classnode = getScopeForLine(srcnode,line)
+    classlines = srcnode.getLines()[classnode.getStartLine()-1:
+                                    classnode.getEndLine()-1]
+    getUndoStack().addSource(srcnode.filename,
+                             srcnode.getSource())
+    getUndoStack().addSource(targetsrcnode.filename,
+                             targetsrcnode.getSource())
+
+    srcnode.getLines()[classnode.getStartLine()-1:
+                       classnode.getEndLine()-1] = []
+    
+    targetsrcnode.getLines().extend(classlines)
+
+    queueFileToSave(srcnode.filename,srcnode.getSource())
+    queueFileToSave(targetsrcnode.filename,targetsrcnode.getSource())
+
+
+exactFromRE = "(from\s+\S+\s+import\s+%s)(.*)"    
+fromRE = "from\s+\S+\s+import\s+(.*)"
+
+def moveFunctionToNewModule(origfile,line,newfile):
+    
+    srcnode = getSourceNode(origfile)
+    targetsrcnode = getSourceNode(newfile)
+    scope = getScopeForLine(srcnode,line)
+
+    linesep = getLineSeperator(srcnode.getLines()[0])
+
+    matches =[m for m in findReferences(origfile, line, scope.getColumnOfName())]
+
+    origFileImport = []
+    fromline = 'from %s import %s'%(filenameToModulePath(newfile),scope.name)
+    
+    for match in matches:
+        if match.filename == origfile:
+            origFileImport = fromline + linesep
+        else:
+            s = getSourceNode(match.filename)
+            m = s.fastparseroot
+            if match.lineno in m.getImportLineNumbers():                
+                getUndoStack().addSource(s.filename,
+                                         s.getSource())
+
+                maskedline = m.getLogicalLine(match.lineno)
+                origline = s.getLines()[match.lineno-1]
+                reMatch =  re.match(exactFromRE%(scope.name),maskedline)
+                if reMatch and not (',' in reMatch.group(2) or \
+                                    '\\' in reMatch.group(2)):
+                    # i.e. line is 'from module import foo'
+
+                    if match.filename == newfile:
+                        #remove the import
+                        s.getLines()[match.lineno-1:match.lineno] = []
+                        pass
+                    else:
+                        restOfOrigLine = origline[len(reMatch.group(1)):]
+                        s.getLines()[match.lineno-1] = fromline + restOfOrigLine
+
+                elif re.match(fromRE,maskedline):
+                    # i.e. line is 'from module import foo,bah,baz'
+                    #remove the element from the import stmt
+                    line = removeNameFromMultipleImportLine(scope.name, origline)
+                    s.getLines()[match.lineno-1] = line
+                    #and add a new line
+                    nextline = match.lineno + maskedline.count('\\') + 1
+                    s.getLines()[nextline-1:nextline-1] = [fromline+linesep]
+                    
+                queueFileToSave(s.filename,s.getSource())
+                    
+    
+    refs = getVariableReferencesInLines(scope.getMaskedLines())
+
+    scopeLines = srcnode.getLines()[scope.getStartLine()-1:
+                                    scope.getEndLine()-1]
+    importModules = deduceImportsForNewFile(refs, scope)
+    importlines = composeNewFileImportLines(importModules, linesep)
+
+
+
+    getUndoStack().addSource(srcnode.filename,
+                             srcnode.getSource())
+    getUndoStack().addSource(targetsrcnode.filename,
+                             targetsrcnode.getSource())
+
+    srcnode.getLines()[scope.getStartLine()-1:
+                       scope.getEndLine()-1] = origFileImport
+
+    targetsrcnode.getLines().extend(importlines+scopeLines)
+
+    queueFileToSave(srcnode.filename,srcnode.getSource())
+    queueFileToSave(targetsrcnode.filename,targetsrcnode.getSource())
+
+def removeNameFromMultipleImportLine(name, origline):
+    def replacefn(match):
+        return match.group(1)
+    line = re.sub('(\W)%s\s*?,'%(name),replacefn,origline)
+    return line
+
+
+
+
+def composeNewFileImportLines(importModules, linesep):
+    importlines = []
+    for mpath in importModules:
+        importlines += "from %s import %s"%(mpath,
+                                  ', '.join(importModules[mpath]))
+        importlines += linesep
+    return importlines
+
+def deduceImportsForNewFile(refs, scope):
+    importModules = {}
+    for ref in refs:
+        match = findDefinitionFromASTNode(scope,Name(ref))
+
+        if match.filename == scope.module.filename:
+            tgtscope = getScopeForLine(getSourceNode(match.filename),
+                                       match.lineno)
+            while tgtscope != scope and not isinstance(tgtscope,Module):
+                tgtscope = tgtscope.getParent()
+            
+            if not isinstance(tgtscope,Module):
+                continue   # was defined in this function
+        
+        mpath = filenameToModulePath(match.filename)            
+        if mpath in importModules:            
+            importModules[mpath].append(ref)
+        else:
+            importModules[mpath] = [ref]
+    return importModules
+    
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/rename.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,19 @@
+from bike.transformer.WordRewriter import WordRewriter
+from bike.query.findReferences import findReferencesIncludingDefn
+from bike.transformer.save import save
+
+def rename(filename,lineno,col,newname,promptcallback=None):
+    strrewrite = WordRewriter()
+    for match in findReferencesIncludingDefn(filename,lineno,col):
+        #print "rename match ",match
+        if match.confidence == 100 or promptUser(promptcallback,match):
+            strrewrite.rewriteString(match.sourcenode,
+                                     match.lineno,match.colno,newname)
+    strrewrite.commit()
+
+def promptUser(promptCallback,match):
+    if promptCallback is not None and \
+       promptCallback(match.filename, match.lineno, match.colno, match.colend):
+        return 1
+    return 0
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("../..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath("../.."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_extractMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,791 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+
+from bike.refactor.extractMethod import ExtractMethod, \
+     extractMethod, coords
+from bike import testdata
+from bike.testutils import *
+from bike.parsing.load import Cache
+
+def assertTokensAreSame(t1begin, t1end, tokens):
+    it = t1begin.clone()
+    pos = 0
+    while it != t1end:
+        assert it.deref() == tokens[pos]
+        it.incr()
+        pos+=1
+    assert pos == len(tokens)
+
+
+def helper(src,startcoords, endcoords, newname):
+    sourcenode = createAST(src)
+    extractMethod(tmpfile, startcoords, endcoords, newname)
+    return sourcenode.getSource()
+
+class TestExtractMethod(BRMTestCase):
+
+    def test_extractsPass(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(3, 8), coords(3, 12), "newMethod")
+        self.assertEqual(src,srcAfter)
+
+    def test_extractsPassWhenFunctionAllOnOneLine(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): pass # comment
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): self.newMethod() # comment
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(2, 24), coords(2, 28),"newMethod")
+        self.assertEqual(src,srcAfter)
+
+    def test_extractsPassFromForLoop(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+        """)                
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(4, 12), coords(4, 16), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasArgumentsForUsedTemporarys(self):
+
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self, c): 
+                a = something()
+                b = somethingelse()
+                print a + b + c + d
+                print \"hello\"
+                dosomethingelse(a, b)
+        """)                
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self, c): 
+                a = something()
+                b = somethingelse()
+                self.newMethod(a, b, c)
+                dosomethingelse(a, b)
+
+            def newMethod(self, a, b, c):
+                print a + b + c + d
+                print \"hello\"
+        """)
+
+        src = helper(srcBefore, coords(5, 8), coords(6, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasSingleArgument(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a = something()
+                print a
+                print \"hello\"
+                dosomethingelse(a, b)
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a = something()
+                self.newMethod(a)
+                dosomethingelse(a, b)
+
+            def newMethod(self, a):
+                print a
+                print \"hello\"
+        """)
+        src = helper(srcBefore, coords(4, 8), coords(5, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntHaveDuplicateArguments(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 3
+                print a
+                print a
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 3
+                self.newMethod(a)
+
+            def newMethod(self, a):
+                print a
+                print a
+        """)
+        src = helper(srcBefore, coords(4, 0), coords(6, 0), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractsQueryWhenFunctionAllOnOneLine(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self, a): print a # comment
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self, a): self.newMethod(a) # comment
+
+            def newMethod(self, a):
+                print a
+        """)
+        src = helper(srcBefore, coords(2, 27), coords(2, 34), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_worksWhenAssignmentsToTuples(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a, b, c = 35, 36, 37
+                print a + b
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a, b, c = 35, 36, 37
+                self.newMethod(a, b)
+
+            def newMethod(self, a, b):
+                print a + b
+        """)
+
+        src = helper(srcBefore, coords(4, 8), coords(4, 19), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_worksWhenUserSelectsABlockButDoesntSelectTheHangingDedent(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+
+        src = helper(srcBefore, coords(4, 8), coords(4, 16), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasSingleReturnValue(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 35    # <-- extract me
+                print a
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = self.newMethod()
+                print a
+
+            def newMethod(self):
+                a = 35    # <-- extract me
+                return a
+        """)
+
+        src = helper(srcBefore, coords(3, 4),
+                         coords(3, 34), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_newMethodHasMultipleReturnValues(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 35
+                b = 352
+                print a + b
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a, b = self.newMethod()
+                print a + b
+
+            def newMethod(self):
+                a = 35
+                b = 352
+                return a, b
+        """)
+        src = helper(srcBefore, coords(3, 8),
+                         coords(4, 15), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_worksWhenMovingCodeJustAfterDedent(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+                print \"hello\"
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+                self.newMethod()
+
+            def newMethod(self):
+                print \"hello\"
+        """)
+
+        src = helper(srcBefore, coords(5, 8),
+                         coords(5, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    
+    def test_extractsPassWhenSelectionCoordsAreReversed(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(3, 12), coords(3, 8), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsExpression(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                a = 32
+                b = 2 + a * 1 + 2
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                a = 32
+                b = 2 + self.newMethod(a) + 2
+
+            def newMethod(self, a):
+                return a * 1
+        """)
+        src = helper(srcBefore, coords(4, 16), coords(4, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsExpression2(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                g = 32
+                assert output.thingy(g) == \"bah\"
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                g = 32
+                assert self.newMethod(g) == \"bah\"
+
+            def newMethod(self, g):
+                return output.thingy(g)
+        """)
+        src = helper(srcBefore, coords(4, 15), coords(4, 31), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+class TestExtractFunction(BRMTestCase):
+    def runTarget(self, src, begincoords, endcoords, newname):
+        ast = createAST(src)
+        extractFunction(ast, begincoords, endcoords, newname)
+        return ast
+
+    def test_extractsFunction(self):        
+        srcBefore=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            c = a + 99
+            b = c * 1
+            print b
+        """)
+        srcAfter=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            b = newFunction(a)
+            print b
+
+        def newFunction(a):
+            c = a + 99
+            b = c * 1
+            return b
+        """)
+
+        src = helper(srcBefore, coords(3, 4),
+                         coords(4, 13), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractsAssignToAttribute(self):
+        srcBefore=trimLines("""
+        def simulateLoad(path):
+            item = foo()
+            item.decl = line
+        """)
+        srcAfter=trimLines("""
+        def simulateLoad(path):
+            item = foo()
+            newFunction(item)
+
+        def newFunction(item):
+            item.decl = line
+        """)
+
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsFromFirstBlockOfIfElseStatement(self):
+        srcBefore=trimLines("""
+        def foo():
+            if bah:
+                print \"hello1\"
+                print \"hello2\"
+                
+            elif foo:
+                pass
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            if bah:
+                newFunction()
+                print \"hello2\"
+                
+            elif foo:
+                pass
+
+        def newFunction():
+            print \"hello1\"
+        """)
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_extractsAugAssign(self):
+        srcBefore=trimLines("""
+        def foo():
+            a = 3
+            a += 1
+            print a
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3
+            a = newFunction(a)
+            print a
+
+        def newFunction(a):
+            a += 1
+            return a
+        """)
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+    def test_extractsForLoopUsingLoopVariable(self):
+        srcBefore=trimLines("""
+        def foo():
+            for i in range(1, 3):
+                print i
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            for i in range(1, 3):
+                newFunction(i)
+
+        def newFunction(i):
+            print i
+        """)
+
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractWhileLoopVariableIncrement(self):
+        srcBefore=trimLines("""
+        def foo():
+            a = 0
+            while a != 3:
+                a = a+1
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 0
+            while a != 3:
+                a = newFunction(a)
+
+        def newFunction(a):
+            a = a+1
+            return a
+        """)
+        src = helper(srcBefore, coords(4, 0),
+                         coords(5, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractAssignedVariableUsedInOuterForLoop(self):
+        srcBefore=trimLines("""
+        def foo():
+            b = 0
+            for a in range(1, 3):
+                b = b+1
+                while b != 2:
+                    print a
+                    b += 1
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            b = 0
+            for a in range(1, 3):
+                b = b+1
+                while b != 2:
+                    b = newFunction(a, b)
+
+        def newFunction(a, b):
+            print a
+            b += 1
+            return b
+        """)
+
+        src = helper(srcBefore, coords(6, 0),
+                         coords(8, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_extractsConditionalFromExpression(self):
+        srcBefore=trimLines("""
+        def foo():
+            if 123+3:
+                print aoue
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            if newFunction():
+                print aoue
+
+        def newFunction():
+            return 123+3
+        """)
+        src = helper(srcBefore, coords(2, 7),
+                         coords(2, 12), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+    def test_extractCodeAfterCommentInMiddleOfFnDoesntRaiseParseException(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            print 1
+            # comment
+            print 2
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            print 1
+            # comment
+            newFunction()
+
+        def newFunction():
+            print 2
+        """)
+        src = helper(srcBefore, coords(4, 0),
+                         coords(5, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_canExtractQueryFromNestedIfStatement(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            if foo: # comment
+                if bah:
+                    pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            if foo: # comment
+                if newFunction():
+                    pass
+
+        def newFunction():
+            return bah
+        """)
+        src = helper(srcBefore, coords(3, 11),
+                         coords(3, 14), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_doesntMessUpTheNextFunctionOrClass(self):
+        srcBefore=trimLines("""
+        def myFunction():
+            a = 3
+            print \"hello\"+a  # extract me
+            
+        class MyClass:
+            def myMethod(self):
+                b = 12      # extract me
+                c = 3       # and me
+                d = 2       # and me
+                print b, c
+        """)
+        srcAfter=trimLines("""
+        def myFunction():
+            a = 3
+            newFunction(a)
+
+        def newFunction(a):
+            print \"hello\"+a  # extract me
+            
+        class MyClass:
+            def myMethod(self):
+                b = 12      # extract me
+                c = 3       # and me
+                d = 2       # and me
+                print b, c
+        """)
+
+        # extract code on one line
+        src = helper(srcBefore, coords(3, 4),
+                         coords(3, 34), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+        # extract code on 2 lines (most common user method)
+        resetRoot()
+        Cache.instance.reset()
+        Root()
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntBallsUpIndentWhenTheresALineWithNoSpacesInIt(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            if 1:
+                pass
+
+            pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            newFunction()
+
+        def newFunction():
+            if 1:
+                pass
+            
+            pass
+        """)
+        src = helper(srcBefore, coords(2, 4),
+                     coords(5, 8), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntHaveToBeInsideAFunction(self):
+        srcBefore=trimLines(r"""
+        a = 1
+        print a + 2
+        f(b)	
+        """)
+        srcAfter=trimLines(r"""
+        a = 1
+        newFunction(a)
+
+        def newFunction(a):
+            print a + 2
+            f(b)	
+        """)
+        src = helper(srcBefore, coords(2, 0),
+                         coords(3, 4), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntBarfWhenEncountersMethodCalledOnCreatedObj(self):
+        srcBefore=trimLines(r"""
+        results = QueryEngine(q).foo()
+        """)
+        srcAfter=trimLines(r"""
+        newFunction()
+
+        def newFunction():
+            results = QueryEngine(q).foo()
+        """)
+        src = helper(srcBefore, coords(1, 0),
+                         coords(2, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_worksIfNoLinesBeforeExtractedCode(self):
+        srcBefore=trimLines(r"""
+        print a + 2
+        f(b)	
+        """)
+        srcAfter=trimLines(r"""
+        newFunction()
+
+        def newFunction():
+            print a + 2
+            f(b)	
+        """)
+        src = helper(srcBefore, coords(1, 0),
+                         coords(2, 4), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+class TestGetRegionAsString(BRMTestCase):
+    def test_getsHighlightedSingleLinePassStatement(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 8),
+                             coords(3, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(len(em.extractedLines), 1)
+        self.assertEqual(em.extractedLines[0], "pass\n")
+        
+    def test_getsSingleLinePassStatementWhenWholeLineIsHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 0),
+                             coords(3, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(len(em.extractedLines), 1)
+        self.assertEqual(em.extractedLines[0], "pass\n")
+
+
+    def test_getsMultiLineRegionWhenJustRegionIsHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                print 'hello'
+                pass
+        """)
+        region=trimLines("""
+        print 'hello'
+        pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 8),
+                             coords(4, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+    def test_getsMultiLineRegionWhenRegionLinesAreHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                print 'hello'
+                pass
+
+        """)
+        region=trimLines("""
+        print 'hello'
+        pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 0),
+                             coords(5, 0), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+    def test_getsHighlightedSubstringOfLine(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                if a == 3:
+                    pass
+        """)
+        region=trimLines("""
+        a == 3
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 11),
+                             coords(3, 17), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+
+class TestGetTabwidthOfParentFunction(BRMTestCase):
+    def test_getsTabwidthForSimpleMethod(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 11),
+                             coords(3, 17), "foobah")
+        self.assertEqual(em.getTabwidthOfParentFunction(), 4)
+
+    def test_getsTabwidthForFunctionAtRootScope(self):
+        src=trimLines("""
+        def myFn(self):
+            pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(2, 0),
+                             coords(2, 9), "foobah")
+        self.assertEqual(em.getTabwidthOfParentFunction(), 0)
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_extractVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike.testutils import *
+from bike.refactor.extractVariable import coords, extractLocalVariable
+
+class TestExtractLocalVariable(BRMTestCase):
+    def test_worksOnSimpleCase(self):
+        srcBefore=trimLines("""
+        def foo():
+            print 3 + 2
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3 + 2
+            print a
+        """)
+        sourcenode = createAST(srcBefore)
+        extractLocalVariable(tmpfile,coords(2,10),coords(2,15),'a')
+        self.assertEqual(sourcenode.getSource(),srcAfter)
+
+    def test_worksIfCoordsTheWrongWayRound(self):
+        srcBefore=trimLines("""
+        def foo():
+            print 3 + 2
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3 + 2
+            print a
+        """)
+        sourcenode = createAST(srcBefore)
+        extractLocalVariable(tmpfile,coords(2,15),coords(2,10),'a')
+        self.assertEqual(sourcenode.getSource(),srcAfter)
+
+        
+if __name__ == "__main__":
+    unittest.main()
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_inlineVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike.testutils import trimLines,createAST, BRMTestCase
+from inlineVariable import inlineLocalVariable_old
+
+class TestInlineLocalVariable(BRMTestCase):
+
+    def test_worksWhenUserDoesItAgainstReference(self):
+        srcBefore=r"""
+        def foo():
+            b = 'hello'
+            print b
+        """
+        srcAfter=r"""
+        def foo():
+            print 'hello'
+        """
+
+        self.helper( srcBefore, 3, 10, srcAfter )
+
+    def test_worksWhenInlinedCodeIsOverTwoLines(self):
+        srcBefore=r"""
+        def foo():
+            b = 3 + \
+                2
+            print b
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 3 + \
+                2
+        """
+
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    ''' Needs Adding Again 
+    def test_addsBracketsWhenInlinedCodeHasPresidenceOverSurroundingCode(self):
+        srcBefore=trimLines(r"""
+        def foo():
+            b = 3 + 2
+            print 3 * b
+        """)
+        srcAfter=trimLines(r"""
+        def foo():
+            print 3 * (3 + 2)
+        """)
+        assert 0
+    '''
+
+    def test_worksWithMultipleInstancesOfVariableOnLine(self):
+        srcBefore=r"""
+        def foo():
+            x = 11
+            print x, x
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 11, 11
+        """
+        
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    def test_worksWithMultipleMultilineCode(self):
+        srcBefore=r"""
+        def foo():
+            b = 3 + \
+                2
+            print b
+            print b
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 3 + \
+                2
+            print 3 + \
+                2
+        """
+
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    ''' Can't do this without some hairy logic to deduce how to inline
+        the variables. E.g. how do you inline a,b = foo() ?
+
+    def test_handlesTupleAssignment(self):
+        srcBefore=r"""
+        def foo():
+            x, y = 1, 2
+            print x
+            print y
+        """
+
+        srcAfter=r"""
+        def foo():
+            y = 2
+            print 1
+            print y
+        """
+        
+        self.helper(srcBefore, 2, 4, srcAfter)
+    '''
+
+
+    def helper(self, srcBefore, y, x, srcAfter):
+        sourcenode = createAST(trimLines(srcBefore))
+        inlineLocalVariable_old(sourcenode,y,x)
+        self.assertEqual(sourcenode.getSource(),trimLines(srcAfter))
+
+if __name__ == "__main__":
+    unittest.main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_moveToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+import setpath
+from bike.testutils import *
+from bike.transformer.save import save
+
+from moveToModule import *
+
+class TestMoveClass(BRMTestCase):
+    def test_movesTheText(self):
+        src1=trimLines("""
+        def before(): pass
+        class TheClass:
+            pass
+        def after(): pass
+        """)
+        src1after=trimLines("""
+        def before(): pass
+        def after(): pass
+        """)
+        src2after=trimLines("""
+        class TheClass:
+            pass
+        """)
+        
+        try:
+            createPackageStructure(src1, "")
+            moveClassToNewModule(pkgstructureFile1,2,
+                                 pkgstructureFile2)
+            save()
+            self.assertEqual(src1after,file(pkgstructureFile1).read())
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+
+class TestMoveFunction(BRMTestCase):
+    def test_importsNameReference(self):
+        src1=trimLines("""
+        a = 'hello'
+        def theFunction(self):
+            print a
+        """)
+        src2after=trimLines("""
+        from a.foo import a
+        def theFunction(self):
+            print a
+        """)
+        self.helper(src1, src2after)
+        
+
+
+    def test_importsExternalReference(self):
+        src0=("""
+        a = 'hello'
+        """)
+        src1=trimLines("""
+        from top import a
+        def theFunction(self):
+            print a
+        """)
+        src2after=trimLines("""
+        from top import a
+        def theFunction(self):
+            print a
+        """)
+        try:
+            createPackageStructure(src1, "", src0)
+            moveFunctionToNewModule(pkgstructureFile1,2,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+
+    def test_doesntImportRefCreatedInFunction(self):
+        src1=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        src2after=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        
+        self.helper(src1, src2after)
+
+
+    def test_doesntImportRefCreatedInFunction(self):
+        src1=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        src2after=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        
+        self.helper(src1, src2after)
+
+
+    def test_addsImportStatementToOriginalFileIfRequired(self):
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        b = theFunction()
+        """)
+        
+        src1after=trimLines("""
+        from a.b.bah import theFunction
+        b = theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"")
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src1after,file(pkgstructureFile1).read())
+        finally:
+            removePackageStructure()
+
+    def test_updatesFromImportStatementsInOtherModules(self):
+        src0=trimLines("""
+        from a.foo import theFunction
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        """)
+        
+        src0after=trimLines("""
+        from a.b.bah import theFunction
+        print theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+    def test_updatesFromImportMultiplesInOtherModules(self):
+        src0=trimLines("""
+        from a.foo import something,theFunction,somethingelse #comment
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        something = ''
+        somethingelse = 0
+        """)
+        
+        src0after=trimLines("""
+        from a.foo import something,somethingelse #comment
+        from a.b.bah import theFunction
+        print theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+        
+    def test_updatesFromImportMultiplesInTargetModule(self):
+        src0=trimLines("""
+        from a.foo import something,theFunction,somethingelse #comment
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        something = ''
+        somethingelse = 0
+        """)
+        
+        src0after=trimLines("""
+        from a.foo import something,somethingelse #comment
+        print theFunction()
+        def theFunction(self):
+            pass
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile0)
+            save()
+            #print file(pkgstructureFile0).read()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+
+    def test_updatesFromImportInTargetModule(self):
+        src0=trimLines("""
+        from a.foo import theFunction
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        """)
+        
+        src0after=trimLines("""
+        print theFunction()
+        def theFunction(self):
+            pass
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile0)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+
+
+    def helper(self, src1, src2after):
+        try:
+            createPackageStructure(src1, "")
+            moveFunctionToNewModule(pkgstructureFile1,2,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+        
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_rename.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike import testdata
+from rename import rename
+from bike.testutils import *
+
+class TestRenameTemporary(BRMTestCase):
+    def test_renamesSimpleReferencesGivenAssignment(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            b = 3
+            print b
+        """)
+        src = self.helper(src,"",2,4,"b")
+        self.assertEqual(srcAfter,src)
+
+    def helper(self, src, classsrc, line, col, newname):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            rename(filename,line,col,newname)
+            # modify me once save is moved
+            #return readFile(filename)
+            from bike.transformer.save import outputqueue
+            return outputqueue[filename]
+        finally:
+            removePackageStructure()
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameClass.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+from bike.transformer.save import save
+from bike.testutils import *
+import compiler
+
+class RenameClassTests:
+
+    def testRenamesClassDcl(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            def theMethod():
+                pass
+        """)
+
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass()
+    def testRenamesClassReference(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        a = NewName()
+        """)
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass.TheClass()
+    def testRenamesClassReferenceWhenScopeIsSameNameAsClass(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            class NewName:
+                pass
+        a = TheClass.NewName()
+        """)
+        src = self.rename(srcBefore, 2,10, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass.TheClass()
+    def testRenamesClassReferenceWhenChildIsSameNameAsClass(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            class TheClass:
+                pass
+        a = NewName.TheClass()
+        """)
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+
+    # a = TheClass() + TheClass()
+    def testRenamesClassReferenceWhenTwoRefsInTheSameLine(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass() + TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        a = NewName() + NewName()
+        """)
+        src = self.rename(srcBefore,1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferenceInInstanceCreation(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            def theMethod(self): pass
+        NewName().theMethod()
+        """)
+        src = self.rename(srcBefore,1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. if renaming TheClass, shouldnt rename a.b.c.TheClass
+    def testDoesntRenameBugusClassReferenceOnEndOfGetattrNest(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass        
+        a.b.c.TheClass    # Shouldn't be renamed
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass        
+        a.b.c.TheClass    # Shouldn't be renamed
+        """)
+        src = self.rename(srcBefore,1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassRefUsedInExceptionRaise(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        raise TheClass, \"hello mum\"
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        raise NewName, \"hello mum\"
+        """)
+        src = self.rename(srcBefore, 1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferenceNameInInheritenceSpec(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        class DerivedClass(TheClass):
+            pass
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        class DerivedClass(NewName):
+            pass
+        """)
+        src = self.rename(srcBefore, 1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+
+
+class RenameClassTests_importsClass:
+
+    def testRenamesClassReferenceInInstanceCreationWithFQN(self):
+        srcBefore=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.NewName()
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferencesInInheritenceSpecs(self):
+
+        srcBefore=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        """)
+        srcAfter=trimLines("""
+        import b
+        class DerivedClass(b.bah.NewName):
+            pass
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFromImportReferenceWhenInBodyOfClass(self):
+        srcBefore=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        srcAfter=trimLines("""
+        class AnotherClass:
+            from b.bah import NewName
+            NewName.baz = 0
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+
+    def testRenamesReferenceToClassImportedInSameClassScope(self):
+        srcBefore=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        srcAfter=trimLines("""
+        class AnotherClass:
+            from b.bah import NewName
+            NewName.baz = 0
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesReferenceToClassImportedWithFromImportStar(self):
+        srcBefore=trimLines("""
+        from a.b.bah import *
+        a = TheClass()
+        """)
+        srcAfter=trimLines("""
+        from a.b.bah import *
+        a = NewName()
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+class TestRenameClass(BRMTestCase, RenameClassTests):
+
+    def rename(self, src, line, col, newname):
+        createPackageStructure(src,"pass")
+        rename(pkgstructureFile1,line,col, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+class TestRenameClassReferenceWithDirectoryStructure(BRMTestCase,
+                                         RenameClassTests_importsClass):
+
+    def renameClass(self, src, newname):
+        createPackageStructure(src,TheClassTestdata)
+        rename(pkgstructureFile2,1,6, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+TheClassTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameFunction.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+from bike import testdata
+from bike.testutils import *
+from bike.transformer.save import save
+import compiler
+
+class RenameFunctionTests:
+    def runTarget(self, src, klassfqn, newname):
+        # see concrete subclasses for implementation
+        pass
+
+    def testRenamesFunctionDcl(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            pass
+        """)
+        srcAfter=trimLines("""
+        def newName():
+            pass
+        """)
+        src = self.rename(srcBefore,1,4,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testDoesntBarfWhenFunctionIncludesBrackettedExpression(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            return ('\\n').strip()
+        """)
+        srcAfter=trimLines("""
+        def newName():
+            return ('\\n').strip()
+        """)
+        src = self.rename(srcBefore,1,4, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+
+class RenameFunctionTests_importsFunction:
+
+    def testRenamesImportedFunctionReference(self):
+        srcBefore=trimLines("""
+        import b.bah
+        b.bah.theFunction()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        b.bah.newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFunctionReferenceImportedWithFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import theFunction
+        theFunction()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import newName
+        newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFunctionRefInImportClause(self):
+        srcBefore=trimLines("""
+        import b.bah
+        b.bah.theFunction()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        b.bah.newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def testRenamesFunctionRefInImportFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import theFunction
+        theFunction()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import newName
+        newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+class TestRenameFunction(BRMTestCase, RenameFunctionTests):
+    def rename(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        rename(tmpfile,line,col, newname)
+        save()
+        return file(tmpfile).read()
+
+
+class TestRenameFunctionReferenceWithDirectoryStructure(BRMTestCase, RenameFunctionTests_importsFunction):
+
+    def renameFunction(self, src, newname):
+        createPackageStructure(src,FunctionTestdata)
+        rename(pkgstructureFile2,1,4, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+FunctionTestdata = trimLines("""
+def theFunction():
+    pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,710 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+import compiler
+from bike import testdata
+
+from bike.testutils import*
+
+from bike.transformer.save import save
+
+class RenameMethodTests:
+    
+    def test_renamesTheMethod(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameMethodOfSameNameOnOtherClasses(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        class b:
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        class b:
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameOtherMethodsOfSameClass(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                a=b
+            def aMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                a=b
+            def aMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodWhenClassNestedInFunction(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            class TheClass:
+                def theMethod(self):
+                    pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            class TheClass:
+                def newName(self):
+                    pass
+        """)
+        src = self.rename(srcBefore,3,12,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnInheritanceHierarchies(self):
+        srcBefore=trimLines("""
+        from b.bah import DifferentClass
+        class TheClass(foo.bah):
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+
+    def test_renamesMethodWhenMethodCallFromOtherMethodInSameClass(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+            def anotherMethod(self):
+                self.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnNestedClasses(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            class AnotherClass:
+                pass
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,4,8,"newName")
+
+    def test_renamesMethodWhenBaseClassesArentInAST(self):
+        srcBefore=trimLines("""
+        class TheClass(notInAst):
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass(notInAst):
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodInRelatedClasses(self):
+        srcBefore=trimLines("""
+        class root:
+            def theMethod(self):
+                pass
+
+        class a(root):
+            def theMethod(self):
+                pass
+
+        class b(root):
+            pass
+
+        class TheClass(b):
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class root:
+            def newName(self):
+                pass
+
+        class a(root):
+            def newName(self):
+                pass
+
+        class b(root):
+            pass
+
+        class TheClass(b):
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,13,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renameMethodDoesntBarfOnNoneAsDefaultArgToMethod(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self, root, flist, stack=None):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+
+
+
+class RenameMethodTests_ImportsClass:
+    def test_renamesMethodOnDerivedClassInstance(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        class DerivedDerivedClass(DerivedClass):
+            def theMethod(self):
+                print 'hello'
+        """)
+        srcAfter = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        class DerivedDerivedClass(DerivedClass):
+            def newName(self):
+                print 'hello'
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+        
+class RenameMethodReferenceTests:
+    # Generic tests. These tests are designed to be run in the context of a ui
+    #  and in a package hierarchy structure
+
+    def test_doesntBarfWhenConfrontedWithComplexReturnTypes(self):
+        src = trimLines("""
+        import a
+        class TheClass:
+            def theMethod(self):
+                 pass
+                 
+        def bah():
+            return a[35]
+            
+        b = bah()
+        b.theMethod()
+        """)
+        self.rename(src,3,8,"newName")
+
+    def test_doesntbarfWhenCallMadeOnInstanceReturnedFromFnCall(self):
+        srcBefore=trimLines("""
+        from foo import e
+        class TheClass:
+            def theMethod(self):
+                pass
+        ast = e().f(src)
+        """)
+        self.rename(srcBefore,3,8,"newName")
+
+    def test_doesntStackOverflowOnRecursiveFunctions(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+
+        def foo(a):
+            return foo(a)
+        """)
+        self.rename(srcBefore,2,8,"newName")
+
+    def test_renamesMethodReferenceOfInstanceCreatedInParentScopeAfterFunction(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass()
+        def foo():
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        a = TheClass()
+        def foo():
+            a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+ 
+    def test_renamesMethodReferenceOfInstanceObtainedByCallingFunction(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInAnotherFunction(self):
+
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def bah():
+            return TheClass()
+        def foo():
+            a = bah()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        def bah():
+            return TheClass()
+        def foo():
+            a = bah()
+            a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.newName()
+            
+        def bah():
+            return TheClass()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOnInstanceThatIsAnAttributeOfSelf(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnGetattrThatItCantDeduceTypeOf(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass
+        
+        a.b.bah = 3
+        """)
+        self.rename(srcBefore,2,8,"newName")
+
+
+class RenameMethodReferenceTests_ImportsClass:
+
+    def test_renamesReferenceOfClassImportedAsAnotherName(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass as MyTheClass        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass as MyTheClass        
+        def foo():
+            a = MyTheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore,2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesReferenceWhenObjectCreationAndReferenceInModuleScope(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renamesReferenceWhenObjectCreatedInSameFunctionAsReference(self):
+        srcBefore=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntrenameDifferentMethodReferenceWhenObjectCreatedInSameScope(self):
+        srcBefore=trimLines("""
+        import b.bah.TheClass
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 4,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_doesntrenameMethodReferenceWhenDifferentObjectCreatedInSameScope(self):
+        srcBefore=trimLines("""
+        import b.bah.TheClass
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 8,8,"newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfImportedClass(self):
+        srcBefore=trimLines("""
+        import b.bah
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameReferenceOfDifferentImportedClass(self):
+        srcBefore=trimLines("""
+        from b.bah import DifferentClass
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 8,8,
+                                           "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfClassImportedWithFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            a = TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntrenameReferenceOfClassImportedWithDifferentAsClause(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass as MyClass
+        
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfClassImportedWithFromFooImportStar(self):
+        srcBefore=trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInParentScope(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        def foo():
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        def foo():
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOnDerivedClassInstance(self):
+        srcBefore=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        theInstance = DerivedDerivedClass()
+        theInstance.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        theInstance = DerivedDerivedClass()
+        theInstance.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+# tests that cover stuff not renamed automatically
+# (I.e. are renamed after user manually expresses desire to do so)
+class RenameMethodAfterPromptTests:
+    def test_renamesReferenceWhenMethodCallDoneOnInstanceCreation(self):
+
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self): pass
+        TheClass().newName()
+        """)
+        src = self.renameMethod(srcBefore,2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renamesReferenceInMiddleOfBiggerCompoundCall(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self): return AnotherClass()
+        TheClass().newName().anotherMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+class TestRenameMethodWithSingleModule(BRMTestCase, RenameMethodTests, RenameMethodReferenceTests):
+    # template method 
+    def rename(self, src, line, col, newname):
+        try:
+            createPackageStructure(src, "pass")
+            rename(pkgstructureFile1,line,col,newname)
+            save()
+            return file(pkgstructureFile1).read()
+        finally:
+            removePackageStructure()
+
+
+class TestRenameMethodWithDirectoryStructure(RenameMethodTests, RenameMethodReferenceTests, BRMTestCase):
+
+    def rename(self, src, line, col, newname):
+        try:
+            createPackageStructure("pass",src)
+            rename(pkgstructureFile2,line,col,newname)
+            save()
+            return file(pkgstructureFile2).read()
+        finally:
+            removePackageStructure()
+
+
+class TestRenameMethodReferenceWithDirectoryStructure(BRMTestCase, RenameMethodTests_ImportsClass, RenameMethodReferenceTests_ImportsClass):
+
+    def renameMethod(self, src, line, col, newname):
+        try:
+            createPackageStructure(src,MethodTestdata)
+            rename(pkgstructureFile2,line,col,newname)
+            save()
+            return file(pkgstructureFile1).read()
+        finally:
+            removePackageStructure()
+
+class TestRenameMethodStuffCorrectlyAfterPromptReturnsTrue(BRMTestCase, 
+                                                      RenameMethodAfterPromptTests):
+
+    def callback(self, filename, line, colbegin, colend):
+        return 1
+
+
+    def renameMethod(self, src, line, col, newname):
+        createPackageStructure(src, MethodTestdata)
+        rename(pkgstructureFile1,line,col,newname,self.callback)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+
+class TestDoesntRenameMethodIfPromptReturnsFalse(BRMTestCase):
+    def callback(self, filename, line, colbegin, colend):
+        return 0
+
+    def renameMethod(self, src, line, col, newname):
+        createPackageStructure(src, MethodTestdata)
+        rename(pkgstructureFile1,line,col,newname,self.callback)
+        save()
+        return file(pkgstructureFile1).read()
+
+    def test_doesntRenameMethodIfPromptReturnsFalse(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        b = TheClass()
+        b.theMethod()
+        a = someFunction()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        b = TheClass()
+        b.newName()
+        a = someFunction()
+        a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+MethodTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+import setpath
+from test_renameMethod import *
+from test_renameClass import *
+from test_renameFunction import *
+from test_rename import *
+from test_extractMethod import *
+from test_inlineVariable import *
+from test_extractVariable import *
+from test_moveToModule import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,24 @@
+import re
+
+def getLineSeperator(line):
+    if line.endswith("\r\n"):
+        linesep = "\r\n"          # windoze
+    else:
+        linesep = line[-1]   # mac or unix
+    return linesep
+
+
+def getTabWidthOfLine(line):
+    match = re.match("\s+",line)
+    if match is None:
+        return 0
+    else:
+        return match.end(0)
+
+def reverseCoordsIfWrongWayRound(startcoords,endcoords):
+    if(startcoords.line > endcoords.line) or \
+         (startcoords.line == endcoords.line and \
+          startcoords.column > endcoords.column):
+        return endcoords,startcoords
+    else:
+        return startcoords,endcoords
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath(".."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/test_bikefacade.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,377 @@
+#!/usr/bin/env python
+import unittest
+import setpath
+import sys
+
+from bike import testdata
+from bike.testutils import *
+import bike
+from bike.refactor.test_renameFunction import RenameFunctionTests, RenameFunctionTests_importsFunction, FunctionTestdata
+from bike.refactor.test_renameClass import RenameClassTests, RenameClassTests_importsClass, TheClassTestdata
+from bike.refactor.test_renameMethod import RenameMethodTests, RenameMethodTests_ImportsClass, RenameMethodReferenceTests, RenameMethodReferenceTests_ImportsClass, RenameMethodAfterPromptTests, TestDoesntRenameMethodIfPromptReturnsFalse,MethodTestdata
+from bike.refactor import test_extractMethod
+import bikefacade
+from bike import UndoStackEmptyException
+from bike.query.getTypeOf import getTypeOf
+
+class TestPathFunctions(BRMTestCase):
+    def test_setCompletePythonPath_removesDuplicates(self):
+        origpath = sys.path
+        try:
+            sys.path = ["foobah"]
+            ctx = bike.init()
+            ctx._setCompletePythonPath(sys.path[-1])
+            self.assertEqual(1,ctx._getCurrentSearchPath().count(sys.path[-1]))
+        finally:
+            sys.path = origpath
+
+
+    def test_setNonLibPathonPath_removesLibDirectories(self):
+        origpath = sys.path
+        try:
+            writeTmpTestFile("pass")
+            libdir = os.path.join(sys.prefix,"lib","python"+sys.version[:3])
+            sys.path = [libdir,os.path.join(libdir,"site-packages")]
+            ctx = bike.init()
+            ctx._setNonLibPythonPath(tmproot)
+            self.assertEqual([tmproot],ctx._getCurrentSearchPath())
+        finally:
+            sys.path = origpath
+
+class TestRenameMethodAfterPrompt(BRMTestCase,RenameMethodAfterPromptTests):
+    def callback(self, filename, line, colstart, colend):
+        return 1
+
+    def renameMethod(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.setRenameMethodPromptCallback(self.callback)
+        ctx.renameByCoordinates(tmpfile,line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+class TestDoesntRenameMethodIfPromptReturnsFalse(TestDoesntRenameMethodIfPromptReturnsFalse):
+
+    def callback(self, filename, line, colstart, colend):
+        return 0
+
+    def renameMethod(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.setRenameMethodPromptCallback(self.callback)
+        ctx.renameByCoordinates(tmpfile,line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+
+class TestRenameByCoordinates2(RenameMethodTests,RenameMethodReferenceTests, RenameClassTests,RenameFunctionTests,BRMTestCase):
+    def rename(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.renameByCoordinates(os.path.abspath(tmpfile),line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+
+class TestRenameByCoordinatesWithDirectoryStructure(
+                                RenameClassTests_importsClass,
+                                RenameFunctionTests_importsFunction,
+                                RenameMethodTests_ImportsClass,
+                                RenameMethodReferenceTests_ImportsClass,
+                                BRMTestCase):
+    def renameClass(self, src, newname):
+        try:
+            createPackageStructure(src, TheClassTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,1,6,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+
+    def renameMethod(self, src, line, col, newname):
+        try:
+            createPackageStructure(src, MethodTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,line,col,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+    def renameFunction(self, src, newname):
+        try:
+            createPackageStructure(src, FunctionTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,1,4,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+
+
+class Test_deducePackageOfFile(BRMTestCase):
+    def test_returnsEmptyStringIfFileNotInPackage(self):
+        try:
+            # this doesnt have __init__.py file, so
+            # isnt package
+            os.makedirs("a")
+            writeFile(os.path.join("a","foo.py"),"pass")
+            pkg = bikefacade._deducePackageOfFile(os.path.join("a","foo.py"))
+            assert pkg == ""
+        finally:
+            os.remove(os.path.join("a","foo.py"))
+            os.removedirs(os.path.join("a"))
+
+    def test_returnsNestedPackage(self):
+        try:
+            os.makedirs(os.path.join("a","b"))
+            writeFile(os.path.join("a","__init__.py"),"# ")
+            writeFile(os.path.join("a","b","__init__.py"),"# ")
+            writeFile(os.path.join("a","b","foo.py"),"pass")
+            pkg = bikefacade._deducePackageOfFile(os.path.join("a","b","foo.py"))
+            assert pkg == "a.b"
+        finally:
+            os.remove(os.path.join("a","__init__.py"))
+            os.remove(os.path.join("a","b","__init__.py"))
+            os.remove(os.path.join("a","b","foo.py"))
+            os.removedirs(os.path.join("a","b"))
+        
+
+class TestExtractMethod(test_extractMethod.TestExtractMethod):
+
+    def test_extractsPass(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+
+        writeTmpTestFile(srcBefore)
+        ctx = bike.init()
+        ctx.extractMethod(os.path.abspath(tmpfile),3,8,3,12,"newMethod")
+        ctx.save()
+        self.assertEqual(readTmpTestFile(),srcAfter)
+        ctx.undo()
+        ctx.save()
+        self.assertEqual(readTmpTestFile(),srcBefore)
+        
+
+class TestExtractFunction(test_extractMethod.TestExtractFunction):
+    def test_extractsFunction(self):        
+        srcBefore=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            c = a + 99
+            b = c * 1
+            print b
+        """)
+        srcAfter=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            b = newFunction(a)
+            print b
+
+        def newFunction(a):
+            c = a + 99
+            b = c * 1
+            return b
+        """)
+        writeTmpTestFile(srcBefore)
+        ctx = bike.init()
+        ctx.extractMethod(os.path.abspath(tmpfile),3,4,4,13,"newFunction")
+        ctx.save()
+        self.assertEqual(readTmpTestFile(),srcAfter)
+        ctx.undo()
+        ctx.save()
+        self.assertEqual(readTmpTestFile(),srcBefore)
+
+
+class TestUndo(BRMTestCase):
+
+    def test_undoesTheTextOfASingleFile(self):
+        src = trimLines("""
+        class a:
+            def foo(self):
+                pass
+        """)
+        writeTmpTestFile(src)
+        #ctx = bike.init()
+        ctx = bike.init()
+
+        ctx.renameByCoordinates(tmpfile,2,8,"c")
+        ctx.save()
+        ctx.undo()
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        self.assertEqual(newsrc,src)
+
+
+    def test_undoesTwoConsecutiveRefactorings(self):
+        try:
+            src = trimLines("""
+            class a:
+                def foo(self):
+                    pass
+            """)
+            writeTmpTestFile(src)
+            ctx = bike.init()
+            ctx.renameByCoordinates(tmpfile,2,8,"c")
+            ctx.save()
+            
+            newsrc1 = readFile(tmpfile)
+
+            ctx.renameByCoordinates(tmpfile,2,8,"d")
+            ctx.save()
+
+            
+            # 1st undo
+            ctx.undo()
+            ctx.save()
+            newsrc = readFile(tmpfile)
+            self.assertEqual(newsrc,
+                             newsrc1)
+
+            # 2nd undo
+            ctx.undo()
+            ctx.save()
+            newsrc = readFile(tmpfile)
+            self.assertEqual(newsrc,src)
+        finally:
+            pass
+            #deleteTmpTestFile()
+        
+
+    def test_undoesTheTextOfAFileTwice(self):
+        for i in range(3):
+            src = trimLines("""
+            class foo:
+                def bah(self):
+                    pass
+            """)
+            writeTmpTestFile(src)
+            ctx = bike.init()
+            ctx.renameByCoordinates(tmpfile,2,8,"c")
+            ctx.save()
+            ctx.undo()
+            ctx.save()
+            newsrc = readFile(tmpfile)
+            self.assertEqual(newsrc,src)
+            raisedexception=0
+            try:
+                ctx.undo()
+            except UndoStackEmptyException:
+                pass
+            else:
+                assert 0,"should have raised an exception"
+
+    '''
+    def test_undoesManualModificationsToFiles(self):
+        writeTmpTestFile("class foo: pass")
+        origsrc = readFile(tmpfile)
+        ctx = bike.init()
+
+        writeTmpTestFile("pass")
+        import os
+        ctx.init()
+        newsrc = readFile(tmpfile)
+        assert newsrc != origsrc
+        ctx.undo()
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        assert newsrc == origsrc
+    '''
+
+class TestGetReferencesToClass_Facade(BRMTestCase):
+    def test_returnsReferences(self):        
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        refs = [refs for refs in ctx.findReferencesByCoordinates(tmpfile,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(tmpfile))
+        self.assertEqual(refs[0].lineno,3)
+        assert hasattr(refs[0],"confidence")
+
+
+class TestFindDefinitionByCoordinates(BRMTestCase):
+    def test_findsClassRef(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        defn = [x for x in ctx.findDefinitionByCoordinates(tmpfile,3,6)]
+        assert defn[0].filename == os.path.abspath(tmpfile)
+        assert defn[0].lineno == 1
+        assert defn[0].confidence == 100
+
+class TestBRM_InlineLocalVariable(BRMTestCase):
+    def test_works(self):
+        srcBefore=trimLines("""
+        def foo():
+            b = 'hello'
+            print b
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            print 'hello'
+        """)
+
+        writeTmpTestFile(srcBefore)
+        ctx = bike.init()
+        ctx.inlineLocalVariable(tmpfile,3,10)
+        ctx.save()
+        self.assertEqual(file(tmpfile).read(),srcAfter)
+
+
+class TestBRM_ExtractLocalVariable(BRMTestCase):
+    def test_works(self):
+        srcBefore=trimLines("""
+        def foo():
+            print 3 + 2
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3 + 2
+            print a
+        """)
+        try:
+            writeTmpTestFile(srcBefore)
+            ctx = bike.init()
+            ctx.extractLocalVariable(tmpfile,2,10,2,15,'a')
+            ctx.save()
+            self.assertEqual(file(tmpfile).read(),srcAfter)
+        finally:
+            pass
+            #deleteTmpTestFile()
+
+
+
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/test_testutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from testutils import*
+import testdata
+import sys
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+import setpath
+from test_bikefacade import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/testdata.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,17 @@
+TheClass = """
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+"""
+
+
+Function = """
+def theFunction():
+    pass
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/testutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,170 @@
+from bike.globals import *
+import unittest
+import os
+import os.path
+from mock import Mock
+from bike.parsing.fastparserast import getRoot, Root, resetRoot
+from parsing.utils import fqn_rcar, fqn_rcdr
+import re
+from bike import log
+filesToDelete = None
+dirsToDelete = None
+
+class BRMTestCase(unittest.TestCase):
+    def setUp(self):
+        log.warning = log.SilentLogger()
+        try: os.makedirs(tmproot)
+        except: pass
+        os.chdir(tmproot)
+        
+        resetRoot(Root([tmproot]))
+        getRoot().unittestmode = True
+        global filesToDelete
+        global dirsToDelete
+        filesToDelete = []
+        dirsToDelete = []
+        from bike.parsing.load import Cache
+        Cache.instance.reset()
+
+
+
+    def tearDown(self):
+        global filesToDelete
+        global dirsToDelete
+
+        for path in filesToDelete:
+            try: os.remove(path)
+            except: pass
+        filesToDelete = []
+            
+        for path in dirsToDelete:
+            try: os.removedirs(path)
+            except: pass
+        dirsToDelete = []
+
+        os.chdir("..")
+        try: os.removedirs(tmproot)
+        except: pass
+
+
+
+tmproot = os.path.abspath("tmproot")
+tmpfile = os.path.join(tmproot, "bicyclerepairman_tmp_testfile.py")
+tmpmodule = "bicyclerepairman_tmp_testfile"
+
+
+def writeFile(filename, src):
+    f = open(filename, "w+")
+    f.write(src)
+    f.close()
+    filesToDelete.append(filename)
+
+def readFile(filename):
+    f = open(filename)
+    src = f.read()
+    f.close()
+    return src
+
+def writeTmpTestFile(src):
+    try:
+        os.makedirs(tmproot)
+    except OSError:
+        pass
+    writeFile(tmpfile, src)
+
+def readTmpTestFile():
+    return readFile(tmpfile)
+
+def deleteTmpTestFile():
+    os.remove(tmpfile)
+    os.removedirs(tmproot)
+
+
+pkgstructureRootDir = tmproot
+pkgstructureBasedir = os.path.join(pkgstructureRootDir, "a")
+pkgstructureChilddir = os.path.join(pkgstructureBasedir, "b")
+pkgstructureFile0 = os.path.join(pkgstructureRootDir, "top.py")
+pkgstructureFile1 = os.path.join(pkgstructureBasedir, "foo.py")
+pkgstructureFile2 = os.path.join(pkgstructureChilddir, "bah.py")
+
+
+def createPackageStructure(src1, src2, src0="pass"):
+    try: os.makedirs(pkgstructureChilddir)
+    except: pass
+    writeFile(os.path.join(pkgstructureBasedir, "__init__.py"), "#")
+    writeFile(os.path.join(pkgstructureChilddir, "__init__.py"), "#")
+    writeFile(pkgstructureFile0, src0)
+    writeFile(pkgstructureFile1, src1)
+    writeFile(pkgstructureFile2, src2)
+
+def removePackageStructure():
+    os.remove(os.path.join(pkgstructureBasedir, "__init__.py"))
+    os.remove(os.path.join(pkgstructureChilddir, "__init__.py"))
+    os.remove(pkgstructureFile0)
+    os.remove(pkgstructureFile1)
+    os.remove(pkgstructureFile2)
+    os.removedirs(pkgstructureChilddir)
+
+
+pkgstructureBasedir2 = os.path.join(pkgstructureRootDir, "c")
+pkgstructureFile3 = os.path.join(pkgstructureBasedir2, "bing.py")
+
+def createSecondPackageStructure(src3):
+    try: os.makedirs(pkgstructureBasedir2)
+    except: pass
+    writeFile(os.path.join(pkgstructureBasedir2, "__init__.py"), "#")
+    writeFile(pkgstructureFile3, src3)
+
+def removeSecondPackageStructure():
+    os.remove(os.path.join(pkgstructureBasedir2, "__init__.py"))
+    os.remove(pkgstructureFile3)
+    os.removedirs(pkgstructureBasedir2)
+
+
+
+def createAST(src):
+    from bike.parsing.load import getSourceNode
+    writeFile(tmpfile,src)
+    return getSourceNode(tmpfile)
+
+
+def createSourceNodeAt(src, fqn):
+    modname = fqn_rcar(fqn)
+    packagefqn = fqn_rcdr(fqn)
+    dirpath = os.path.join(*packagefqn.split("."))
+    filepath = os.path.join(dirpath,modname+".py")
+    try: os.makedirs(dirpath)
+    except: pass
+    dirsToDelete.append(dirpath)
+
+    # add the __init__.py files
+    path = "."
+    for pathelem in packagefqn.split("."):
+        path = os.path.join(path,pathelem)
+        initfile = os.path.join(path,"__init__.py")
+        writeFile(initfile,"#")
+        filesToDelete.append(initfile)
+    writeFile(filepath,src)
+    filesToDelete.append(filepath)
+    return getRoot()
+
+
+# takes the leading whitespace out of a multi line comment.
+# means you can imbed """
+#                     text like
+#                     this
+#                     """
+# in your code, and it will come out
+#"""text like
+#this"""
+def trimLines(src):
+    lines = src.splitlines(1)[1:]
+    tabwidth = re.match("\s*",lines[0]).end(0)
+    newlines = []
+    for line in lines:
+        if line == "\n" or line == "\r\n":
+            newlines.append(line)
+        else:
+            newlines.append(line[tabwidth:])
+    return "".join(newlines)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/WordRewriter.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,48 @@
+from bike.parsing.load import getSourceNode
+from bike.transformer.undo import getUndoStack
+from bike.transformer.save import queueFileToSave
+import re
+
+# This class maintains a set of changed lines to the original source
+# nodes. This is important because the act of changing a line messes
+# up the coordinates on which renames are done.
+# Commit writes the changes back to the source nodes
+class WordRewriter:
+    def __init__(self):
+        self.modifiedsrc = {}
+
+    def rewriteString(self, srcnode, lineno, colno, newname):
+        filename = srcnode.filename
+        if not self.modifiedsrc.has_key(filename):
+            getUndoStack().addSource(filename,srcnode.getSource())
+            self.modifiedsrc[filename] = {}
+        if not self.modifiedsrc[filename].has_key(lineno):
+            line = srcnode.getLines()[lineno-1]
+            self.modifiedsrc[filename][lineno] = self._lineToDict(line)
+        self.modifiedsrc[filename][lineno][colno] = newname
+
+
+    # writes all the changes back to the src nodes
+    def commit(self):
+        for filename in self.modifiedsrc.keys():
+            srcnode = getSourceNode(filename)
+            for lineno in self.modifiedsrc[filename]:
+                lines = srcnode.getLines()
+                lines[lineno-1] = self._dictToLine(self.modifiedsrc[filename][lineno])
+            queueFileToSave(filename,"".join(srcnode.getLines()))
+
+
+    # this function creates a dictionary with each word referenced by
+    # its column position in the original line
+    def _lineToDict(self, line):
+        words = re.split("(\w+)", line)
+        h = {};i = 0
+        for word in words:
+            h[i] = word
+            i+=len(word)
+        return h
+
+    def _dictToLine(self, d):
+        cols = d.keys()
+        cols.sort()
+        return "".join([d[colno]for colno in cols])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,4 @@
+"""
+Package containing modules which transform the internal
+representation of the sourcecode.
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/save.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,36 @@
+from bike import log
+
+outputqueue = {}
+
+def getQueuedFile(filename):
+    try:
+        return outputqueue[filename]
+    except:
+        pass
+        #print "HERE!"
+        
+
+def resetOutputQueue():
+    global outputqueue
+    outputqueue = {}
+
+def queueFileToSave(filename,src):
+    outputqueue[filename] = src
+    from bike.parsing.load import getSourceNode
+    getSourceNode(filename).resetWithSource(src)
+
+def save():
+    from bike.transformer.undo import getUndoStack
+
+    global outputqueue
+    savedFiles = []
+    for filename,src in outputqueue.iteritems():
+        print >> log.progress, "Writing:",filename
+        f = file(filename, "w+")
+        f.write(outputqueue[filename])
+        f.close()
+        savedFiles.append(filename)
+    outputqueue = {}
+    #print "stack is "+ str(getUndoStack().stack)
+    getUndoStack().commitUndoFrame()    
+    return savedFiles
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath(".."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+#from test_undo import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/transformer/undo.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,50 @@
+from bike import log
+from bike.transformer.save import queueFileToSave
+
+_undoStack = None
+
+def getUndoStack(forceNewStack = 0):
+    global _undoStack
+    if _undoStack is None or forceNewStack:
+        _undoStack = UndoStack()
+    return _undoStack
+
+class UndoStackEmptyException: pass
+
+class UndoStack(object):
+    def __init__(self):
+        self.stack = []
+        self.stack.append({})
+        self.frame = self.stack[-1]
+        self.setUndoBufferSize(10)
+
+    def setUndoBufferSize(self, undoBufferSize):
+        self.undoBufferSize = undoBufferSize
+
+    def addSource(self, filename, src):
+        if filename not in self.frame:
+            self.frame[filename] = src
+
+    def commitUndoFrame(self):
+        #restrict size of buffer
+        while len(self.stack) > self.undoBufferSize:
+            #print "clipping undo stack"
+            del self.stack[0]
+
+        if len(self.frame) != 0:
+            #print "commitUndoFrame"
+            self.stack.append({})
+            self.frame = self.stack[-1]
+
+    def undo(self, **opts):
+        #print "undo called",self.stack
+        if len(self.stack) < 2:
+            raise UndoStackEmptyException()
+        undoframe = self.stack[-2]
+        #print "undoframe is",undoframe
+        for filename,src in undoframe.iteritems():
+            print >>log.progress, "Undoing:",filename
+            queueFileToSave(filename,src)
+        self.stack = self.stack[:-2]
+        self.stack.append({})
+        self.frame = self.stack[-1]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/BicycleRepairMan_Idle.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,422 @@
+# bicycle repair man idle extension
+import bike
+from bike.transformer.undo import UndoStackEmptyException
+import bike.parsing.load
+import os
+from Tkinter import *
+import tkFileDialog
+import tkMessageBox
+import tkSimpleDialog
+import sys
+import string
+try:
+    from idlelib.PathBrowser import *
+    from idlelib.WindowList import ListedToplevel
+    from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas
+    from idlelib import EditorWindow
+    from idlelib.PyShell import PyShell
+    from idlelib.OutputWindow import OutputWindow
+    try:
+        from idlelib.configHandler import idleConf
+    except ImportError:
+        pass
+
+
+
+except ImportError:
+    from PathBrowser import*
+    from WindowList import ListedToplevel
+    from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
+    import EditorWindow
+    from PyShell import PyShell
+    from OutputWindow import OutputWindow
+    try:
+        from configHandler import idleConf
+    except ImportError:
+        pass
+
+brmctx = None
+shellwin = None
+loadingFiles = 0
+matchwin = None
+
+class NotHighlightedException(Exception):
+    pass
+
+class BicycleRepairMan_Idle:
+    menudefs = [
+    ('bicycleRepairMan', [
+        ('----- Queries -----',''),
+        ('_Find References','<<brm-find-references>>'),
+        ('_Find Definition','<<brm-find-definition>>'),
+        None,
+        ('--- Refactoring ---',''),
+        ('_Rename', '<<brm-rename>>'), 
+        ('_Extract Method', '<<brm-extract-method>>'), 
+        None,
+        ('_Undo', '<<brm-undo>>'), 
+        ])
+    ]
+
+    keydefs = {
+    '<<brm-find-references>>':[],
+    '<<brm-find-definition>>':[],
+    '<<brm-rename>>':[], 
+    '<<brm-extract-method>>':[], 
+    '<<brm-undo>>':[], 
+     }
+
+
+    try:
+        TRACE = idleConf.GetOption('extensions','BicycleRepairMan_Idle',
+                                        'trace',default=1)        
+    except NameError:   # hasnt imported idleconf - probably python 22
+        TRACE = 1
+
+
+    def __init__(self, editwin):
+        self.editwin = editwin
+        
+        if self.TRACE == 1:
+            self.progressLogger = ProgressLogger(self.editwin.flist)
+            
+        if not isinstance(editwin, PyShell):
+            # sly'ly add the refactor menu to the window
+            name, label = ("bicycleRepairMan", "_BicycleRepairMan")
+            underline, label = EditorWindow.prepstr(label)
+            mbar = editwin.menubar
+            editwin.menudict[name] = menu = Menu(mbar, name = name)
+            mbar.add_cascade(label = label, menu = menu, underline = underline)
+
+            # Initialize Bicyclerepairman and import the code
+            path = self.editwin.io.filename
+            if path is not None:
+                global brmctx
+                if brmctx is None:
+                    self.initbrm()
+        else:
+            global shellwin
+            shellwin = editwin
+
+
+    def initbrm(self):
+        global brmctx
+        brmctx = bike.init()
+        if self.TRACE == 1:
+            brmctx.setProgressLogger(self.progressLogger)
+        
+
+    def brm_find_references_event(self,event):
+        try:
+            if not self.confirm_all_buffers_saved():
+                return
+
+            if self.editwin.text.index("sel.first") == "":
+                self.errorbox("Not highlighted", "Highlight the name of a Function, Class or Method and try again")
+                return
+
+            filename = os.path.normpath(self.editwin.io.filename)
+            line, column = string.split(self.editwin.text.index("sel.first"),'.')
+
+            numMatches = 0
+            global matchwin
+            if matchwin is None:
+                matchwin = BRMMatchesWindow(self.editwin.flist, self)
+
+            matchwin.clear()
+
+            for ref in brmctx.findReferencesByCoordinates(filename,int(line),int(column)):
+                print >>matchwin, "File \""+ref.filename+"\", line "+str(ref.lineno)+", "+str(ref.confidence)+"% confidence"
+                numMatches +=1
+
+            print >>matchwin, numMatches," matches"
+            print >>matchwin, "(Hint: right-click to open locations.)"
+        except:
+            self._handleUnexpectedException()
+
+
+    def brm_find_definition_event(self,event):
+        try:
+            if not self.confirm_all_buffers_saved():
+                return
+            filename = os.path.normpath(self.editwin.io.filename)
+
+            if self.editwin.text.index("sel.first") != "":
+                line, column = string.split(self.editwin.text.index("sel.first"),'.')
+            else:
+                line, column = string.split(self.editwin.text.index("insert"), '.')
+
+
+            defns = brmctx.findDefinitionByCoordinates(filename,int(line),
+                                                       int(column))
+
+            try:
+                
+                firstref = defns.next()
+                
+                editwin = self.editwin.flist.open(firstref.filename)
+                editwin.gotoline(firstref.lineno)
+            except StopIteration:
+                self.errorbox("Couldn't Find definition","Couldn't Find definition")
+                pass
+            else:
+                numRefs = 1
+                global matchwin
+                if matchwin is None:
+                    matchwin = BRMMatchesWindow(self.editwin.flist, self)
+                    
+                for ref in defns:
+                    if numRefs == 1:
+                        print >>matchwin, firstref.filename+":"+str(firstref.lineno)+":    "+str(firstref.confidence)+"% confidence"
+
+                    numRefs += 1
+                    print >>matchwin,ref.filename+":"+str(ref.lineno)+":    "+str(ref.confidence)+"% confidence"
+                if matchwin is not None:
+                    print >>matchwin, "(Hint: right-click to open locations.)"
+                    
+        except:
+            self._handleUnexpectedException()
+
+
+    def brm_rename_event(self, event):
+        try:
+            self.renameItemByCoordinates()
+        except:
+            self._handleUnexpectedException()
+
+    def brm_extract_method_event(self, event):
+        try:
+            if not self.confirm_all_buffers_saved():
+                return
+            try:
+                filename, newname, beginline, begincolumn, endline, endcolumn = self._getExtractionInformation("Method")
+            except NotHighlightedException:
+                return
+            brmctx.extractMethod(filename, int(beginline), int(begincolumn), 
+                                 int(endline), int(endcolumn), newname)
+            savedfiles = brmctx.save()
+            self.refreshWindows(savedfiles, beginline)
+        except:
+            self._handleUnexpectedException()
+
+
+    def brm_undo_event(self, event):
+        try:
+            line, column = string.split(self.editwin.text.index("insert"), '.')
+            brmctx.undo()
+            savedfiles = brmctx.save()
+            self.refreshWindows(savedfiles, line)
+        except UndoStackEmptyException:
+            self.errorbox("Undo Stack Empty", "Undo Stack is empty")
+        except:
+            self._handleUnexpectedException()
+
+    def _handleUnexpectedException(self):
+        import traceback
+        traceback.print_exc()
+        self.errorbox("Caught Exception", "Caught Exception "+str(sys.exc_info()[0]))
+
+    def _getExtractionInformation(self, extracttype):
+        if self.editwin.text.index("sel.first") == "":
+            self.errorbox("Code not highlighted", "Highlight the region of code you want to extract and try again")
+            raise NotHighlightedException()
+        filename = os.path.normpath(self.editwin.io.filename)
+        newname = tkSimpleDialog.askstring("Extract Method ", 
+                                           "New "+extracttype+" Name:", 
+                                           parent = self.editwin.text)
+        beginline, begincolumn = string.split(self.editwin.text.index("sel.first"), '.')
+        endline, endcolumn = string.split(self.editwin.text.index("sel.last"), '.')
+        return filename, newname, beginline, begincolumn, endline, endcolumn
+
+
+    def renameMethodPromptCallback(self, filename, line, colbegin, colend):
+
+        editwin = self.editwin.flist.open(filename)
+        originaltop = self.editwin.getwindowlines()[0]
+
+        # select the method call and position the window
+        editwin.text.tag_remove("sel", "1.0", "end")
+        editwin.text.tag_add("sel", str(line)+"."+str(colbegin), 
+                                  str(line)+"."+str(colend))
+
+        line, column = string.split(editwin.text.index("sel.first"), '.')
+        editwin.text.yview(str(int(line)-2)+".0")
+
+
+        d = NoFocusDialog("Rename?", 
+                     "Cannot deduce the type of highlighted object reference.\nRename this declaration?", 
+                     parent = editwin.text)
+
+        # put the window back where it was
+        self.editwin.text.yview(float(originaltop))
+        return d.answer
+
+    def renameItemByCoordinates(self):
+        if not self.confirm_all_buffers_saved():
+            return
+        if self.editwin.text.index("sel.first") == "":
+            self.errorbox("Name not highlighted", "Double click the name of the declaration you want to rename (to highlight it) and try again")
+            return
+
+        brmctx.setRenameMethodPromptCallback(self.renameMethodPromptCallback)
+        line, column = string.split(self.editwin.text.index("sel.first"), '.')
+        filename = os.path.normpath(self.editwin.io.filename)
+        newname = tkSimpleDialog.askstring("Rename", 
+                                           "Rename to:", 
+                                           parent = self.editwin.text)
+        if newname is None: # cancel clicked
+            return
+        brmctx.renameByCoordinates(filename, int(line), int(column), newname)
+        savedfiles = brmctx.save()
+        self.refreshWindows(savedfiles, line)
+
+
+
+    def refreshWindows(self, savedfiles, line):
+        # refresh editor windows
+        oldtop = self.editwin.getwindowlines()[0]
+
+        global loadingFiles
+        loadingFiles = 1
+        for sf in savedfiles:
+            normsf = os.path.normcase(sf)
+            if normsf in self.editwin.flist.dict:
+                editwin = self.editwin.flist.dict[normsf]
+                editwin.io.loadfile(sf)
+        loadingFiles = 0
+
+        self.editwin.text.mark_set("insert", float(line))
+        self.editwin.text.yview(float(oldtop))
+
+
+
+    def confirm_all_buffers_saved(self):
+        filelist = self.editwin.flist.dict.keys()
+        for f in filelist:
+            #editwin = self.editwin.flist.open(f)
+            editwin = self.editwin.flist.dict[f]
+            if self.confirm_buffer_is_saved(editwin) == 0:
+                return 0
+        return 1
+
+
+    def confirm_buffer_is_saved(self, editwin):
+        if not editwin.get_saved():
+            name = (editwin.short_title()or
+            editwin.long_title()or
+            "Untitled")
+            reply = tkMessageBox.askokcancel("Bicycle Repair Man",
+                "The buffer for %s is not saved.\n\n"%name+
+                "Save it and continue?",
+                master = self.editwin.text)
+          &nbs p; self.editwin.text.focus_set()
+            if reply:
+                editwin.io.save(None)
+            else:
+                return 0
+        return 1
+
+    def errorbox(self, title, message):
+        tkMessageBox.showerror(title, message, master = self.editwin.text)
+        self.editwin.text.focus_set()
+
+
+class BRMTraceWindow(OutputWindow):
+    def short_title(self):
+        return "BicycleRepairMan Trace"
+
+class ProgressLogger:
+    def __init__(self,flist):
+        self.flist = flist
+
+    def write(self,txt):
+        if not hasattr(self,"io"):
+            self.io = BRMTraceWindow(self.flist)
+        try:
+            self.io.write(txt)
+            self.io.flush()
+        except IOError:
+            pass
+
+        
+class NoFocusDialog(tkSimpleDialog._QueryDialog):
+    def __init__(self, title, prompt, 
+                 initialvalue = None, 
+                 minvalue = None, maxvalue = None, 
+                 parent = None):
+        self.answer = 0
+
+        if not parent:
+            import Tkinter
+            parent = Tkinter._default_root
+
+        self.prompt = prompt
+        self.minvalue = minvalue
+        self.maxvalue = maxvalue
+
+        self.initialvalue = initialvalue
+
+        Toplevel.__init__(self, parent)
+
+        if title:
+            self.title(title)
+
+        self.parent = parent
+
+        self.result = None
+
+        body = Frame(self)
+        self.initial_focus = self.body(body)
+        body.pack(padx = 5, pady = 5)
+
+        self.buttonbox()
+
+        self.grab_set()
+
+        self.protocol("WM_DELETE_WINDOW", self.cancel)
+
+        if self.parent is not None:
+            self.geometry("+%d+%d"%(parent.winfo_rootx()+50, 
+                                      parent.winfo_rooty()+50))
+        self.wait_window(self)
+
+
+    def getresult(self):
+        self.answer = 1
+
+    def body(self, master):
+        w = Label(master, text = self.prompt, justify = LEFT)
+        w.grid(row = 0, padx = 5, sticky = W)
+
+    def buttonbox(self):
+        box = Frame(self)
+
+        w = Button(box, text = "Yes", width = 10, command = self.ok, default = ACTIVE)
+        w.pack(side = LEFT, padx = 5, pady = 5)
+        w = Button(box, text = "No", width = 10, command = self.cancel)
+        w.pack(side = LEFT, padx = 5, pady = 5)
+
+        self.bind("<Return>", self.ok)
+        self.bind("<Escape>", self.cancel)
+        box.pack()
+
+
+
+
+
+class BRMMatchesWindow(OutputWindow):
+    def __init__(self,flist,masterwin):
+        OutputWindow.__init__(self,flist)
+        self.masterwin = masterwin
+
+    def close(self):
+        global matchwin
+        matchwin = None
+        OutputWindow.close(self)
+
+    def short_title(self):
+        return "BicycleRepairMan Matches"
+    
+    def clear(self):
+        self.text.delete("1.0","end-1c")
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,417 @@
+2002-11-23  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.20.
+
+	* Pymacs/__init__.py: Integrate version.py.
+	* Pymacs/version.py: Deleted.
+	* setup.py, Pymacs/pymacs.py: Adjusted.
+
+2002-11-15  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-python-reference): Handle when function is
+	defined as a mere variable, or when a function is being advised.
+
+2002-11-14  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.19.
+
+	* Pymacs/pymacs.py (List.__getitem__): Raise IndexError when
+	out of bounds.  This should allow for iterating over a list.
+
+	* README.html: New, merely a template for Webert.
+
+2002-11-13  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-call): New.  Use it whenever adequate.
+
+2002-09-26  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Makefile (publish): Revised.
+
+2002-08-18  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.18.
+
+2002-08-09  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py (Emacs_Rebox.find_comment): Correctly spell
+	backward_char, not backward-char.
+
+2002-08-08  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py (pymacs_load_hook): Compute the interactions
+	map from the bound methods, instead of from the generic ones.
+
+2002-07-14  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/pymacs.py (Lisp_Interface.__call__): Wrap argument in
+	progn, so lisp() could accept a sequence of expressions.
+
+2002-07-01  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-start-services): Disable undo for *Pymacs*.
+
+2002-06-25  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.17.
+
+	* pymacs.py: Deleted, this was the compatibility module.
+	* setup: Simplified to handle the Emacs Lisp part only.
+	Deleted -P, -p and -x, as well as compile_python.
+
+	* Makefile: Adjusted.  Removed pythondir and pymacsdir.
+	* pymacs.el (pymacs-load-path): Merely preset to nil.
+
+	* setup: Changes for easing installation on Win32.
+	Reported by Syver Enstad.
+
+	* Pymacs/pymacs.py (print_lisp): Produce Emacs strings more
+	explicitly, avoiding hexadecimal sequences generated by Python
+	2.2.  Those hexadecimal sequences confused Emacs when immediately
+	followed by more hexadecimal looking characters.
+
+2002-01-30  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-load-path): Initialise with pymacsdir.
+	* pymacs-services: Do not handle a patched pymacsdir anymore.
+	* setup (complete_install): Set pymacsdir for Lisp, not Python.
+	Do not accept a -b option anymore, do not install pymacs-services,
+	as this is now to be done through setup.py.
+	* Makefile (install): Do not use -b while calling setup.
+
+2002-01-29  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.16.
+
+	* Pymacs/pymacs.py: New file, previously top-level.
+	* pymacs.py: Now a mere bootstrap for Pymacs/pymacs.py.
+	* Pymacs/__init__.py: Define lisp and Let.
+	* Makefile (pythondir): Documentation amended.
+	* setup: Distinguish between empty arguments, which ask for
+	autoconfiguration, and None arguments, which inhibit it.
+	* pymacs-services: Import pymacs from Pymacs.
+
+	* Pymacs/version.py: New file.  Rename pymacs to Pymacs.
+	* setup, setup.py, Pymacs/pymacs.py (main): Use it.
+
+	* setup: Substitute None for pymacsdir instead of the empty string.
+	* pymacs-services: Adjusted.
+
+	* Pymacs/pymacs.py (Let): Have all push_* methods to return self.
+
+2002-01-20  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el, pymacs.el: Replace LISP by Lisp in comments.
+	Reported by Paul Foley.
+
+2002-01-10  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.15.
+
+	* pymacs.el (pymacs-start-services): Properly diagnose a timeout,
+	using the timeout parameter value instead of a fixed string.
+
+2002-01-07  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.14.
+
+	* pymacs.py: Set various __repr__() to yield Python code,
+	containing the corresponding expanded LISP expression.
+	Set various __str__() to yield mutable LISP code.
+
+	* pymacs.py (Let): Point markers to nowhere once done with them.
+
+2002-01-06  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.13.
+
+	* pymacs.el (pymacs-load): Imply prefix correctly when the module
+	is part of a package, that is, when its name has at least one dot.
+	* pymacs.py (pymacs_load_helper): Idem.
+
+	* pymacs.py (Protocol): New name for Server.
+
+	* pymacs.py (pymacs_load_helper): Implement pymacs_load_hook.
+
+	* MANIFEST.in, setup.py, Pymacs/__init__.py: New files.
+	* Makefile: Adjusted and simplified.
+
+2002-01-03  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (pymacs_load_helper): Handle module within package.
+	Reported by Syver Enstad.
+
+2001-12-18  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.bat: New file.
+
+2001-11-29  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.12.
+
+	* pymacs.el (pymacs-timeout-at-start, pymacs-timeout-at-reply,
+	pymacs-timeout-at-line): New variables.  Use them.
+
+2001-10-17  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (pymacs_load_helper): Check the function attribute
+	before the interactions dictionary, for people having Python 2.x.
+	Reported by Carel Fellinger.
+
+	* pymacs.el, pymacs.py, pymacs-services: Add the usual GPL notices.
+	Reported by Richard Stallman.
+
+2001-10-16  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.11.
+
+	* pymacs.el (pymacs-defuns): Accept interaction specifications.
+	(pymacs-defun): Process an interaction specification.
+	(pymacs-python-reference): Adjust for interactive functions.
+	* pymacs.py (pymacs_load_helper): Transmit interaction specifications.
+	Reported by Christian Tanzer and Stefan Reichör.
+
+2001-10-15  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (pymacs_load_helper): Accept dashed module names.
+	Reported by Stefan Reichör.
+
+	* pymacs.el (pymacs-python-reference): Rewrite, as it was broken.
+	(documentation): Say it is a Python function, even if no docstring.
+	Reported by Stefan Reichör.
+
+2001-10-12  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.10.
+
+	* pymacs.el (pymacs-print-for-eval): Handle multi-line strings.
+	Reported by Dave Sellars.
+
+	* pymacs.el (pymacs-print-for-eval): Remove string text properties.
+	Reported by Eli Zaretskii.
+
+2001-10-06  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (Let.__nonzero__): New.
+
+2001-09-28  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.9.
+
+2001-09-26  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (Let.push): Save the value of the symbol, not the
+	symbol itself.
+
+2001-09-25  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.8.
+
+	* pymacs.py (Let): New class.
+
+	* pymacs.el: New variable pymacs-use-hash-tables, set to t when
+	hash tables are available, or nil otherwise.  Use it.  This is so
+	older Emacs would work.
+	Reported by Dirk Vleugels.
+
+2001-09-21  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-defun): Ensure the function is registered
+	at definition, not at call time.  Otherwise, it would never be
+	garbage-collected if it is never called.
+
+2001-09-20  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.7.
+
+	* pymacs.el (pymacs-print-for-apply): Also accept Python objects
+	for a function, instead of requiring strings.
+	(pymacs-defun): Use a Python object, not an explicit string reference.
+	(pymacs-python): Merge pymacs-save-index.
+	(pymacs-save-index): Deleted.
+
+2001-09-18  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-load): Accept a noerror argument.
+
+2001-09-17  François Pinard  <pinard@iro.umontreal.ca>
+
+	* setup: New script.
+	* Makefile: Use it.
+
+	* pymacs.py (Symbol.set): Make things simpler when value is None.
+
+	* pymacs.el (pymacs-print-for-eval): Use Python lists to represent
+	LISP proper lists and Python tuples to represent LISP vectors,
+	instead of the other way around.
+	* pymacs.py (pymacs_load_helper, print_lisp): Similar changes.
+	Reported by John Wiegley.
+
+2001-09-16  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.6.
+
+	* pymacs.el (pymacs-start-services, pymacs-print-for-eval,
+	pymacs-round-trip): Protect match data.
+
+2001-09-15  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (documentation): Completed.  Now into service.
+	(pymacs-documentation): Deleted.
+	(pymacs-python-reference): New.
+
+	* pymacs.el (pymacs-print-for-eval): Use car-safe.
+
+2001-09-14  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-print-for-eval): replace-regexp-in-string does
+	not exist in older Emacs versions, so use paraphrases.
+	Reported by Carey Evans.
+
+	* pymacs.el (pymacs-start-services): Set pymacs-transit-buffer
+	permanently only at end of the function, in case anything fails.
+	Reported by Carey Evans.
+
+2001-09-13  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.5.
+
+	* pymacs.el (documentation, pymacs-documentation): New, experimental.
+	* pymacs.py (doc_string): New.
+	(pymacs_load_helper): The result should evaluate to the module.
+
+2001-09-12  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.py (pymacs_load_helper): Use reload instead of __import__
+	whenever the module was already loaded.
+
+	* pymacs.py (pymacs_load_helper): Return t when there is nothing
+	to define, instead of returning a noisy pymacs-defuns noop.
+
+	* Makefile (dist): Update a version-less symbolic link.
+
+	* pymacs.el (pymacs-python, pymacs-defun): New functions.
+	(pymacs-defuns): Use pymacs-defun.
+	* pymacs.py (print_lisp): Use the above.
+
+	* pymacs.py (Server): Free all accumulated LISP indices, while
+	replying for another reason.  This should decrease overhead.
+	(Lisp.__del__): Delay freeing LISP, do not free one index at a time.
+	* pymacs.el (pymacs-free-lisp): Free many indices at once.
+
+	* pymacs.el (pymacs-start-services, pymacs-round-trip): Recognise
+	reply even when not at beginning of line.  The Python module may
+	print incomplete lines, unrelated to the communication protocol.
+
+2001-09-11  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.4.
+
+	* pymacs.py (zombie): New, so to get a clear diagnostic.
+	(zombie_python): Link objects to the above function.
+	* pymacs.el (pymacs-terminate-services): Ask for confirmation if
+	any object in LISP space is still in use on the Python side.
+	* pymacs-test.el (try-lisp): Do not terminate the helper.
+
+	* pymacs.py (Buffer): New class, yet empty for now.
+	* pymacs.el (pymacs-print-for-eval): Use it.
+	Reported by Brian McErlean.
+
+	* pymacs.py (Table): New class.
+	* pymacs.el (pymacs-print-for-eval): Use it.
+	Reported by Brian McErlean.
+
+	* pymacs.py (List, Vector): New classes, split out of Lisp class.
+	* pymacs.el (pymacs-print-for-eval): Use them.
+	(pymacs-lisp-length, pymacs-lisp-ref, pymacs-list-set):	Deleted.
+	Reported by Brian McErlean.
+
+	* pymacs.py (Server.loop): Allow keyboard interrupts through.
+
+	* pymacs.el: Use Lisp instead of Handle.  Rename
+	pymacs-handle-length to pymacs-lisp-length, pymacs-handle-ref to
+	pymacs-lisp-ref, pymacs-handle-set o pymacs-lisp-set,
+	pymacs-allocate-handle to pymacs-allocate-lisp and
+	pymacs-free-handle to pymacs-free-lisp.
+
+	* pymacs.py: Rename Lisp to Lisp_Interface, and Handle to Lisp.
+	Adjust for other renamings above.
+
+	* pymacs.el: Rename pymacs-id to pymacs-python.  Ajust for below.
+	* pymacs.py: Rename handles to python, free_handles to
+	free_python, zombie_handles to zombie_python and allocate_handle
+	to allocate_python.
+
+	* pymacs.el (pymacs-proper-list-p): New function.  Use it
+	everywhere instead of listp, which is not what I thought it was!
+
+	* pymacs.el (pymacs-serve-until-reply): In case of LISP error,
+	transmit a list of one argument, instead of the argument itself,
+	to print-for-apply.  This was preventing proper diagnostic.
+	Correct a similar error for when expansion is requested.
+
+	* pymacs.el (pymacs-print-for-eval):  Do not transmit a symbol
+	by its name, when it comes from another oblist than the main one.
+
+	* pymacs.py (print_lisp): Transmit pymacs-id as a dotted pair.
+	* pymacs.el (pymacs-print-for-eval):  Adjusted.
+
+	* pymacs.el (pymacs-print-for-eval): Use lisp[], not sym[].
+	Avoid double escaping of the transmitted string in this case.
+	Reported by Brian McErlean.
+
+2001-09-10  François Pinard  <pinard@iro.umontreal.ca>
+
+	* : Release 0.3.
+
+	* pymacs.py (Server.send): Ensure an end of line after reply.
+	* pymacs.el (pymacs-round-trip): Do not add one after Python replies.
+
+	* pymacs.el (pymacs-round-trip): Check for vanishing helper process.
+	(pymacs-serve-until-reply): Get text without catching errors, than
+	eval. Else, protocol errors get reported back to Python.
+	* pymacs.py (Server.ProtocolError): New.  Better than AssertError.
+	If it occurs, get out of program, do not keep returning errors.
+	Reported by Carey Evans.
+
+	* pymacs.el (pymacs-round-trip): If point coincides with marker,
+	just keep it that way as the buffer grows.
+
+	* pymacs.el (pymacs-start-services): If the hash table already
+	exists, inform the Python side of IDs that it should not reuse.
+	Otherwise, old lambdas may randomly refer to new Python objects.
+	(pymacs-terminate-services): Remember Python IDs, do not reset them.
+
+	* pymacs.py (zombie_handles): New.
+
+	* Makefile: Transmit $(pymacsdir) to pymacs-services.
+	* pymacs-services: Handle it.
+
+	* pymacs.py (print_lisp): Process an empty tuple properly.
+	Reported by Carey Evans.
+
+	* pymacs.el (pymacs-start-services): With run-at-time, use `20 20'
+	instead of `t 20', so XEmacs is happy.
+	Reported by Carey Evans.
+
+	* pymacs.el (pymacs-start-services, pymacs-terminate-services):
+	Use `post-gc-hook' if available, instead of using a timer.
+	Reported by Gerd Möllman.
+
+	* pymacs.py (Symbol.value, Symbol.copy): Add argument self.
+	(print_lisp): Quote symbols if quoted=1.
+
+2001-09-09  François Pinard  <pinard@iro.umontreal.ca>
+
+	* pymacs.el (pymacs-defuns): New function.
+	* pymacs.py: Use it.  This should allow faster imports.
+
+	* Makefile, pymacs.el, pymacs.py: Use `(pymacs-version VERSION)',
+	not `(started)'.  Check for version discrepancies.
+
+	* Makefile: A bit more parameterization.
+
+	* : Release 0.2, including ideas and suggestions from others.
+	Reported by Brian McErlean, Carel Fellinger, Cedric Adjih,
+	Marcin Qrczak Kowalczyk, Paul Winkler and Steffen Ries.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog-rebox	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,146 @@
+2002-01-29  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py: Use an interactions map instead of the
+	interaction attribute, so it works with earlier Python versions.
+
+	* Pymacs/rebox.py: Import lisp and Let from Pymacs.
+
+2002-01-13  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py (Emacs_Rebox.emacs_engine): Expand flag value,
+	when it is neither the - symbol nor a number.
+
+2002-01-08  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py (Template.build): Subtract margin from width
+	just before actually rebuilding the box.
+	Reported by Paul Provost.
+
+2002-01-07  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py (main): Implement -v option.
+
+	* Pymacs/rebox.py (pymacs_load_hook): Declare set_default_style.
+
+	* Pymacs/rebox.py (Emacs_Rebox.clean_undo_after): Debugged.
+
+	* Pymacs/rebox.py (Template): New class.  Reorgnise all code.
+	* Pymacs/rebox.py (engine): Moved out of Rebox class.
+	* Pymacs/rebox.py (Rebox, Batch_Rebox): Deleted, as they got empty.
+
+	* Pymacs/rebox.py (Emacs_Rebox.clean_undo_after): Rewrite in LISP.
+
+2002-01-06  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox: New file.
+
+2002-01-03  François Pinard  <pinard@iro.umontreal.ca>
+
+	* Pymacs/rebox.py: New file, translated from Libit/rebox.el.
+
+2000-09-28  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Replace statistical heuristics for box style recognition
+	by more precise checks and explicit priorities between styles.  To do
+	so, add weights to rebox-templates, replace rebox-building-data	by
+	rebox-style-data holding regexps, delete rebox-recognition-data.
+
+	* rebox.el (rebox-regexp-ruler): New function.
+	(rebox-regexp-quote): Add matching for following white space.
+	Don't force two characters on each middle line, nor in blank rulers.
+	Reported by Paul Provost.
+
+2000-04-28  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-guess-style): When two styles have equal weight,
+	retain the highest numbered, as it probably is the richest.
+	Otherwise, simple C++ comments end up with a single slash.
+	Reported by Akim Demaille.
+
+2000-04-19  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Reorganize from bottom-up into top-down.
+	(taarna-mode): Deleted.
+
+2000-04-18  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-show-style, rebox-help-string-for-language,
+	rebox-help-string-for-quality, rebox-help-string-for-type): Deleted.
+	(rebox-rstrip, rebox-regexp-quote, rebox-unbuild): New functions.
+	(rebox-build): New name for rebox-reconstruct.
+
+2000-04-15  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-guess-style): New function.
+	(rebox-engine): Use it.  Simplified by using template information.
+
+2000-04-14  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-templates): New variable.
+	(rebox-register-template): New function.
+	(rebox-reconstruct): Much simplified by using the above.
+
+2000-04-12  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Rework the initial documentation block.
+	(rebox-reconstruct): Guarantee newline at end for style 241.
+	Reported by Marc Feeley and Paul Provost.
+
+2000-02-22  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Little speed cleanup.  Avoid looking-at when easy.
+
+2000-02-10  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Adjust comment to suggest add-hook instead of setq.
+	Reported by Akim Demaille.
+
+2000-01-30  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Prefer when, unless and cond over if and progn.
+	Combine successive setq.
+
+	* rebox.el (rebox-engine): Recognise quality for shell boxes.
+	Reported by Akim Demaille.
+
+1999-06-30  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Add GPL comment.
+	Reported by Paul Eggert.
+
+1998-03-28  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-reconstruct): Refill a closing */ with the rest.
+	Do not add spaces to a line which is otherwise empty.
+
+1997-12-01  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-engine): Simplify two regexps, for XEmacs.
+	Reported by Ulrich Drepper.
+
+1997-02-17  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-reconstruct): Ensure indent-tabs-mode is nil.
+
+1997-02-14  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Corrected a bug demonstrated as the beginning line
+	of a paragraph spuriously jumping right spuriously.  The full
+	match of the beginning of comment was replaced by spaces on the
+	initial line, while only \1 needed replacement.  This shortened
+	this line, causing later nasty effects.
+
+1996-07-10  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Recognise style 241, so margin does not get doubled.
+	Reported by Marc Feeley.
+
+1996-07-09  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el: Use symbolic constants for language, quality and type.
+
+1996-06-09  François Pinard  <pinard@iro.umontreal.ca>
+
+	* rebox.el (rebox-find-and-narrow): Take care of a missing end of
+	line after a comment being at end of buffer.
+	Reported by Ulrich Drepper.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/Makefile	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,40 @@
+# Interface between Emacs LISP and Python - Makefile.
+# Copyright İ 2001, 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+# The `README' file provides a few good hints about installation.
+
+### Start of customisation.
+#
+# Somewhere on your Emacs LISP load-path.
+lispdir =
+#
+### End of customisation.
+
+PYSETUP = python setup.py
+DISTRIBUTION := $(shell ./setup -V)
+
+all:
+	$(PYSETUP) build
+
+install: all
+	@./setup -l '$(lispdir)'
+	$(PYSETUP) install
+
+tags:
+	(find bin -type f; find -name '*.py') | grep -v '~$$' | etags -
+
+dist:
+	$(PYSETUP) sdist
+	mv dist/$(DISTRIBUTION).tar.gz .
+	rmdir dist
+	ls -l *.gz
+
+publish: dist
+	traiter README.html > index.html
+	chmod 644 index.html $(DISTRIBUTION).tar.gz
+	scp -p index.html $(DISTRIBUTION).tar.gz bor:w/pymacs/
+	rm index.html $(DISTRIBUTION).tar.gz
+	ssh bor rm -vf w/pymacs/Pymacs.tar.gz
+	ssh bor ln -vs $(DISTRIBUTION).tar.gz w/pymacs/Pymacs.tar.gz
+	ssh bor ls -Llt w/pymacs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/PKG-INFO	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: Pymacs
+Version: 0.20
+Summary: Interface between Emacs LISP and Python.
+Home-page: http://www.iro.umontreal.ca/~pinard
+Author: François Pinard
+Author-email: pinard@iro.umontreal.ca
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/.cvsignore	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# Copyright İ 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2002.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+"""\
+Interface between Emacs Lisp and Python - Module initialisation.
+
+A few symbols are moved in here so they appear to be defined at this level.
+"""
+
+from pymacs import Let, lisp
+
+# Identification of version.
+
+package = 'Pymacs'
+version = '0.20'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/pymacs.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,587 @@
+#!/usr/bin/env python
+# Copyright İ 2001, 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+"""\
+Interface between Emacs Lisp and Python - Python part.
+
+Emacs may launch this module as a stand-alone program, in which case it
+acts as a server of Python facilities for that Emacs session, reading
+requests from standard input and writing replies on standard output.
+
+This module may also be usefully imported by those other Python modules.
+See the Pymacs documentation (in `README') for more information.
+"""
+
+## Note: This code is currently compatible down to Python version 1.5.2.
+## It is probably worth keeping it that way for a good while, still.
+
+import os, string, sys, types
+
+# Python services for Emacs applications.
+
+def main(*arguments):
+    """\
+Execute Python services for Emacs, and Emacs services for Python.
+This program is meant to be called from Emacs, using `pymacs.el'.
+
+The program arguments are additional search paths for Python modules.
+"""
+    from Pymacs import version
+    arguments = list(arguments)
+    arguments.reverse()
+    for argument in arguments:
+        if os.path.isdir(argument):
+            sys.path.insert(0, argument)
+    lisp._protocol.send('(pymacs-version "%s")' % version)
+    lisp._protocol.loop()
+
+class Protocol:
+
+    # FIXME: The following should work, but does not:
+    #
+    # * pymacs.py (Protocol): Declare exceptions as classes, not strings.
+    #
+    #class ProtocolError(Exception): pass
+    #class ReplyException(Exception): pass
+    #class ErrorException(Exception): pass
+    #
+    # I get:
+    #    (pymacs-eval "lisp('\"abc\"').__class__.__name__")
+    #    "ReplyException"
+
+    ProtocolError = 'ProtocolError'
+    ReplyException = 'ReplyException'
+    ErrorException = 'ErrorException'
+
+    def __init__(self):
+        self.freed = []
+
+    def loop(self):
+        # The server loop repeatedly receives a request from Emacs and
+        # returns a response, which is either the value of the received
+        # Python expression, or the Python traceback if an error occurs
+        # while evaluating the expression.
+
+        # The server loop may also be executed, as a recursive invocation,
+        # in the context of Emacs serving a Python request.  In which
+        # case, we might also receive a notification from Emacs telling
+        # that the reply has been transmitted, or that an error occurred.
+        # A reply notification from Emacs interrupts the loop: the result
+        # of this function is the value returned from Emacs.
+        while 1:
+            try:
+                text = self.receive()
+                if text[:5] == 'exec ':
+                    exec eval(text[5:], {}, {})
+                    status = 'reply'
+                    argument = None
+                else:
+                    status = 'reply'
+                    argument = eval(text)
+            except Protocol.ReplyException, value:
+                return value
+            except Protocol.ErrorException, message:
+                status = 'error'
+                argument = message
+            except Protocol.ProtocolError, message:
+                sys.stderr.write("Protocol error: %s\n" % message)
+                sys.exit(1)
+            except KeyboardInterrupt:
+                raise
+            except:
+                import StringIO, traceback
+                message = StringIO.StringIO()
+                traceback.print_exc(file=message)
+                status = 'error'
+                argument = message.getvalue()
+            # Send an expression to EMACS applying FUNCTION over ARGUMENT,
+            # where FUNCTION is `pymacs-STATUS'.
+            fragments = []
+            write = fragments.append
+            if self.freed:
+                write('(progn (pymacs-free-lisp')
+                for index in self.freed:
+                    write(' %d' % index)
+                write(') ')
+            write('(pymacs-%s ' % status)
+            print_lisp(argument, write, quoted=1)
+            write(')')
+            if self.freed:
+                write(')')
+                self.freed = []
+            self.send(string.join(fragments, ''))
+
+    def receive(self):
+        # Receive a Python expression from Emacs, return its text unevaluated.
+        text = sys.stdin.read(3)
+        if not text or text[0] != '>':
+            raise Protocol.ProtocolError, "`>' expected."
+        while text[-1] != '\t':
+            text = text + sys.stdin.read(1)
+        return sys.stdin.read(int(text[1:-1]))
+
+    def send(self, text):
+        # Send TEXT to Emacs, which is an expression to evaluate.
+        if text[-1] == '\n':
+            sys.stdout.write('<%d\t%s' % (len(text), text))
+        else:
+            sys.stdout.write('<%d\t%s\n' % (len(text) + 1, text))
+        sys.stdout.flush()
+
+def reply(value):
+    # This function implements the `reply' pseudo-function.
+    raise Protocol.ReplyException, value
+
+def error(message):
+    # This function implements the `error' pseudo-function.
+    raise Protocol.ErrorException, "Emacs: %s" % message
+
+def pymacs_load_helper(file_without_extension, prefix):
+    # This function imports a Python module, then returns a Lisp expression
+    # which, when later evaluated, will install trampoline definitions in
+    # Emacs for accessing the Python module facilities.  MODULE may be a
+    # full path, yet without the `.py' or `.pyc' extension, in which case
+    # the directory is temporarily added to the Python search path for
+    # the sole duration of that import.  All defined symbols on the Lisp
+    # side have have PREFIX prepended, and have Python underlines in Python
+    # turned into dashes.  If PREFIX is None, it then defaults to the base
+    # name of MODULE with underlines turned to dashes, followed by a dash.
+    directory, module_name = os.path.split(file_without_extension)
+    module_components = string.split(module_name, '.')
+    if prefix is None:
+        prefix = string.replace(module_components[-1], '_', '-') + '-'
+    try:
+        object = sys.modules.get(module_name)
+        if object:
+            reload(object)
+        else:
+            try:
+                if directory:
+                    sys.path.insert(0, directory)
+                object = __import__(module_name)
+            finally:
+                if directory:
+                    del sys.path[0]
+            # Whenever MODULE_NAME is of the form [PACKAGE.]...MODULE,
+            # __import__ returns the outer PACKAGE, not the module.
+            for component in module_components[1:]:
+                object = getattr(object, component)
+    except ImportError:
+        return None
+    load_hook = object.__dict__.get('pymacs_load_hook')
+    if load_hook:
+        load_hook()
+    interactions = object.__dict__.get('interactions', {})
+    if type(interactions) != types.DictType:
+        interactions = {}
+    arguments = []
+    for name, value in object.__dict__.items():
+        if callable(value) and value is not lisp:
+            arguments.append(allocate_python(value))
+            arguments.append(lisp[prefix + string.replace(name, '_', '-')])
+            try:
+                interaction = value.interaction
+            except AttributeError:
+                interaction = interactions.get(value)
+            if callable(interaction):
+                arguments.append(allocate_python(interaction))
+            else:
+                arguments.append(interaction)
+    if arguments:
+        return [lisp.progn,
+                [lisp.pymacs_defuns, [lisp.quote, arguments]],
+                object]
+    return [lisp.quote, object]
+
+def doc_string(object):
+    if hasattr(object, '__doc__'):
+        return object.__doc__
+
+# Garbage collection matters.
+
+# Many Python types do not have direct Lisp equivalents, and may not be
+# directly returned to Lisp for this reason.  They are rather allocated in
+# a list of handles, below, and a handle index is used for communication
+# instead of the Python value.  Whenever such a handle is freed from the
+# Lisp side, its index is added of a freed list for later reuse.
+
+python = []
+freed_list = []
+
+def allocate_python(value):
+    assert type(value) != type(''), (type(value), `value`)
+    # Allocate some handle to hold VALUE, return its index.
+    if freed_list:
+        index = freed_list[-1]
+        del freed_list[-1]
+        python[index] = value
+    else:
+        index = len(python)
+        python.append(value)
+    return index
+
+def free_python(*indices):
+    # Return many handles to the pool.
+    for index in indices:
+        python[index] = None
+        freed_list.append(index)
+
+def zombie_python(*indices):
+    # Ensure that some handles are _not_ in the pool.
+    for index in indices:
+        while index >= len(python):
+            freed_list.append(len(python))
+            python.append(None)
+        python[index] = zombie
+        freed_list.remove(index)
+    # Merely to make `*Pymacs*' a bit more readable.
+    freed_list.sort()
+
+def zombie(*arguments):
+    error("Object vanished when helper was killed.")
+
+# Emacs services for Python applications.
+
+class Let:
+
+    def __init__(self, **keywords):
+        self.stack = []
+        apply(self.push, (), keywords)
+
+    def __del__(self):
+        while self.stack:
+            method = self.stack[-1][0]
+            if method == 'variables':
+                self.pop()
+            elif method == 'excursion':
+                self.pop_excursion()
+            elif method == 'match_data':
+                self.pop_match_data()
+            elif method == 'restriction':
+                self.pop_restriction()
+            elif method == 'selected_window':
+                self.pop_selected_window()
+            elif method == 'window_excursion':
+                self.pop_window_excursion()
+
+    def __nonzero__(self):
+        # So stylistic `if let:' executes faster.
+        return 1
+
+    def push(self, **keywords):
+        pairs = []
+        for name, value in keywords.items():
+            pairs.append((name, getattr(lisp, name).value()))
+            setattr(lisp, name, value)
+        self.stack.append(('variables', pairs))
+        return self
+
+    def pop(self):
+        method, pairs = self.stack[-1]
+        assert method == 'variables', self.stack[-1]
+        del self.stack[-1]
+        for name, value in pairs:
+            setattr(lisp, name, value)
+
+    def push_excursion(self):
+        self.stack.append(('excursion',
+                           (lisp.current_buffer(),
+                            lisp.point_marker(), lisp.mark_marker())))
+        return self
+
+    def pop_excursion(self):
+        method, (buffer, point_marker, mark_marker) = self.stack[-1]
+        assert method == 'excursion', self.stack[-1]
+        del self.stack[-1]
+        lisp.set_buffer(buffer)
+        lisp.goto_char(point_marker)
+        lisp.set_mark(mark_marker)
+        lisp.set_marker(point_marker, None)
+        lisp.set_marker(mark_marker, None)
+
+    def push_match_data(self):
+        self.stack.append(('match_data', lisp.match_data()))
+        return self
+
+    def pop_match_data(self):
+        method, match_data = self.stack[-1]
+        assert method == 'match_data', self.stack[-1]
+        del self.stack[-1]
+        lisp.set_match_data(match_data)
+
+    def push_restriction(self):
+        self.stack.append(('restriction',
+                           (lisp.point_min_marker(), lisp.point_max_marker())))
+        return self
+
+    def pop_restriction(self):
+        method, (point_min_marker, point_max_marker) = self.stack[-1]
+        assert method == 'restriction', self.stack[-1]
+        del self.stack[-1]
+        lisp.narrow_to_region(point_min_marker, point_max_marker)
+        lisp.set_marker(point_min_marker, None)
+        lisp.set_marker(point_max_marker, None)
+
+    def push_selected_window(self):
+        self.stack.append(('selected_window', lisp.selected_window()))
+        return self
+
+    def pop_selected_window(self):
+        method, selected_window = self.stack[-1]
+        assert method == 'selected_window', self.stack[-1]
+        del self.stack[-1]
+        lisp.select_window(selected_window)
+
+    def push_window_excursion(self):
+        self.stack.append(('window_excursion',
+                           lisp.current_window_configuration()))
+        return self
+
+    def pop_window_excursion(self):
+        method, current_window_configuration = self.stack[-1]
+        assert method == 'window_excursion', self.stack[-1]
+        del self.stack[-1]
+        lisp.set_window_configuration(current_window_configuration)
+
+class Symbol:
+
+    def __init__(self, text):
+        self.text = text
+
+    def __repr__(self):
+        return 'lisp[%s]' % repr(self.text)
+
+    def __str__(self):
+        return '\'' + self.text
+
+    def value(self):
+        return lisp(self.text)
+
+    def copy(self):
+        return lisp('(pymacs-expand %s)' % self.text)
+
+    def set(self, value):
+        if value is None:
+            lisp('(setq %s nil)' % self.text)
+        else:
+            fragments = []
+            write = fragments.append
+            write('(progn (setq %s ' % self.text)
+            print_lisp(value, write, quoted=1)
+            write(') nil)')
+            lisp(string.join(fragments, ''))
+
+    def __call__(self, *arguments):
+        fragments = []
+        write = fragments.append
+        write('(%s' % self.text)
+        for argument in arguments:
+            write(' ')
+            print_lisp(argument, write, quoted=1)
+        write(')')
+        return lisp(string.join(fragments, ''))
+
+class Lisp:
+
+    def __init__(self, index):
+        self.index = index
+
+    def __del__(self):
+        lisp._protocol.freed.append(self.index)
+
+    def __repr__(self):
+        return ('lisp(%s)' % repr(lisp('(prin1-to-string %s)' % self)))
+
+    def __str__(self):
+        return '(aref pymacs-lisp %d)' % self.index
+
+    def value(self):
+        return self
+
+    def copy(self):
+        return lisp('(pymacs-expand %s)' % self)
+
+class Buffer(Lisp):
+    pass
+
+    #def write(text):
+    #    # So you could do things like
+    #    # print >>lisp.current_buffer(), "Hello World"
+    #    lisp.insert(text, self)
+
+    #def point(self):
+    #    return lisp.point(self)
+
+class List(Lisp):
+
+    def __call__(self, *arguments):
+        fragments = []
+        write = fragments.append
+        write('(%s' % self)
+        for argument in arguments:
+            write(' ')
+            print_lisp(argument, write, quoted=1)
+        write(')')
+        return lisp(string.join(fragments, ''))
+
+    def __len__(self):
+        return lisp('(length %s)' % self)
+
+    def __getitem__(self, key):
+        value = lisp('(nth %d %s)' % (key, self))
+        if value is None and key >= len(self):
+            raise IndexError, key
+        return value
+
+    def __setitem__(self, key, value):
+        fragments = []
+        write = fragments.append
+        write('(setcar (nthcdr %d %s) ' % (key, self))
+        print_lisp(value, write, quoted=1)
+        write(')')
+        lisp(string.join(fragments, ''))
+
+class Table(Lisp):
+
+    def __getitem__(self, key):
+        fragments = []
+        write = fragments.append
+        write('(gethash ')
+        print_lisp(key, write, quoted=1)
+        write(' %s)' % self)
+        return lisp(string.join(fragments, ''))
+
+    def __setitem__(self, key, value):
+        fragments = []
+        write = fragments.append
+        write('(puthash ')
+        print_lisp(key, write, quoted=1)
+        write(' ')
+        print_lisp(value, write, quoted=1)
+        write(' %s)' % self)
+        lisp(string.join(fragments, ''))
+
+class Vector(Lisp):
+
+    def __len__(self):
+        return lisp('(length %s)' % self)
+
+    def __getitem__(self, key):
+        return lisp('(aref %s %d)' % (self, key))
+
+    def __setitem__(self, key, value):
+        fragments = []
+        write = fragments.append
+        write('(aset %s %d ' % (self, key))
+        print_lisp(value, write, quoted=1)
+        write(')')
+        lisp(string.join(fragments, ''))
+
+class Lisp_Interface:
+
+    def __init__(self):
+        self.__dict__['_cache'] = {'nil': None}
+        self.__dict__['_protocol'] = Protocol()
+
+    def __call__(self, text):
+        self._protocol.send('(progn %s)' % text)
+        return self._protocol.loop()
+
+    def __getattr__(self, name):
+        if name[0] == '_':
+            raise AttributeError, name
+        return self[string.replace(name, '_', '-')]
+
+    def __setattr__(self, name, value):
+        if name[0] == '_':
+            raise AttributeError, name
+        self[string.replace(name, '_', '-')] = value
+
+    def __getitem__(self, name):
+        try:
+            return self._cache[name]
+        except KeyError:
+            symbol = self._cache[name] = Symbol(name)
+            return symbol
+
+    def __setitem__(self, name, value):
+        try:
+            symbol = self._cache[name]
+        except KeyError:
+            symbol = self._cache[name] = Symbol(name)
+        symbol.set(value)
+
+lisp = Lisp_Interface()
+
+print_lisp_quoted_specials = {'"': '\\"', '\\': '\\\\', '\b': '\\b',
+                              '\f': '\\f', '\n': '\\n', '\t': '\\t'}
+
+def print_lisp(value, write, quoted=0):
+    if value is None:
+        write('nil')
+    elif type(value) == types.IntType:
+        write(repr(value))
+    elif type(value) == types.FloatType:
+        write(repr(value))
+    elif type(value) == types.StringType:
+        write('"')
+        for character in value:
+            special = print_lisp_quoted_specials.get(character)
+            if special is not None:
+                write(special)
+            elif 32 <= ord(character) < 127:
+                write(character)
+            else:
+                write('\\%.3o' % ord(character))
+        write('"')
+    elif type(value) == types.ListType:
+        if quoted:
+            write("'")
+        if len(value) == 0:
+            write('nil')
+        elif len(value) == 2 and value[0] == lisp.quote:
+            write("'")
+            print_lisp(value[1], write)
+        else:
+            write('(')
+            print_lisp(value[0], write)
+            for sub_value in value[1:]:
+                write(' ')
+                print_lisp(sub_value, write)
+            write(')')
+    elif type(value) == types.TupleType:
+        write('[')
+        if len(value) > 0:
+            print_lisp(value[0], write)
+            for sub_value in value[1:]:
+                write(' ')
+                print_lisp(sub_value, write)
+        write(']')
+    elif isinstance(value, Lisp):
+        write(str(value))
+    elif isinstance(value, Symbol):
+        if quoted:
+            write("'")
+        write(value.text)
+    elif callable(value):
+        write('(pymacs-defun %d)' % allocate_python(value))
+    else:
+        write('(pymacs-python %d)' % allocate_python(value))
+
+if __name__ == '__main__':
+    apply(main, sys.argv[1:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/rebox.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1235 @@
+#!/usr/bin/env python
+# Copyright İ 1991-1998, 2000, 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, April 1991.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""\
+Handling of boxed comments in various box styles.
+
+Introduction
+------------
+
+For comments held within boxes, it is painful to fill paragraphs, while
+stretching or shrinking the surrounding box "by hand", as needed.  This piece
+of Python code eases my life on this.  It may be used interactively from
+within Emacs through the Pymacs interface, or in batch as a script which
+filters a single region to be reformatted.  I find only fair, while giving
+all sources for a package using such boxed comments, to also give the
+means I use for nicely modifying comments.  So here they are!
+
+Box styles
+----------
+
+Each supported box style has a number associated with it.  This number is
+arbitrary, yet by _convention_, it holds three non-zero digits such the the
+hundreds digit roughly represents the programming language, the tens digit
+roughly represents a box quality (or weight) and the units digit roughly
+a box type (or figure).  An unboxed comment is merely one of box styles.
+Language, quality and types are collectively referred to as style attributes.
+
+When rebuilding a boxed comment, attributes are selected independently
+of each other.  They may be specified by the digits of the value given
+as Emacs commands argument prefix, or as the `-s' argument to the `rebox'
+script when called from the shell.  If there is no such prefix, or if the
+corresponding digit is zero, the attribute is taken from the value of the
+default style instead.  If the corresponding digit of the default style
+is also zero, than the attribute is recognised and taken from the actual
+boxed comment, as it existed before prior to the command.  The value 1,
+which is the simplest attribute, is ultimately taken if the parsing fails.
+
+A programming language is associated with comment delimiters.  Values are
+100 for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for `//'
+as in C++, 400 for `#' as in most scripting languages, 500 for `;' as in
+LISP or assembler and 600 for `%' as in TeX or PostScript.
+
+Box quality differs according to language. For unknown languages (100) or
+for the C language (200), values are 10 for simple, 20 for rounded, and
+30 or 40 for starred.  Simple quality boxes (10) use comment delimiters
+to left and right of each comment line, and also for the top or bottom
+line when applicable. Rounded quality boxes (20) try to suggest rounded
+corners in boxes.  Starred quality boxes (40) mostly use a left margin of
+asterisks or X'es, and use them also in box surroundings.  For all others
+languages, box quality indicates the thickness in characters of the left
+and right sides of the box: values are 10, 20, 30 or 40 for 1, 2, 3 or 4
+characters wide.  With C++, quality 10 is not useful, it is not allowed.
+
+Box type values are 1 for fully opened boxes for which boxing is done
+only for the left and right but not for top or bottom, 2 for half
+single lined boxes for which boxing is done on all sides except top,
+3 for fully single lined boxes for which boxing is done on all sides,
+4 for half double lined boxes which is like type 2 but more bold,
+or 5 for fully double lined boxes which is like type 3 but more bold.
+
+The special style 221 is for C comments between a single opening `/*'
+and a single closing `*/'.  The special style 111 deletes a box.
+
+Batch usage
+-----------
+
+Usage is `rebox [OPTION]... [FILE]'.  By default, FILE is reformatted to
+standard output by refilling the comment up to column 79, while preserving
+existing boxed comment style.  If FILE is not given, standard input is read.
+Options may be:
+
+  -n         Do not refill the comment inside its box, and ignore -w.
+  -s STYLE   Replace box style according to STYLE, as explained above.
+  -t         Replace initial sequence of spaces by TABs on each line.
+  -v         Echo both the old and the new box styles on standard error.
+  -w WIDTH   Try to avoid going over WIDTH columns per line.
+
+So, a single boxed comment is reformatted by invocation.  `vi' users, for
+example, would need to delimit the boxed comment first, before executing
+the `!}rebox' command (is this correct? my `vi' recollection is far away).
+
+Batch usage is also slow, as internal structures have to be reinitialised
+at every call.  Producing a box in a single style is fast, but recognising
+the previous style requires setting up for all possible styles.
+
+Emacs usage
+-----------
+
+For most Emacs language editing modes, refilling does not make sense
+outside comments, one may redefine the `M-q' command and link it to this
+Pymacs module.  For example, I use this in my `.emacs' file:
+
+     (add-hook 'c-mode-hook 'fp-c-mode-routine)
+     (defun fp-c-mode-routine ()
+       (local-set-key "\M-q" 'rebox-comment))
+     (autoload 'rebox-comment "rebox" nil t)
+     (autoload 'rebox-region "rebox" nil t)
+
+with a "rebox.el" file having this single line:
+
+     (pymacs-load "Pymacs.rebox")
+
+Install Pymacs from `http://www.iro.umontreal.ca/~pinard/pymacs.tar.gz'.
+
+The Emacs function `rebox-comment' automatically discovers the extent of
+the boxed comment near the cursor, possibly refills the text, then adjusts
+the box style.  When this command is executed, the cursor should be within
+a comment, or else it should be between two comments, in which case the
+command applies to the next comment.  The function `rebox-region' does
+the same, except that it takes the current region as a boxed comment.
+Both commands obey numeric prefixes to add or remove a box, force a
+particular box style, or to prevent refilling of text.  Without such
+prefixes, the commands may deduce the current box style from the comment
+itself so the style is preserved.
+
+The default style initial value is nil or 0.  It may be preset to another
+value through calling `rebox-set-default-style' from Emacs LISP, or changed
+to anything else though using a negative value for a prefix, in which case
+the default style is set to the absolute value of the prefix.
+
+A `C-u' prefix avoids refilling the text, but forces using the default box
+style.  `C-u -' lets the user interact to select one attribute at a time.
+
+Adding new styles
+-----------------
+
+Let's suppose you want to add your own boxed comment style, say:
+
+    //--------------------------------------------+
+    // This is the style mandated in our company.
+    //--------------------------------------------+
+
+You might modify `rebox.py' but then, you will have to edit it whenever you
+get a new release of `pybox.py'.  Emacs users might modify their `.emacs'
+file or their `rebox.el' bootstrap, if they use one.  In either cases,
+after the `(pymacs-load "Pymacs.rebox")' line, merely add:
+
+    (rebox-Template NNN MMM ["//-----+"
+                             "// box  "
+                             "//-----+"])
+
+If you use the `rebox' script rather than Emacs, the simplest is to make
+your own.  This is easy, as it is very small.  For example, the above
+style could be implemented by using this script instead of `rebox':
+
+    #!/usr/bin/env python
+    import sys
+    from Pymacs import rebox
+    rebox.Template(226, 325, ('//-----+',
+                              '// box  ',
+                              '//-----+'))
+    apply(rebox.main, tuple(sys.argv[1:]))
+
+In all cases, NNN is the style three-digit number, with no zero digit.
+Pick any free style number, you are safe with 911 and up.  MMM is the
+recognition priority, only used to disambiguate the style of a given boxed
+comments, when it matches many styles at once.  Try something like 400.
+Raise or lower that number as needed if you observe false matches.
+
+On average, the template uses three lines of equal length.  Do not worry if
+this implies a few trailing spaces, they will be cleaned up automatically
+at box generation time.  The first line or the third line may be omitted
+to create vertically opened boxes.  But the middle line may not be omitted,
+it ought to include the word `box', which will get replaced by your actual
+comment.  If the first line is shorter than the middle one, it gets merged
+at the start of the comment.  If the last line is shorter than the middle
+one, it gets merged at the end of the comment and is refilled with it.
+
+History
+-------
+
+I first observed rounded corners, as in style 223 boxes, in code from
+Warren Tucker, a previous maintainer of the `shar' package, circa 1980.
+
+Except for very special files, I carefully avoided boxed comments for
+real work, as I found them much too hard to maintain.  My friend Paul
+Provost was working at Taarna, a computer graphics place, which had boxes
+as part of their coding standards.  He asked that we try something to get
+him out of his misery, and this how `rebox.el' was originally written.
+I did not plan to use it for myself, but Paul was so enthusiastic that I
+timidly started to use boxes in my things, very little at first, but more
+and more as time passed, still in doubt that it was a good move.  Later,
+many friends spontaneously started to use this tool for real, some being very
+serious workers.  This convinced me that boxes are acceptable, after all.
+
+I do not use boxes much with Python code.  It is so legible that boxing
+is not that useful.  Vertical white space is less necessary, too.  I even
+avoid white lines within functions.  Comments appear prominent enough when
+using highlighting editors like Emacs or nice printer tools like `enscript'.
+
+After Emacs could be extended with Python, in 2001, I translated `rebox.el'
+into `rebox.py', and added the facility to use it as a batch script.
+"""
+
+## Note: This code is currently compatible down to Python version 1.5.2.
+## It is probably worth keeping it that way for a good while, still.
+
+## Note: a double hash comment introduces a group of functions or methods.
+
+import re, string, sys
+
+def main(*arguments):
+    refill = 1
+    style = None
+    tabify = 0
+    verbose = 0
+    width = 79
+    import getopt
+    options, arguments = getopt.getopt(arguments, 'ns:tvw:', ['help'])
+    for option, value in options:
+        if option == '--help':
+            sys.stdout.write(__doc__)
+            sys.exit(0)
+        elif option == '-n':
+            refill = 0
+        elif option == '-s':
+            style = int(value)
+        elif option == '-t':
+            tabify = 1
+        elif option == '-v':
+            verbose = 1
+        elif option == '-w':
+            width = int(value)
+    if len(arguments) == 0:
+        text = sys.stdin.read()
+    elif len(arguments) == 1:
+        text = open(arguments[0]).read()
+    else:
+        sys.stderr.write("Invalid usage, try `rebox --help' for help.\n")
+        sys.exit(1)
+    old_style, new_style, text, position = engine(
+        text, style=style, width=width, refill=refill, tabify=tabify)
+    if text is None:
+        sys.stderr.write("* Cannot rebox to style %d.\n" % new_style)
+        sys.exit(1)
+    sys.stdout.write(text)
+    if verbose:
+        if old_style == new_style:
+            sys.stderr.write("Reboxed with style %d.\n" % old_style)
+        else:
+            sys.stderr.write("Reboxed from style %d to %d.\n"
+                             % (old_style, new_style))
+
+def pymacs_load_hook():
+    global interactions, lisp, Let, region, comment, set_default_style
+    from Pymacs import lisp, Let
+    emacs_rebox = Emacs_Rebox()
+    # Declare functions for Emacs to import.
+    interactions = {}
+    region = emacs_rebox.region
+    interactions[region] = 'P'
+    comment = emacs_rebox.comment
+    interactions[comment] = 'P'
+    set_default_style = emacs_rebox.set_default_style
+
+class Emacs_Rebox:
+
+    def __init__(self):
+        self.default_style = None
+
+    def set_default_style(self, style):
+        """\
+Set the default style to STYLE.
+"""
+        self.default_style = style
+
+    def region(self, flag):
+        """\
+Rebox the boxed comment in the current region, obeying FLAG.
+"""
+        self.emacs_engine(flag, self.find_region)
+
+    def comment(self, flag):
+        """\
+Rebox the surrounding boxed comment, obeying FLAG.
+"""
+        self.emacs_engine(flag, self.find_comment)
+
+    def emacs_engine(self, flag, find_limits):
+        """\
+Rebox text while obeying FLAG.  Call FIND_LIMITS to discover the extent
+of the boxed comment.
+"""
+        # `C-u -' means that box style is to be decided interactively.
+        if flag == lisp['-']:
+            flag = self.ask_for_style()
+        # If FLAG is zero or negative, only change default box style.
+        if type(flag) is type(0) and flag <= 0:
+            self.default_style = -flag
+            lisp.message("Default style set to %d" % -flag)
+            return
+        # Decide box style and refilling.
+        if flag is None:
+            style = self.default_style
+            refill = 1
+        elif type(flag) == type(0):
+            if self.default_style is None:
+                style = flag
+            else:
+                style = merge_styles(self.default_style, flag)
+            refill = 1
+        else:
+            flag = flag.copy()
+            if type(flag) == type([]):
+                style = self.default_style
+                refill = 0
+            else:
+                lisp.error("Unexpected flag value %s" % flag)
+        # Prepare for reboxing.
+        lisp.message("Reboxing...")
+        checkpoint = lisp.buffer_undo_list.value()
+        start, end = find_limits()
+        text = lisp.buffer_substring(start, end)
+        width = lisp.fill_column.value()
+        tabify = lisp.indent_tabs_mode.value() is not None
+        point = lisp.point()
+        if start <= point < end:
+            position = point - start
+        else:
+            position = None
+        # Rebox the text and replace it in Emacs buffer.
+        old_style, new_style, text, position = engine(
+            text, style=style, width=width,
+            refill=refill, tabify=tabify, position=position)
+        if text is None:
+            lisp.error("Cannot rebox to style %d" % new_style)
+        lisp.delete_region(start, end)
+        lisp.insert(text)
+        if position is not None:
+            lisp.goto_char(start + position)
+        # Collapse all operations into a single one, for Undo.
+        self.clean_undo_after(checkpoint)
+        # We are finished, tell the user.
+        if old_style == new_style:
+            lisp.message("Reboxed with style %d" % old_style)
+        else:
+            lisp.message("Reboxed from style %d to %d"
+                         % (old_style, new_style))
+
+    def ask_for_style(self):
+        """\
+Request the style interactively, using the minibuffer.
+"""
+        language = quality = type = None
+        while language is None:
+            lisp.message("\
+Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
+            key = lisp.read_char()
+            if key >= ord('0') and key <= ord('6'):
+                language = key - ord('0')
+        while quality is None:
+            lisp.message("\
+Box quality/width is 10-simple/1, 20-rounded/2, 30-starred/3 or 40-starred/4")
+            key = lisp.read_char()
+            if key >= ord('0') and key <= ord('4'):
+                quality = key - ord('0')
+        while type is None:
+            lisp.message("\
+Box type is 1-opened, 2-half-single, 3-single, 4-half-double or 5-double")
+            key = lisp.read_char()
+            if key >= ord('0') and key <= ord('5'):
+                type = key - ord('0')
+        return 100*language + 10*quality + type
+
+    def find_region(self):
+        """\
+Return the limits of the region.
+"""
+        return lisp.point(), lisp.mark(lisp.t)
+
+    def find_comment(self):
+        """\
+Find and return the limits of the block of comments following or enclosing
+the cursor, or return an error if the cursor is not within such a block
+of comments.  Extend it as far as possible in both directions.
+"""
+        let = Let()
+        let.push_excursion()
+        # Find the start of the current or immediately following comment.
+        lisp.beginning_of_line()
+        lisp.skip_chars_forward(' \t\n')
+        lisp.beginning_of_line()
+        if not language_matcher[0](self.remainder_of_line()):
+            temp = lisp.point()
+            if not lisp.re_search_forward('\\*/', None, lisp.t):
+                lisp.error("outside any comment block")
+            lisp.re_search_backward('/\\*')
+            if lisp.point() > temp:
+                lisp.error("outside any comment block")
+            temp = lisp.point()
+            lisp.beginning_of_line()
+            lisp.skip_chars_forward(' \t')
+            if lisp.point() != temp:
+                lisp.error("text before start of comment")
+            lisp.beginning_of_line()
+        start = lisp.point()
+        language = guess_language(self.remainder_of_line())
+        # Find the end of this comment.
+        if language == 2:
+            lisp.search_forward('*/')
+            if not lisp.looking_at('[ \t]*$'):
+                lisp.error("text after end of comment")
+        lisp.end_of_line()
+        if lisp.eobp():
+            lisp.insert('\n')
+        else:
+            lisp.forward_char(1)
+        end = lisp.point()
+        # Try to extend the comment block backwards.
+        lisp.goto_char(start)
+        while not lisp.bobp():
+            if language == 2:
+                lisp.skip_chars_backward(' \t\n')
+                if not lisp.looking_at('[ \t]*\n[ \t]*/\\*'):
+                    break
+                if lisp.point() < 2:
+                    break
+                lisp.backward_char(2)
+                if not lisp.looking_at('\\*/'):
+                    break
+                lisp.re_search_backward('/\\*')
+                temp = lisp.point()
+                lisp.beginning_of_line()
+                lisp.skip_chars_forward(' \t')
+                if lisp.point() != temp:
+                    break
+                lisp.beginning_of_line()
+            else:
+                lisp.previous_line(1)
+                if not language_matcher[language](self.remainder_of_line()):
+                    break
+            start = lisp.point()
+        # Try to extend the comment block forward.
+        lisp.goto_char(end)
+        while language_matcher[language](self.remainder_of_line()):
+            if language == 2:
+                lisp.re_search_forward('[ \t]*/\\*')
+                lisp.re_search_forward('\\*/')
+                if lisp.looking_at('[ \t]*$'):
+                    lisp.beginning_of_line()
+                    lisp.forward_line(1)
+                    end = lisp.point()
+            else:
+                lisp.forward_line(1)
+                end = lisp.point()
+        return start, end
+
+    def remainder_of_line(self):
+        """\
+Return all characters between point and end of line in Emacs buffer.
+"""
+        return lisp('''\
+(buffer-substring (point) (save-excursion (skip-chars-forward "^\n") (point)))
+''')
+
+    def clean_undo_after_old(self, checkpoint):
+        """\
+Remove all intermediate boundaries from the Undo list since CHECKPOINT.
+"""
+        # Declare some LISP functions.
+        car = lisp.car
+        cdr = lisp.cdr
+        eq = lisp.eq
+        setcdr = lisp.setcdr
+        # Remove any `nil' delimiter recently added to the Undo list.
+        cursor = lisp.buffer_undo_list.value()
+        if not eq(cursor, checkpoint):
+            tail = cdr(cursor)
+            while not eq(tail, checkpoint):
+                if car(tail):
+                    cursor = tail
+                    tail = cdr(cursor)
+                else:
+                    tail = cdr(tail)
+                    setcdr(cursor, tail)
+
+    def clean_undo_after(self, checkpoint):
+        """\
+Remove all intermediate boundaries from the Undo list since CHECKPOINT.
+"""
+        lisp("""
+(let ((undo-list %s))
+  (if (not (eq buffer-undo-list undo-list))
+      (let ((cursor buffer-undo-list))
+	(while (not (eq (cdr cursor) undo-list))
+	  (if (car (cdr cursor))
+	      (setq cursor (cdr cursor))
+	    (setcdr cursor (cdr (cdr cursor)))))))
+  nil)
+"""
+             % (checkpoint or 'nil'))
+
+def engine(text, style=None, width=79, refill=1, tabify=0, position=None):
+    """\
+Add, delete or adjust a boxed comment held in TEXT, according to STYLE.
+STYLE values are explained at beginning of this file.  Any zero attribute
+in STYLE indicates that the corresponding attribute should be recovered
+from the currently existing box.  Produced lines will not go over WIDTH
+columns if possible, if refilling gets done.  But if REFILL is false, WIDTH
+is ignored.  If TABIFY is true, the beginning of produced lines will have
+spaces replace by TABs.  POSITION is either None, or a character position
+within TEXT.  Returns four values: the old box style, the new box style,
+the reformatted text, and either None or the adjusted value of POSITION in
+the new text.  The reformatted text is returned as None if the requested
+style does not exist.
+"""
+    last_line_complete = text and text[-1] == '\n'
+    if last_line_complete:
+        text = text[:-1]
+    lines = string.split(string.expandtabs(text), '\n')
+    # Decide about refilling and the box style to use.
+    new_style = 111
+    old_template = guess_template(lines)
+    new_style = merge_styles(new_style, old_template.style)
+    if style is not None:
+        new_style = merge_styles(new_style, style)
+    new_template = template_registry.get(new_style)
+    # Interrupt processing if STYLE does not exist.
+    if not new_template:
+        return old_template.style, new_style, None, None
+    # Remove all previous comment marks, and left margin.
+    if position is not None:
+        marker = Marker()
+        marker.save_position(text, position, old_template.characters())
+    lines, margin = old_template.unbuild(lines)
+    # Ensure only one white line between paragraphs.
+    counter = 1
+    while counter < len(lines) - 1:
+        if lines[counter] == '' and lines[counter-1] == '':
+            del lines[counter]
+        else:
+            counter = counter + 1
+    # Rebuild the boxed comment.
+    lines = new_template.build(lines, width, refill, margin)
+    # Retabify to the left only.
+    if tabify:
+        for counter in range(len(lines)):
+            tabs = len(re.match(' *', lines[counter]).group()) / 8
+            lines[counter] = '\t' * tabs + lines[counter][8*tabs:]
+    # Restore the point position.
+    text = string.join(lines, '\n')
+    if last_line_complete:
+        text = text + '\n'
+    if position is not None:
+        position = marker.get_position(text, new_template.characters())
+    return old_template.style, new_style, text, position
+
+def guess_language(line):
+    """\
+Guess the language in use for LINE.
+"""
+    for language in range(len(language_matcher) - 1, 1, -1):
+        if language_matcher[language](line):
+            return language
+    return 1
+
+def guess_template(lines):
+    """\
+Find the heaviest box template matching LINES.
+"""
+    best_template = None
+    for template in template_registry.values():
+        if best_template is None or template > best_template:
+            if template.match(lines):
+                best_template = template
+    return best_template
+
+def left_margin_size(lines):
+    """\
+Return the width of the left margin for all LINES.  Ignore white lines.
+"""
+    margin = None
+    for line in lines:
+        counter = len(re.match(' *', line).group())
+        if counter != len(line):
+            if margin is None or counter < margin:
+                margin = counter
+    if margin is None:
+        margin = 0
+    return margin
+
+def merge_styles(original, update):
+    """\
+Return style attributes as per ORIGINAL, in which attributes have been
+overridden by non-zero corresponding style attributes from UPDATE.
+"""
+    style = [original / 100, original / 10 % 10, original % 10]
+    merge = update / 100, update / 10 % 10, update % 10
+    for counter in range(3):
+        if merge[counter]:
+            style[counter] = merge[counter]
+    return 100*style[0] + 10*style[1] + style[2]
+
+def refill_lines(lines, width):
+    """\
+Refill LINES, trying to not produce lines having more than WIDTH columns.
+"""
+    # Try using GNU `fmt'.
+    import tempfile, os
+    name = tempfile.mktemp()
+    open(name, 'w').write(string.join(lines, '\n') + '\n')
+    process = os.popen('fmt -cuw %d %s' % (width, name))
+    text = process.read()
+    os.remove(name)
+    if process.close() is None:
+        return map(string.expandtabs, string.split(text, '\n')[:-1])
+    # If `fmt' failed, do refilling more naively, wihtout using the
+    # Knuth algorithm, nor protecting full stops at end of sentences.
+    lines.append(None)
+    new_lines = []
+    new_line = ''
+    start = 0
+    for end in range(len(lines)):
+        if not lines[end]:
+            margin = left_margin_size(lines[start:end])
+            for line in lines[start:end]:
+                counter = len(re.match(' *', line).group())
+                if counter > margin:
+                    if new_line:
+                        new_lines.append(' ' * margin + new_line)
+                        new_line = ''
+                    indent = counter - margin
+                else:
+                    indent = 0
+                for word in string.split(line):
+                    if new_line:
+                        if len(new_line) + 1 + len(word) > width:
+                            new_lines.append(' ' * margin + new_line)
+                            new_line = word
+                        else:
+                            new_line = new_line + ' ' + word
+                    else:
+                        new_line = ' ' * indent + word
+                        indent = 0
+            if new_line:
+                new_lines.append(' ' * margin + new_line)
+                new_line = ''
+            if lines[end] is not None:
+                new_lines.append('')
+                start = end + 1
+    return new_lines
+
+class Marker:
+
+    ## Heuristic to simulate a marker while reformatting boxes.
+
+    def save_position(self, text, position, ignorable):
+        """\
+Given a TEXT and a POSITION in that text, save the adjusted position
+by faking that all IGNORABLE characters before POSITION were removed.
+"""
+        ignore = {}
+        for character in ' \t\r\n' + ignorable:
+            ignore[character] = None
+        counter = 0
+        for character in text[:position]:
+            if ignore.has_key(character):
+                counter = counter + 1
+        self.position = position - counter
+
+    def get_position(self, text, ignorable, latest=0):
+        """\
+Given a TEXT, return the value that would yield the currently saved position,
+if it was saved by `save_position' with IGNORABLE.  Unless the position lies
+within a series of ignorable characters, LATEST has no effect in practice.
+If LATEST is true, return the biggest possible value instead of the smallest.
+"""
+        ignore = {}
+        for character in ' \t\r\n' + ignorable:
+            ignore[character] = None
+        counter = 0
+        position = 0
+        if latest:
+            for character in text:
+                if ignore.has_key(character):
+                    counter = counter + 1
+                else:
+                    if position == self.position:
+                        break
+                    position = position + 1
+        elif self.position > 0:
+            for character in text:
+                if ignore.has_key(character):
+                    counter = counter + 1
+                else:
+                    position = position + 1
+                    if position == self.position:
+                        break
+        return position + counter
+
+## Template processing.
+
+class Template:
+
+    def __init__(self, style, weight, lines):
+        """\
+Digest and register a single template.  The template is numbered STYLE,
+has a parsing WEIGHT, and is described by one to three LINES.
+STYLE should be used only once through all `declare_template' calls.
+
+One of the lines should contain the substring `box' to represent the comment
+to be boxed, and if three lines are given, `box' should appear in the middle
+one.  Lines containing only spaces are implied as necessary before and after
+the the `box' line, so we have three lines.
+
+Normally, all three template lines should be of the same length.  If the first
+line is shorter, it represents a start comment string to be bundled within the
+first line of the comment text.  If the third line is shorter, it represents
+an end comment string to be bundled at the end of the comment text, and
+refilled with it.
+"""
+        assert not template_registry.has_key(style), \
+               "Style %d defined more than once" % style
+        self.style = style
+        self.weight = weight
+        # Make it exactly three lines, with `box' in the middle.
+        start = string.find(lines[0], 'box')
+        if start >= 0:
+            line1 = None
+            line2 = lines[0]
+            if len(lines) > 1:
+                line3 = lines[1]
+            else:
+                line3 = None
+        else:
+            start = string.find(lines[1], 'box')
+            if start >= 0:
+                line1 = lines[0]
+                line2 = lines[1]
+                if len(lines) > 2:
+                    line3 = lines[2]
+                else:
+                    line3 = None
+            else:
+                assert 0, "Erroneous template for %d style" % style
+        end = start + len('box')
+        # Define a few booleans.
+        self.merge_nw = line1 is not None and len(line1) < len(line2)
+        self.merge_se = line3 is not None and len(line3) < len(line2)
+        # Define strings at various cardinal directions.
+        if line1 is None:
+            self.nw = self.nn = self.ne = None
+        elif self.merge_nw:
+            self.nw = line1
+            self.nn = self.ne = None
+        else:
+            if start > 0:
+                self.nw = line1[:start]
+            else:
+                self.nw = None
+            if line1[start] != ' ':
+                self.nn = line1[start]
+            else:
+                self.nn = None
+            if end < len(line1):
+                self.ne = string.rstrip(line1[end:])
+            else:
+                self.ne = None
+        if start > 0:
+            self.ww = line2[:start]
+        else:
+            self.ww = None
+        if end < len(line2):
+            self.ee = line2[end:]
+        else:
+            self.ee = None
+        if line3 is None:
+            self.sw = self.ss = self.se = None
+        elif self.merge_se:
+            self.sw = self.ss = None
+            self.se = string.rstrip(line3)
+        else:
+            if start > 0:
+                self.sw = line3[:start]
+            else:
+                self.sw = None
+            if line3[start] != ' ':
+                self.ss = line3[start]
+            else:
+                self.ss = None
+            if end < len(line3):
+                self.se = string.rstrip(line3[end:])
+            else:
+                self.se = None
+        # Define parsing regexps.
+        if self.merge_nw:
+            self.regexp1 = re.compile(' *' + regexp_quote(self.nw) + '.*$')
+        elif self.nw and not self.nn and not self.ne:
+            self.regexp1 = re.compile(' *' + regexp_quote(self.nw) + '$')
+        elif self.nw or self.nn or self.ne:
+            self.regexp1 = re.compile(
+                ' *' + regexp_quote(self.nw) + regexp_ruler(self.nn)
+                + regexp_quote(self.ne) + '$')
+        else:
+            self.regexp1 = None
+        if self.ww or self.ee:
+            self.regexp2 = re.compile(
+                ' *' + regexp_quote(self.ww) + '.*'
+                + regexp_quote(self.ee) + '$')
+        else:
+            self.regexp2 = None
+        if self.merge_se:
+            self.regexp3 = re.compile('.*' + regexp_quote(self.se) + '$')
+        elif self.sw and not self.ss and not self.se:
+            self.regexp3 = re.compile(' *' + regexp_quote(self.sw) + '$')
+        elif self.sw or self.ss or self.se:
+            self.regexp3 = re.compile(
+                ' *' + regexp_quote(self.sw) + regexp_ruler(self.ss)
+                + regexp_quote(self.se) + '$')
+        else:
+            self.regexp3 = None
+        # Save results.
+        template_registry[style] = self
+
+    def __cmp__(self, other):
+        return cmp(self.weight, other.weight)
+
+    def characters(self):
+        """\
+Return a string of characters which may be used to draw the box.
+"""
+        characters = ''
+        for text in (self.nw, self.nn, self.ne,
+                     self.ww, self.ee,
+                     self.sw, self.ss, self.se):
+            if text:
+                for character in text:
+                    if character not in characters:
+                        characters = characters + character
+        return characters
+
+    def match(self, lines):
+        """\
+Returns true if LINES exactly match this template.
+"""
+        start = 0
+        end = len(lines)
+        if self.regexp1 is not None:
+            if start == end or not self.regexp1.match(lines[start]):
+                return 0
+            start = start + 1
+        if self.regexp3 is not None:
+            if end == 0 or not self.regexp3.match(lines[end-1]):
+                return 0
+            end = end - 1
+        if self.regexp2 is not None:
+            for line in lines[start:end]:
+                if not self.regexp2.match(line):
+                    return 0
+        return 1
+
+    def unbuild(self, lines):
+        """\
+Remove all comment marks from LINES, as hinted by this template.  Returns the
+cleaned up set of lines, and the size of the left margin.
+"""
+        margin = left_margin_size(lines)
+        # Remove box style marks.
+        start = 0
+        end = len(lines)
+        if self.regexp1 is not None:
+            lines[start] = unbuild_clean(lines[start], self.regexp1)
+            start = start + 1
+        if self.regexp3 is not None:
+            lines[end-1] = unbuild_clean(lines[end-1], self.regexp3)
+            end = end - 1
+        if self.regexp2 is not None:
+            for counter in range(start, end):
+                lines[counter] = unbuild_clean(lines[counter], self.regexp2)
+        # Remove the left side of the box after it turned into spaces.
+        delta = left_margin_size(lines) - margin
+        for counter in range(len(lines)):
+            lines[counter] = lines[counter][delta:]
+        # Remove leading and trailing white lines.
+        start = 0
+        end = len(lines)
+        while start < end and lines[start] == '':
+            start = start + 1
+        while end > start and lines[end-1] == '':
+            end = end - 1
+        return lines[start:end], margin
+
+    def build(self, lines, width, refill, margin):
+        """\
+Put LINES back into a boxed comment according to this template, after
+having refilled them if REFILL.  The box should start at column MARGIN,
+and the total size of each line should ideally not go over WIDTH.
+"""
+        # Merge a short end delimiter now, so it gets refilled with text.
+        if self.merge_se:
+            if lines:
+                lines[-1] = lines[-1] + '  ' + self.se
+            else:
+                lines = [self.se]
+        # Reduce WIDTH according to left and right inserts, then refill.
+        if self.ww:
+            width = width - len(self.ww)
+        if self.ee:
+            width = width - len(self.ee)
+        if refill:
+            lines = refill_lines(lines, width)
+        # Reduce WIDTH further according to the current right margin,
+        # and excluding the left margin.
+        maximum = 0
+        for line in lines:
+            if line:
+                if line[-1] in '.!?':
+                    length = len(line) + 1
+                else:
+                    length = len(line)
+                if length > maximum:
+                    maximum = length
+        width = maximum - margin
+        # Construct the top line.
+        if self.merge_nw:
+            lines[0] = ' ' * margin + self.nw + lines[0][margin:]
+            start = 1
+        elif self.nw or self.nn or self.ne:
+            if self.nn:
+                line = self.nn * width
+            else:
+                line = ' ' * width
+            if self.nw:
+                line = self.nw + line
+            if self.ne:
+                line = line + self.ne
+            lines.insert(0, string.rstrip(' ' * margin + line))
+            start = 1
+        else:
+            start = 0
+        # Construct all middle lines.
+        for counter in range(start, len(lines)):
+            line = lines[counter][margin:]
+            line = line + ' ' * (width - len(line))
+            if self.ww:
+                line = self.ww + line
+            if self.ee:
+                line = line + self.ee
+            lines[counter] = string.rstrip(' ' * margin + line)
+        # Construct the bottom line.
+        if self.sw or self.ss or self.se and not self.merge_se:
+            if self.ss:
+                line = self.ss * width
+            else:
+                line = ' ' * width
+            if self.sw:
+                line = self.sw + line
+            if self.se and not self.merge_se:
+                line = line + self.se
+            lines.append(string.rstrip(' ' * margin + line))
+        return lines
+
+def regexp_quote(text):
+    """\
+Return a regexp matching TEXT without its surrounding space, maybe
+followed by spaces.  If STRING is nil, return the empty regexp.
+Unless spaces, the text is nested within a regexp parenthetical group.
+"""
+    if text is None:
+        return ''
+    if text == ' ' * len(text):
+        return ' *'
+    return '(' + re.escape(string.strip(text)) + ') *'
+
+def regexp_ruler(character):
+    """\
+Return a regexp matching two or more repetitions of CHARACTER, maybe
+followed by spaces.  Is CHARACTER is nil, return the empty regexp.
+Unless spaces, the ruler is nested within a regexp parenthetical group.
+"""
+    if character is None:
+        return ''
+    if character == ' ':
+        return '  +'
+    return '(' + re.escape(character + character) + '+) *'
+
+def unbuild_clean(line, regexp):
+    """\
+Return LINE with all parenthetical groups in REGEXP erased and replaced by an
+equivalent number of spaces, except for trailing spaces, which get removed.
+"""
+    match = re.match(regexp, line)
+    groups = match.groups()
+    for counter in range(len(groups)):
+        if groups[counter] is not None:
+            start, end = match.span(1 + counter)
+            line = line[:start] + ' ' * (end - start) + line[end:]
+    return string.rstrip(line)
+
+## Template data.
+
+# Matcher functions for a comment start, indexed by numeric LANGUAGE.
+language_matcher = []
+for pattern in (r' *(/\*|//+|#+|;+|%+)',
+                r'',            # 1
+                r' */\*',       # 2
+                r' *//+',       # 3
+                r' *#+',        # 4
+                r' *;+',        # 5
+                r' *%+'):       # 6
+    language_matcher.append(re.compile(pattern).match)
+
+# Template objects, indexed by numeric style.
+template_registry = {}
+
+def make_generic(style, weight, lines):
+    """\
+Add various language digit to STYLE and generate one template per language,
+all using the same WEIGHT.  Replace `?' in LINES accordingly.
+"""
+    for language, character in ((300, '/'),  # C++ style comments
+                                (400, '#'),  # scripting languages
+                                (500, ';'),  # LISP and assembler
+                                (600, '%')): # TeX and PostScript
+        new_style = language + style
+        if 310 < new_style <= 319:
+            # Disallow quality 10 with C++.
+            continue
+        new_lines = []
+        for line in lines:
+            new_lines.append(string.replace(line, '?', character))
+        Template(new_style, weight, new_lines)
+
+# Generic programming language templates.
+
+make_generic(11, 115, ('? box',))
+
+make_generic(12, 215, ('? box ?',
+                       '? --- ?'))
+
+make_generic(13, 315, ('? --- ?',
+                       '? box ?',
+                       '? --- ?'))
+
+make_generic(14, 415, ('? box ?',
+                       '???????'))
+
+make_generic(15, 515, ('???????',
+                       '? box ?',
+                       '???????'))
+
+make_generic(21, 125, ('?? box',))
+
+make_generic(22, 225, ('?? box ??',
+                       '?? --- ??'))
+
+make_generic(23, 325, ('?? --- ??',
+                       '?? box ??',
+                       '?? --- ??'))
+
+make_generic(24, 425, ('?? box ??',
+                       '?????????'))
+
+make_generic(25, 525, ('?????????',
+                       '?? box ??',
+                       '?????????'))
+
+make_generic(31, 135, ('??? box',))
+
+make_generic(32, 235, ('??? box ???',
+                       '??? --- ???'))
+
+make_generic(33, 335, ('??? --- ???',
+                       '??? box ???',
+                       '??? --- ???'))
+
+make_generic(34, 435, ('??? box ???',
+                       '???????????'))
+
+make_generic(35, 535, ('???????????',
+                       '??? box ???',
+                       '???????????'))
+
+make_generic(41, 145, ('???? box',))
+
+make_generic(42, 245, ('???? box ????',
+                       '???? --- ????'))
+
+make_generic(43, 345, ('???? --- ????',
+                       '???? box ????',
+                       '???? --- ????'))
+
+make_generic(44, 445, ('???? box ????',
+                       '?????????????'))
+
+make_generic(45, 545, ('?????????????',
+                       '???? box ????',
+                       '?????????????'))
+
+# Textual (non programming) templates.
+
+Template(111, 113, ('box',))
+
+Template(112, 213, ('| box |',
+                    '+-----+'))
+
+Template(113, 313, ('+-----+',
+                    '| box |',
+                    '+-----+'))
+
+Template(114, 413, ('| box |',
+                    '*=====*'))
+
+Template(115, 513, ('*=====*',
+                    '| box |',
+                    '*=====*'))
+
+Template(121, 123, ('| box |',))
+
+Template(122, 223, ('| box |',
+                    '`-----\''))
+
+Template(123, 323, ('.-----.',
+                    '| box |',
+                    '`-----\''))
+
+Template(124, 423, ('| box |',
+                    '\\=====/'))
+
+Template(125, 523, ('/=====\\',
+                    '| box |',
+                    '\\=====/'))
+
+Template(141, 143, ('| box ',))
+
+Template(142, 243, ('* box *',
+                    '*******'))
+
+Template(143, 343, ('*******',
+                    '* box *',
+                    '*******'))
+
+Template(144, 443, ('X box X',
+                    'XXXXXXX'))
+
+Template(145, 543, ('XXXXXXX',
+                    'X box X',
+                    'XXXXXXX'))
+# C language templates.
+
+Template(211, 118, ('/* box */',))
+
+Template(212, 218, ('/* box */',
+                    '/* --- */'))
+
+Template(213, 318, ('/* --- */',
+                    '/* box */',
+                    '/* --- */'))
+
+Template(214, 418, ('/* box */',
+                    '/* === */'))
+
+Template(215, 518, ('/* === */',
+                    '/* box */',
+                    '/* === */'))
+
+Template(221, 128, ('/* ',
+                    '   box',
+                    '*/'))
+
+Template(222, 228, ('/*    .',
+                    '| box |',
+                    '`----*/'))
+
+Template(223, 328, ('/*----.',
+                    '| box |',
+                    '`----*/'))
+
+Template(224, 428, ('/*    \\',
+                    '| box |',
+                    '\\====*/'))
+
+Template(225, 528, ('/*====\\',
+                    '| box |',
+                    '\\====*/'))
+
+Template(231, 138, ('/*    ',
+                    ' | box',
+                    ' */   '))
+
+Template(232, 238, ('/*        ',
+                    ' | box | ',
+                    ' *-----*/'))
+
+Template(233, 338, ('/*-----* ',
+                    ' | box | ',
+                    ' *-----*/'))
+
+Template(234, 438, ('/* box */',
+                    '/*-----*/'))
+
+Template(235, 538, ('/*-----*/',
+                    '/* box */',
+                    '/*-----*/'))
+
+Template(241, 148, ('/*    ',
+                    ' * box',
+                    ' */   '))
+
+Template(242, 248, ('/*     * ',
+                    ' * box * ',
+                    ' *******/'))
+
+Template(243, 348, ('/******* ',
+                    ' * box * ',
+                    ' *******/'))
+
+Template(244, 448, ('/* box */',
+                    '/*******/'))
+
+Template(245, 548, ('/*******/',
+                    '/* box */',
+                    '/*******/'))
+
+Template(251, 158, ('/* ',
+                    ' * box',
+                    ' */   '))
+
+if __name__ == '__main__':
+    apply(main, sys.argv[1:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/README	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1030 @@
+* README for `Pymacs'				allout -*- outline -*-
+
+  `http://www.iro.umontreal.ca/~pinard/pymacs/' contains a copy of this
+  `README' file in HTML form.  The canonical Pymacs distribution is
+  available as `http://www.iro.umontreal.ca/~pinard/pymacs/Pymacs.tar.gz'.
+  Report problems and suggestions to `mailto:pinard@iro.umontreal.ca'.
+
+.. Presentation.
+
+. : What is Pymacs?
+
+    Pymacs is a powerful tool which, once started from Emacs, allows both-way
+    communication between Emacs Lisp and Python.  Yet, Pymacs aims Python as
+    an extension language for Emacs rather than the other way around; this
+    assymetry is reflected in some design choices.  Within Emacs Lisp code,
+    one may load and use Python modules.  Python functions may themselves use
+    Emacs services, and handle Emacs Lisp objects kept in Emacs Lisp space.
+
+    The goals are to write "naturally" in both languages, debug with ease,
+    fall back gracefully on errors, and allow full cross-recursivity.
+
+    It is very easy to install Pymacs, as neither Emacs nor Python need to
+    be compiled nor relinked.  Emacs merely starts Python as a subprocess,
+    and Pymacs implements a communication protocol between both processes.
+
+. : Warning to Pymacs users.
+
+    I expect average Pymacs users to have a deeper knowledge of Python
+    than Emacs Lisp.  Some examples at the end of this file are meant
+    for Python users having a limited experience with the Emacs API.
+    Currently, there are only contains two examples, one is too small,
+    the other is too big :-).  As there is no dedicated mailing list nor
+    discussion group for Pymacs, let's use `python-list@python.org' for
+    asking questions or discussing Pymacs related matters.
+
+    This is beta status software: specifications are slightly frozen, yet
+    changes may still happen that would require small adaptations in your
+    code.  Report problems to François Pinard at `pinard@iro.umontreal.ca'.
+    For discussing specifications or making suggestions, please also copy
+    the `python-list@python.org' mailing list, to help brain-storming! :-)
+
+. : History and references.
+
+    I once starved for a Python-extensible editor, and pondered the idea of
+    dropping Emacs for other avenues, but found nothing much convincing.
+    Moreover, looking at all LISP extensions I wrote for myself, and
+    considering all those superb tools written by others and that became
+    part of my computer life, it would have been a huge undertaking for
+    me to reprogram these all in Python.  So, when I began to see that
+    something like Pymacs was possible, I felt strongly motivated! :-)
+
+    Pymacs revisits previous Cedric Adjih's works about running Python as a
+    process separate from Emacs.  See `http://www.crepuscule.com/pyemacs/',
+    or write Cedric at `adjih-pam@crepuscule.com'.  Cedric presented
+    `pyemacs' to me as a proof of concept.  As I simplified that concept
+    a bit, I dropped the `e' in `pyemacs' :-).  Cedric also told me that
+    there exist some older patches for linking Python right into XEmacs.
+
+    Brian McErlean independently and simultaneously wrote a tool similar
+    to this one, we decided to join our projects.  Amusing coincidence, he
+    even chose `pymacs' as a name.  Brian paid good attention to complex
+    details that escaped my courage, so his help and collaboration have
+    been beneficial.  You may reach Brian at `brianmce@crosswinds.net'.
+
+    One other reference of interest is Doug Bagley shoot out project,
+    which compares the relative speed of many popular languages.
+    See `http://www.bagley.org/~doug/shootout/' for more information.
+
+.. Installation.
+
+. : Install the Pymacs proper.
+
+    Currently, there are two installation scripts, and both should be run.
+    If you prefer, you may use `make install lispdir=LISPDIR', where
+    LISPDIR is some directory along the list kept in your Emacs `load-path'.
+
+    The first installation script installs the Python package, including the
+    Pymacs examples, using the Python standard Distutils tool.  Merely `cd'
+    into the Pymacs distribution, then execute `python setup.py install'.
+    To get an option reminder, do `python setup.py install --help'.  Check
+    the Distutils documentation if you need more information about this.
+
+    The second installation script installs the Emacs Lisp part only.
+    (It used to do everything, but is now doomed to disappear completely.)
+    Merely `cd' into the Pymacs distribution, then run `python setup -ie'.
+    This will invite you to interactively confirm the Lisp installation
+    directory.  Without `-ie', the Lisp part of Pymacs will be installed
+    in some automatically guessed place.  Use `-n' to known about the guess
+    without proceeding to the actual installation.  `./setup -E xemacs ...'
+    may be useful to XEmacs lovers.  See `./setup -H' for all options.
+
+    About Win32 systems, Syver Enstad says: "For Pymacs to operate correctly,
+    one should create a batch file with `pymacs-services.bat' as a name,
+    which runs the `pymacs-services' script.  The `.bat' file could be
+    placed along with `pymacs-services', wherever that maybe.".
+
+    To check that `pymacs.el' is properly installed, start Emacs and give
+    it the command `M-x load-library RET pymacs': you should not receive
+    any error.  To check that `pymacs.py' is properly installed, start
+    an interactive Python session and type `from Pymacs import lisp':
+    you should not receive any error.  To check that `pymacs-services'
+    is properly installed, type `pymacs-services </dev/null' in a shell;
+    you should then get a line ending with "(pymacs-version VERSION)",
+    and another saying: "Protocol error: `>' expected.".
+
+    Currently, there is only one installed Pymacs example, which comes
+    in two parts: a batch script `rebox' and a `Pymacs.rebox' module.
+    To check that both are properly installed, type `rebox </dev/null'
+    in a shell; you should not receive any output nor see any error.
+
+. : Prepare your `.emacs' file.
+
+    The ".emacs" file is not given in the distribution, you likely have
+    one already in your home directory.  You need to add these lines:
+
+      (autoload 'pymacs-load "pymacs" nil t)
+      (autoload 'pymacs-eval "pymacs" nil t)
+      (autoload 'pymacs-apply "pymacs")
+      (autoload 'pymacs-call "pymacs")
+      ;;(eval-after-load "pymacs"
+      ;;  '(add-to-list 'pymacs-load-path "YOUR-PYMACS-DIRECTORY"))
+
+    If you plan to use a special directory to hold your own Pymacs code in
+    Python, which should be searched prior to the usual Python import search
+    path, then uncomment the last two lines (by removing the semi-colons)
+    and replace YOUR-PYMACS-DIRECTORY by the name of your special directory.
+    If the file "$HOME/.emacs" does not exist, merely create it with the
+    above lines.  You are now all set to use Pymacs.
+
+    To check this, start a fresh Emacs session, and type `M-x pymacs-eval'.
+    Emacs should prompt you for a Python expression.  Try "`2L**111`" (type
+    the backquotes, but not the external double-quotes).  The minibuffer
+    should display `2596148429267413814265248164610048L'. `M-x pymacs-load'
+    should prompt you for a Python module name.  Reply `os'.  After Emacs
+    prompts you for a prefix, merely hit Enter to accept the default prefix.
+    This should have the effect of importing the Python "os" module within
+    Emacs.  Typing `M-: (os-getcwd)' should echo the current directory in
+    the message buffer, as returned by the `os.getcwd' Python function.
+
+. : Porting Pymacs.
+
+    Pymacs has been developped on Linux and Emacs (20 and 21), it is expected
+    to work out of the box on most other Unices, and also with XEmacs.
+
+    Syver Enstad reports that Pymacs could be made to work on Windows-2000
+    (win2k), he suspects it should equally work with NT and XP.  However,
+    little shell stunts may be required, I hope to later document them here.
+
+. : Caveats.
+
+    Some later versions of Emacs 20 silently ignore the request for
+    creating weak hash tables, they create an ordinary table instead.
+    Older Emacses just do not have hash tables.  Pymacs should run on
+    all, yet for these, memory will leak on the Python side whenever
+    complex objects get transmitted to Emacs, as these objects will not
+    be reclaimed on the Python side once Emacs is finished with them.
+    It should not be a practical problem in most simple cases.
+
+.. Emacs Lisp structures and Python objects.
+
+. : Conversions.
+
+    Whenever Emacs Lisp calls Python functions giving them arguments,
+    these arguments are Emacs Lisp structures that should be converted
+    into Python objects in some way.  Conversely, whenever Python calls
+    Emacs Lisp functions, the arguments are Python objects that should
+    be received as Emacs Lisp structures.  We need some conventions for
+    doing such conversions.
+
+    Conversions generally transmit mutable Emacs Lisp structures as mutable
+    objects on the Python side, in such a way that transforming the object in
+    Python will effectively transform the structure on the Emacs Lisp side
+    (strings are handled a bit specially however, see below).  The other
+    way around, Python objects transmitted to Emacs Lisp often loose their
+    mutability, so transforming the Emacs Lisp structure is not reflected
+    on the Python side.
+
+. : Simple objects.
+
+    Emacs Lisp `nil' and the equivalent Emacs Lisp `()' yield Python `None'.
+    Python `None' and the Python empty list `[]' are returned as `nil'
+    in Emacs Lisp.
+
+    Emacs Lisp numbers, either integer or floating, are converted in
+    equivalent Python numbers.  Emacs Lisp characters are really numbers
+    and yield Python numbers.  In the other direction, Python numbers are
+    converted into Emacs Lisp numbers, with the exception of long Python
+    integers and complex numbers.
+
+    Emacs Lisp strings are usually converted into equivalent Python narrow
+    strings.  As Python strings do not have text properties, these are not
+    reflected.  This may be changed by setting the `pymacs-mutable-strings'
+    option: if this variable is not `nil', Emacs Lisp strings are then
+    transmitted opaquely.  Python strings, except Unicode, are always
+    converted into Emacs Lisp strings.
+
+    Emacs Lisp symbols yield the special `lisp.SYMBOL' or `lisp[STRING]'
+    notations on the Python side.  The first notation is used when the
+    Emacs Lisp symbol starts with a letter, and contains only letters,
+    digits and hyphens, in which case Emacs Lisp hyphens get replaced
+    by Python underscores.  This convention is welcome, as Emacs Lisp
+    programmers commonly prefer using dashes, where Python programmers
+    use underlines.  Otherwise, the second notation is used.  Conversely,
+    `lisp.SYMBOL' on the Python side yields an Emacs Lisp symbol with
+    underscores replaced with hyphens, while `lisp[STRING]' corresponds
+    to an Emacs Lisp symbol printed with that STRING which, of course,
+    should then be a valid Emacs Lisp symbol name.
+
+. : Sequences.
+
+    The case of strings has been discussed in the previous section.
+
+    Proper Emacs Lisp lists, those for which the `cdr' of last
+    cell is `nil', are normally transmitted opaquely to Python.
+    If `pymacs-forget-mutability' is set, or if Python later asks for these
+    to be expanded, proper Emacs Lisp lists get converted into Python lists,
+    if we except the empty list, which is always converted as Python `None'.
+    In the other direction, Python lists are always converted into proper
+    Emacs Lisp lists.
+
+    Emacs Lisp vectors are normally transmitted opaquely to Python.  However,
+    if `pymacs-forget-mutability' is set, or if Python later asks for these
+    to be expanded, Emacs Lisp vectors get converted into Python tuples.
+    In the other direction, Python tuples are always converted into Emacs
+    Lisp vectors.
+
+    Remember the rule: "Round parentheses correspond to square brackets!".
+    It works for lists, vectors, tuples, seen from either Emacs Lisp or Python.
+
+    The above choices were debatable.  Since Emacs Lisp proper lists and
+    Python lists are the bread-and-butter of algorithms modifying structures,
+    at least in my experience, I guess they are more naturally mapped into
+    one another, this spares many casts in practice.  While in Python,
+    the most usual idiom for growing lists is appending to their end,
+    the most usual idiom in Emacs Lisp to grow a list is by cons'ing new
+    items at its beginning:
+
+      (setq accumulator (cons 'new-item accumulator))
+
+    or more simply:
+
+      (push accumulator 'new-item)
+
+    So, in case speed is especially important and many modifications happen
+    in a row on the same side, while order of elements ought to be preserved,
+    some (nreverse ...) on the Emacs Lisp side or .reverse() on the Python
+    side side might be needed.  Surely, proper lists in Emacs Lisp and lists
+    in Python are the normal structure for which length is easily modified.
+
+    We cannot so easily change the size of a vector, the same as it is a
+    bit more of a stunt to "modify" a tuple.  The shape of these objects is
+    fixed.  Mapping vectors to tuples, which is admittedly strange, will only
+    be done if the Python side requests an expanded copy, otherwise an opaque
+    Emacs Lisp object is seen in Python.  In the other direction, whenever
+    an Emacs Lisp vector is needed, one has to write `tuple(python_list)'
+    while transmitting the object.  Such transmissions are most probably
+    to be unusual, as people are not going to blindly transmit whole big
+    structures back and forth between Emacs and Python, they would rather do
+    it once in a while only, and do only local modifications afterwards.
+    The infrequent casting to `tuple' for getting an Emacs Lisp vector
+    seems to suggest that we did a reasonable compromise.
+
+    In Python, both tuples and lists have O(1) access, so there is no real
+    speed consideration there.  Emacs Lisp is different: vectors have O(1)
+    access while lists have O(N) access.  The rigidity of Emacs Lisp
+    vectors is such that people do not resort to vectors unless there
+    is a speed issue, so in real Emacs Lisp practice, vectors are used
+    rather parsimoniously.  So much, in fact, that Emacs Lisp vectors are
+    overloaded for what they are not meant: for example, very small vectors
+    are used to represent X events in key-maps, programmers only want
+    to test vectors for their type, or users just like bracketed syntax.
+    The speed of access is hardly an issue then.
+
+. : Opaque objects.
+
+.  , Emacs Lisp handles.
+
+     When a Python function is called from Emacs Lisp, the function arguments
+     have already been converted to Python types from Emacs Lisp types
+     and the function result is going to be converted back to Emacs Lisp.
+
+     Several Emacs Lisp objects do not have Python equivalents, like for
+     Emacs windows, buffers, markers, overlays, etc.  It is nevertheless
+     useful to pass them to Python functions, hoping that these Python
+     functions will "operate" on these Emacs Lisp objects.  Of course,
+     the Python side may not itself modify such objects, it has to call
+     for Emacs services to do so.  Emacs Lisp handles are a mean to ease
+     this communication.
+
+     Whenever an Emacs Lisp object may not be converted to a Python object, an
+     Emacs Lisp handle is created and used instead.  Whenever that Emacs Lisp
+     handle is returned into Emacs Lisp from a Python function, or is used
+     as an argument to an Emacs Lisp function from Python, the original Emacs
+     Lisp object behind the Emacs Lisp handle is automatically retrieved.
+
+     Emacs Lisp handles are either instances of the internal `Lisp' class,
+     or of one of its subclasses.  If `object' is an Emacs Lisp handle, and
+     if the underlying Emacs Lisp object is an Emacs Lisp sequence, then
+     whenever `object[index]', `object[index] = value' and `len(object)'
+     are meaningful, these may be used to fetch or alter an element of the
+     sequence directly in Emacs Lisp space.  Also, if `object' corresponds
+     to an Emacs Lisp function, `object(ARGUMENTS)' may be used to apply
+     the Emacs Lisp function over the given arguments.  Since arguments
+     have been evaluated the Python way on the Python side, it would be
+     conceptual overkill evaluating them again the Emacs Lisp way on the
+     Emacs Lisp side, so Pymacs manage to quotes arguments for defeating
+     Emacs Lisp evaluation.  The same logic applies the other way around.
+
+     Emacs Lisp handles have a `value()' method, which merely returns self.
+     They also have a `copy()' method, which tries to "open the box"
+     if possible.  Emacs Lisp proper lists are turned into Python lists,
+     Emacs Lisp vectors are turned into Python tuples.  Then, modifying
+     the structure of the copy on the Python side has no effect on the
+     Emacs Lisp side.
+
+     For Emacs Lisp handles, `str()' returns an Emacs Lisp representation
+     of the handle which should be `eq' to the original object if read back
+     and evaluated in Emacs Lisp.  `repr()' returns a Python representation
+     of the expanded Emacs Lisp object.  If that Emacs Lisp object has
+     an Emacs Lisp representation which Emacs Lisp could read back, then
+     `repr()' value is such that it could be read back and evaluated in
+     Python as well, this would result in another object which is `equal'
+     to the original, but not neccessarily `eq'.
+
+.  , Python handles.
+
+     The same as Emacs Lisp handles are useful to handle Emacs Lisp objects
+     on the Python side, Python handles are useful to handle Python objects
+     on the Emacs Lisp side.
+
+     Many Python objects do not have direct Emacs Lisp equivalents,
+     including long integers, complex numbers, Unicode strings, modules,
+     classes, instances and surely a lot of others.  When such are being
+     transmitted to the Emacs Lisp side, Pymacs use Python handles.
+     These are automatically recovered into the original Python objects
+     whenever transmitted back to Python, either as arguments to a Python
+     function, as the Python function itself, or as the return value of
+     an Emacs Lisp function called from Python.
+
+     The objects represented by these Python handles may be inspected or
+     modified using the basic library of Python functions.  For example, in:
+
+       (setq matcher (pymacs-eval "re.compile('PATTERN').match"))
+       (pymacs-call matcher ARGUMENT)
+
+     the initial `setq' above could be decomposed into:
+
+       (setq compiled (pymacs-eval "re.compile('PATTERN')")
+             matcher (pymacs-call "getattr" compiled "match"))
+
+     This example shows that one may use `pymacs-call' with "getattr"
+     as the function, to get a wanted attribute for a Python object.
+
+.. Usage on the Emacs Lisp side.
+
+. : `pymacs-eval'.
+
+    Function `(pymacs-eval TEXT)' gets TEXT evaluated as a Python expression,
+    and returns the value of that expression converted back to Emacs Lisp.
+
+. : `pymacs-call'.
+
+    Function `(pymacs-call FUNCTION ARGUMENT...)' will get Python to apply
+    the given FUNCTION over zero or more ARGUMENT.  FUNCTION is either a
+    string holding Python source code for a function (like a mere name, or
+    even an expression), or else, a Python handle previously received from
+    Python, and hopefully holding a callable Python object.  Each ARGUMENT
+    gets separately converted to Python before the function is called.
+    `pymacs-call' returns the resulting value of the function call,
+    converted back to Emacs Lisp.
+
+. : `pymacs-apply'.
+
+    Function `(pymacs-apply FUNCTION ARGUMENTS)' will get Python to apply
+    the given FUNCTION over the given ARGUMENTS.  ARGUMENTS is a list
+    containing all arguments, or `nil' if there is none.  Besides arguments
+    being bundled together instead of given separately, the function acts
+    pretty much like `pymacs-call'.
+
+. : `pymacs-load'.
+
+    Function `(pymacs-load MODULE PREFIX)' imports the Python MODULE into
+    Emacs Lisp space.  MODULE is the name of the file containing the module,
+    without any `.py' or `.pyc' extension.  If the directory part is omitted
+    in MODULE, the module will be looked into the current Python search
+    path.  Dot notation may be used when the module is part of a package.
+    Each top-level function in the module produces a trampoline function in
+    Emacs Lisp having the same name, except that underlines in Python names
+    are turned into dashes in Emacs Lisp, and that PREFIX is uniformly
+    added before the Emacs Lisp name (as a way to avoid name clashes).
+    PREFIX may be omitted, in which case it defaults to base name of MODULE
+    with underlines turned into dashes, and followed by a dash.
+
+    Whenever `pymacs_load_hook' is defined in the loaded Python module,
+    `pymacs-load' calls it without arguments, but before creating the Emacs
+    view for that module.  So, the `pymacs_load_hook' function may create
+    new definitions or even add `interaction' attributes to functions.
+
+    The return value of a successful `pymacs-load' is the module object.
+    An optional third argument, NOERROR, when given and not `nil', will
+    have `pymacs-load' to return `nil' instead of raising an error, if
+    the Python module could not be found.
+
+    When later calling one of these trampoline functions, all provided
+    arguments are converted to Python and transmitted, and the function
+    return value is later converted back to Emacs Lisp.  It is left to
+    the Python side to check for argument consistency.  However, for
+    an interactive function, the interaction specification drives some
+    checking on the Emacs Lisp side.  Currently, there is no provision
+    for collecting keyword arguments in Emacs Lisp.
+
+. : Expected usage.
+
+    We do not expect that `pymacs-eval', `pymacs-call' or `pymacs-apply'
+    will be much used, if ever.  In practice, the Emacs Lisp side
+    of a Pymacs application might call `pymacs-load' a few times for
+    linking into the Python modules, with the indirect effect of defining
+    trampoline functions for these modules on the Emacs Lisp side, which
+    can later be called like usual Emacs Lisp functions.
+
+    These imported functions are usually those which are of interest for
+    the user, and the preferred way to call Python services with Pymacs.
+
+. : Special Emacs Lisp variables.
+
+    Users could alter the inner working of Pymacs through a few variables,
+    these are all documented here.  Except for `pymacs-load-path', which
+    should be set before calling any Pymacs function, the value of these
+    variables can be changed at any time.
+
+.  , pymacs-load-path
+
+     Users might want to use special directories for holding their Python
+     modules, when these modules are meant to be used from Emacs.  Best is
+     to preset `pymacs-load-path, `nil' by default, to a list of these
+     directory names.  (Tilde expansions and such occur automatically.)
+
+     Here is how it works.  The first time Pymacs is needed from Emacs,
+     `pymacs-services' is called, and given as arguments all strings in the
+     `pymacs-load-path' list.  These arguments are added at the beginning
+     of `sys.path', or moved at the beginning if they were already on
+     `sys.path'.  So in practice, nothing is removed from `sys.path'.
+
+.  , pymacs-trace-transit
+
+     The `*Pymacs*' buffer, within Emacs, holds a trace of transactions
+     between Emacs and Python.  When `pymacs-trace-transit' is `nil',
+     and this is the default setting, the buffer only holds the last
+     bi-directional transaction (a request and a reply).  If that variable
+     is not `nil', all transactions are kept.  This could be useful for
+     debugging, but the drawback is that this buffer could grow big over
+     time, to the point of diminishing Emacs performance.
+
+.  , pymacs-forget-mutability
+
+     The default behaviour of Pymacs is to transmit Emacs Lisp objects to
+     Python in such a way thay they are fully modifiable from the Python
+     side, would it mean triggering Emacs Lisp functions to act on them.
+     When `pymacs-forget-mutability' is not `nil', the behaviour is changed,
+     and the flexibility is lost.  Pymacs then tries to expand proper lists
+     and vectors as full copies when transmitting them on the Python side.
+     This variable, seen as a user setting, is best left to `nil'.  It may
+     be temporarily overriden within some functions, when deemed useful.
+
+     There is no corresponding variable from objects transmitted to Emacs
+     from Python.  Pymacs automatically expands what gets transmitted.
+     Mutability is preserved only as a side-effect of not having a natural
+     Emacs Lisp representation for the Python object.  This assymetry is on
+     purpose, yet debatable.  Maybe Pymacs could have a variable telling
+     that mutability _is_ important for Python objects?  That would give
+     Pymacs users the capability of restoring the symmetry somewhat,
+     yet so far, in our experience, this has never been needed.
+
+.  , pymacs-mutable-strings
+
+     Strictly speaking, Emacs Lisp strings are mutable. Yet, it does not
+     come naturally to a Python programmer to modify a string "in-place",
+     as Python strings are never mutable.  When `pymacs-mutable-strings' is
+     `nil', which is the default setting, Emacs Lisp strings are transmitted
+     to Python as Python strings, and so, loose their mutability.
+     Moreover, text properties are not reflected on the Python side.
+     But if that variable is not `nil', Emacs Lisp strings are rather
+     passed as Emacs Lisp handles.  This variable is ignored whenever
+     `pymacs-forget-mutability' is set.
+
+.  , pymacs-timeout-at-start
+.  , pymacs-timeout-at-reply
+.  , pymacs-timeout-at-line
+
+     Emacs needs to protect itself a bit, in case the Pymacs service program,
+     which handles the Python side of requests, would not start correctly,
+     or maybe later die unexpectedly.  So, whenever Emacs reads data coming
+     from that program, it sets a time limit, and take some action whenever
+     that time limit expires.  All times are expressed in seconds.
+
+     The timeout at start defaults to 30 seconds, this time should only
+     be increased if a given machine is so heavily loaded that the Pymacs
+     service program has not enough of 30 seconds to start, in which case
+     Pymacs refuses to work, with an appropriate message in the minibuffer.
+
+     The two other variables almost never need to be changed in practice.
+     When Emacs is expecting a reply from Python, it might repeatedly
+     check the status of the Pymacs service program when that reply is not
+     received fast enough, just to make sure that this program did not die.
+     The timeout at reply, which defaults to 5, says how many seconds
+     to wait without checking, while expecting the first line of a reply.
+     The timeout at line, which defaults to 2, says how many seconds to wait
+     without checking, while expecting a line of the reply after the first.
+
+.. Usage on the Python side.
+
+. : Python setup.
+
+    Pymacs requires little or no setup in the Python modules which are
+    meant to be used from Emacs, for the simple situations where these
+    modules receive nothing but Emacs nil, numbers or strings, or return
+    nothing but Python `None', numbers or strings.
+
+    Otherwise, use `from Pymacs import lisp'.  If you need more Pymacs
+    features, like the `Let' class, write `from Pymacs import lisp, Let'.
+
+. : Response mode.
+
+    When Python receives a request from Emacs in the context of Pymacs,
+    and until it returns the reply, Emacs keeps listening to serve Python
+    requests.  Emacs is not listening otherwise.  Other Python threads,
+    if any, may not call Emacs without _very_ careful synchronisation.
+
+. : Emacs Lisp symbols.
+
+    `lisp' is a special object which has useful built-in magic.
+    Its attributes do nothing but represent Emacs Lisp symbols, created
+    on the fly as needed (symbols also have their built-in magic).
+
+    Except for `lisp.nil' or `lisp["nil"]', which are the same as `None',
+    both `lisp.SYMBOL' and `lisp[STRING]' yield objects of the internal
+    `Symbol' type.  These are genuine Python objects, that could be referred
+    to by simple Python variables.  One may write `quote = lisp.quote',
+    for example, and use `quote' afterwards to mean that Emacs Lisp symbol.
+    If a Python function received an Emacs Lisp symbol as an argument, it
+    can check with `==' if that argument is `lisp.never' or `lisp.ask', say.
+    A Python function may well choose to return `lisp.t'.
+
+    In Python, writing `lisp.SYMBOL = VALUE' or `lisp[STRING] = VALUE'
+    does assign VALUE to the corresponding symbol in Emacs Lisp space.
+    Beware that in such cases, the `lisp.' prefix may not be spared.
+    After `result = lisp.result', one cannot hope that a later `result = 3'
+    will have any effect in the Emacs Lisp space: this would merely change
+    the Python variable `result', which was a reference to a `Symbol'
+    instance, so it is now a reference to the number 3.
+
+    The `Symbol' class has `value()' and `copy()' methods.  One can use
+    either `lisp.SYMBOL.value()' or `lisp.SYMBOL.copy()' to access the
+    Emacs Lisp value of a symbol, after conversion to some Python object,
+    of course.  However, if `value()' would have given an Emacs Lisp handle,
+    `lisp.SYMBOL.copy()' has the effect of `lisp.SYMBOL.value().copy()',
+    that is, it returns the value of the symbol as opened as possible.
+
+    A symbol may also be used as if it was a Python function, in which case
+    it really names an Emacs Lisp function that should be applied over the
+    following function arguments.  The result of the Emacs Lisp function
+    becomes the value of the call, with all due conversions of course.
+
+. : Dynamic bindings.
+
+    As Emacs Lisp uses dynamic bindings, it is common that Emacs Lisp
+    programs use `let' for temporarily setting new values for some Emacs
+    Lisp variables having global scope.  These variables recover their
+    previous value automatically when the `let' gets completed, even if
+    an error occurs which interrupts the normal flow of execution.
+
+    Pymacs has a `Let' class to represent such temporary settings.  Suppose
+    for example that you want to recover the value of `lisp.mark()' when the
+    transient mark mode is active on the Emacs Lisp side.  One could surely
+    use `lisp.mark(lisp.t)' to "force" reading the mark in such cases,
+    but for the sake of illustration, let's ignore that, and temporarily
+    deactivate transient mark mode instead.  This could be done this way:
+
+        try:
+            let = Let()
+            let.push(transient_mark_mode=None)
+            ... USER CODE ...
+        finally:
+            let.pop()
+
+    `let.push()' accepts any number of keywords arguments.  Each keyword
+    name is interpreted as an Emacs Lisp symbol written the Pymacs way,
+    with underlines.  The value of that Emacs Lisp symbol is saved on the
+    Python side, and the value of the keyword becomes the new temporary value
+    for this Emacs Lisp symbol.  A later `let.pop()' restores the previous
+    value for all symbols which were saved together at the time of the
+    corresponding `let.push()'.  There may be more than one `let.push()'
+    call for a single `Let' instance, they stack within that instance.
+    Each `let.pop()' will undo one and only one `let.push()' from the stack,
+    in the reverse order or the pushes.
+
+    When the `Let' instance disappears, either because the programmer does
+    `del let' or `let = None', or just because the Python `let' variable
+    goes out of scope, all remaining `let.pop()' get automatically executed,
+    so the `try'/`finally' statement may be omitted in practice.  For this
+    omission to work flawlessly, the programmer should be careful at not
+    keeping extra references to the `Let' instance.
+
+    The constructor call `let = Let()' also has an implied initial `.push()'
+    over all given arguments, so the explicit `let.push()' may be omitted
+    as well.  In practice, this sums up and the above code could be reduced
+    to a mere:
+
+        let = Let(transient_mark_mode=None)
+        ... USER CODE ...
+
+    Be careful at assigning the result of the constructor to some Python
+    variable.  Otherwise, the instance would disappear immediately after
+    having been created, restoring the Emacs Lisp variable much too soon.
+
+    Any variable to be bound with `Let' should have been bound in advance
+    on the Emacs Lisp side.  This restriction usually does no kind of harm.
+    Yet, it will likely be lifted in some later version of Pymacs.
+
+    The `Let' class has other methods meant for some macros which are
+    common in Emacs Lisp programming, in the spirit of `let' bindings.
+    These method names look like `push_*' or `pop_*', where Emacs
+    Lisp macros are `save-*'.  One has to use the matching `pop_*' for
+    undoing the effect of a given `push_*' rather than a mere `.pop()':
+    the Python code is clearer, this also ensures that things are undone
+    in the proper order.  The same `Let' instance may use many `push_*'
+    methods, their effects nest.
+
+    `push_excursion()' and `pop_excursion()' save and restore the current
+    buffer, point and mark.  `push_match_data()' and `pop_match_data()'
+    save and restore the state of the last regular expression match.
+    `push_restriction()' and `pop_restriction()' save and restore
+    the current narrowing limits.  `push_selected_window()' and
+    `pop_selected_window()' save and restore the fact that a window holds
+    the cursor.  `push_window_excursion()' and `pop_window_excursion()'
+    save and restore the current window configuration in the Emacs display.
+
+    As a convenience, `let.push()' and all other `push_*' methods return
+    the `Let' instance.  This helps chaining various `push_*' right after
+    the instance generation.  For example, one may write:
+
+        let = Let().push_excursion()
+        if True:
+            ... USER CODE ...
+        del let
+
+    The `if True:' (use `if 1:' with older Python releases, some people
+    might prefer writing `if let:' anyway), has the only goal of indenting
+    USER CODE, so the scope of the `let' variable is made very explicit.
+    This is purely stylistic, and not at all necessary.  The last `del let'
+    might be omitted in a few circumstances, for example if the excursion
+    lasts until the end of the Python function.
+
+. : Raw Emacs Lisp expressions.
+
+    Pymacs offers a device for evaluating a raw Emacs Lisp expression,
+    or a sequence of such, expressed as a string.  One merely uses `lisp'
+    as a function, like this:
+
+        lisp("""
+        ...
+        POSSIBLY-LONG-SEQUENCE-OF-LISP-EXPRESSIONS
+        ...
+        """)
+
+    The Emacs Lisp value of the last or only expression in the sequence
+    becomes the value of the `lisp' call, after conversion back to Python.
+
+. : User interaction.
+
+    Emacs functions have the concept of user interaction for completing
+    the specification of their arguments while being called.  This happens
+    only when a function is interactively called by the user, it does
+    not happen when a function is programmatically called by another.
+    As Python does not have a corresponding facility, a bit of trickery
+    was needed to retrofit that facility on the Python side.
+
+    After loading a Python module but prior to creating an Emacs view
+    for this module, Pymacs decides whether loaded functions will be
+    interactively callable from Emacs, or not.  Whenever a function has an
+    `interaction' attribute, this attribute holds the Emacs interaction
+    specification for this function.  The specification is either another
+    Python function or a string.  In the former case, that other function
+    is called without arguments and should, maybe after having consulted
+    the user, return a list of the actual arguments to be used for the
+    original function.  In the latter case, the specification string is
+    used verbatim as the argument to the `(interactive ...)' function
+    on the Emacs side.  To get a short reminder about how this string is
+    interpreted on the Emacs side, try `C-h f interactive' within Emacs.
+    Here is an example where an empty string is used to specify that an
+    interactive has no arguments:
+
+        from Pymacs import lisp
+
+        def hello_world():
+            "`Hello world' from Python."
+            lisp.insert("Hello from Python!")
+        hello_world.interaction = ''
+
+    Versions of Python released before the integration of PEP 232 do not
+    allow users to add attributes to functions, so there is a fallback
+    mechanism.  Let's presume that a given function does not have an
+    `interaction' attribute as explained above.  If the Python module
+    contains an `interactions' global variable which is a dictionary,
+    if that dictionary has an entry for the given function with a value
+    other than `None', that function is going to be interactive on the
+    Emacs side.  Here is how the preceeding example should be written
+    for an older version of Python, or when portability is at premium:
+
+        from Pymacs import lisp
+        interactions = {}
+
+        def hello_world():
+            "`Hello world' from Python."
+            lisp.insert("Hello from Python!")
+        interactions[hello_world] = ''
+
+    One might wonder why we do not merely use `lisp.interactive(...)' from
+    within Python.  There is some magic in the Emacs Lisp interpreter
+    itself, looking for that call _before_ the function is actually
+    entered, this explains why "(interactive ...)" has to appear first in
+    an Emacs Lisp `defun'.  Pymacs could try to scan the already compiled
+    form of the Python code, seeking for `lisp.interactive', but as the
+    evaluation of `lisp.interactive' arguments could get arbitrarily
+    complex, it would a real challenge un-compiling that evaluation into
+    Emacs Lisp.
+
+. : Keybindings.
+
+    An interactive function may be bound to a key sequence.
+
+    To translate bindings like `C-x w', say, one might have to know a bit
+    more how Emacs Lisp processes string escapes like `\C-x' or `\M-\C-x' in
+    Emacs Lisp, and emulate it within Python strings, since Python does not
+    have such escapes.  `\C-L', where L is an upper case letter, produces a
+    character which ordinal is the result of subtracting 0x40 from ordinal
+    of `L'.  `\M-' has the ordinal one gets by adding 0x80 to the ordinal
+    of following described character.  So people can use self-inserting
+    non-ASCII characters, `\M-' is given another representation, which is
+    to replace the addition of 0x80 by prefixing with `ESC', that is 0x1b.
+
+    So "\C-x" in Emacs is '\x18' in Python.  This is easily found, using an
+    interactive Python session, by givin it: chr(ord('X') - ord('A') + 1).
+    An easier way would be using the `kbd' function on the Emacs Lisp side,
+    like with lisp.kbd('C-x w') or lisp.kbd('M-<f2>').
+
+    To bind the F1 key to the `helper' function in some `module':
+
+        lisp.global_set_key((lisp.f1,), lisp.module_helper)
+
+    (item,) is a Python tuple yielding an Emacs Lisp vector.  `lisp.f1'
+    translates to the Emacs Lisp symbol `f1'.  So, Python `(lisp.f1,)' is
+    Emacs Lisp `[f1]'.  Keys like `[M-f2]' might require some more ingenuity,
+    one may write either (lisp['M-f2'],) or (lisp.M_f2,) on the Python side.
+
+.. Debugging.
+
+. : The `*Pymacs*' buffer.
+
+    Emacs and Python are two separate processes (well, each may use more
+    than one process).  Pymacs implements a simple communication protocol
+    between both, and does whatever needed so the programmers do not have
+    to worry about details.  The main debugging tool is the communication
+    buffer between Emacs and Python, which is named `*Pymacs*'.  To make
+    good use of it, first set `pymacs-trace-transit' to `t', so all
+    exchanges are accumulated in that buffer.  As it is sometimes helpful
+    to understand the communication protocol, it is briefly explained here,
+    using an artificially complex example to do so.  Consider:
+
+    ---------------------------------------------------------------------->
+    (pymacs-eval "lisp('(pymacs-eval \"`2L**111`\")')")
+    "2596148429267413814265248164610048L"
+    ----------------------------------------------------------------------<
+
+    Here, Emacs asks Python to ask Emacs to ask Python for a simple bignum
+    computation.  Note that Emacs does not natively know how to handle big
+    integers, nor has an internal representation for them.  This is why I
+    use backticks, so Python returns a string representation of the result,
+    instead of the result itself.  Here is a trace for this example.  The `<'
+    character flags a message going from Python to Emacs and is followed
+    by an expression written in Emacs Lisp.  The '>' character flags a
+    message going from Emacs to Python and is followed by a expression
+    written in Python.  The number gives the length of the message.
+
+    ---------------------------------------------------------------------->
+    <22   (pymacs-version "0.3")
+    >49   eval("lisp('(pymacs-eval \"`2L**111`\")')")
+    <25   (pymacs-eval "`2L**111`")
+    >18   eval("`2L**111`")
+    <47   (pymacs-reply "2596148429267413814265248164610048L")
+    >45   reply("2596148429267413814265248164610048L")
+    <47   (pymacs-reply "2596148429267413814265248164610048L")
+    ----------------------------------------------------------------------<
+
+    Python evaluation is done in the context of the `Pymacs.pymacs' module,
+    so for example a mere `reply' really means `Pymacs.pymacs.reply'.  On the
+    Emacs Lisp side, there is no concept of module namespaces, so we use
+    the `pymacs-' prefix as an attempt to stay clean.  Users should ideally
+    refrain from naming their Emacs Lisp objects with a `pymacs-' prefix.
+
+    `reply' and `pymacs-reply' are special functions meant to indicate that
+    an expected result is finally transmitted.  `error' and `pymacs-error'
+    are special functions that introduce a string which explains an exception
+    which recently occurred.  `pymacs-expand' is a special function
+    implementing the `copy()' methods of Emacs Lisp handles or symbols.
+    In all other cases, the expression is a request for the other side,
+    that request stacks until a corresponding reply is received.
+
+    Part of the protocol manages memory, and this management generates
+    some extra-noise in the `*Pymacs*' buffer.  Whenever Emacs passes a
+    structure to Python, an extra pointer is generated on the Emacs side to
+    inhibit garbage collection by Emacs.  Python garbage collector detects
+    when the received structure is no longer needed on the Python side,
+    at which time the next communication will tell Emacs to remove the
+    extra pointer.  It works symmetrically as well, that is, whenever Python
+    passes a structure to Emacs, an extra Python reference is generated to
+    inhibit garbage collection on the Python side.  Emacs garbage collector
+    detects when the received structure is no longer needed on the Emacs
+    side, after which Python will be told to remove the extra reference.
+    For efficiency, those allocation-related messages are delayed, merged and
+    batched together within the next communication having another purpose.
+
+. : Emacs usual debugging.
+
+    If cross-calls between Emacs Lisp and Python nest deeply, an error will
+    raise successive exceptions alternatively on both sides as requests
+    unstack, and the diagnostic gets transmitted back and forth, slightly
+    growing as we go.  So, errors will eventually be reported by Emacs.
+    I made no kind of effort to transmit the Emacs Lisp backtrace on the
+    Python side, as I do not see a purpose for it: all debugging is done
+    within Emacs windows anyway.
+
+    On recent Emacses, the Python backtrace gets displayed in the
+    mini-buffer, and the Emacs Lisp backtrace is simultaneously shown in the
+    `*Backtrace*' window.  One useful thing is to allow to mini-buffer to
+    grow big, so it has more chance to fully contain the Python backtrace,
+    the last lines of which are often especially useful.  Here, I use:
+
+      (setq resize-mini-windows t
+            max-mini-window-height .85)
+
+    in my `.emacs' file, so the mini-buffer may use 85% of the screen,
+    and quickly shrinks when fewer lines are needed.  The mini-buffer
+    contents disappear at the next keystroke, but you can recover the
+    Python backtrace by looking at the end of the `*Messages*' buffer.
+    In which case the `ffap' package in Emacs may be yet another friend!
+    From the `*Messages*' buffer, once `ffap' activated, merely put the
+    cursor on the file name of a Python module from the backtrace, and
+    `C-x C-f RET' will quickly open that source for you.
+
+. : Auto-reloading on save.
+
+    I found useful to automatically `pymacs-load' some Python files whenever
+    they get saved from Emacs.  Here is how I do it.  The code below assumes
+    that Python files meant for Pymacs are kept in `~/share/emacs/python'.
+
+      (defun fp-maybe-pymacs-reload ()
+        (let ((pymacsdir (expand-file-name "~/share/emacs/python/")))
+          (when (and (string-equal (file-name-directory buffer-file-name)
+                                   pymacsdir)
+                     (string-match "\\.py\\'" buffer-file-name))
+            (pymacs-load (substring buffer-file-name 0 -3)))))
+      (add-hook 'after-save-hook 'fp-maybe-pymacs-reload)
+
+.. Exemples.
+
+. : Paul Winkler's.
+
+.  , The problem.
+
+     Let's say I have a a module, call it `manglers.py', containing this
+     simple python function:
+
+         def break_on_whitespace(some_string):
+             words = some_string.split()
+             return '\n'.join(words)
+
+     The goal is telling Emacs about this function so that I can call it on
+     a region of text and replace the region with the result of the call.
+     And bind this action to a key, of course, let's say `[f7]'.
+
+     The Emacs buffer ought to be handled in some way.  If this is not on the
+     Emacs Lisp side, it has to be on the Python side, but we cannot escape
+     handling the buffer.  So, there is an equilibrium in the work to do for
+     the user, that could be displaced towards Emacs Lisp or towards Python.
+
+.  , Python side.
+
+     Here is a first draft for the Python side of the problem:
+
+         from Pymacs import lisp
+
+         def break_on_whitespace():
+             start = lisp.point()
+             end = lisp.mark(lisp.t)
+             if start > end:
+                 start, end = end, start
+             text = lisp.buffer_substring(start, end)
+             words = text.split()
+             replacement = '\n'.join(words)
+             lisp.delete_region(start, end)
+             lisp.insert(replacement)
+
+         interactions = {break_on_whitespace: ''}
+
+     For various stylistic reasons, this could be rewritten into:
+
+         from Pymacs import lisp
+         interactions = {}
+
+         def break_on_whitespace():
+             start, end = lisp.point(), lisp.mark(lisp.t)
+             words = lisp.buffer_substring(start, end).split()
+             lisp.delete_region(start, end)
+             lisp.insert('\n'.join(words))
+
+         interactions[break_on_whitespace] = ''
+
+     The above relies, in particular, on the fact that for those Emacs
+     Lisp functions used here, `start' and `end' may be given in any order.
+
+.  , Emacs side.
+
+     On the Emacs side, one would do:
+
+       (pymacs-load "manglers")
+       (global-set-key [f7] 'manglers-break-on-whitespace)
+
+. : The `rebox' tool.
+
+.  , The problem.
+
+     For comments held within boxes, it is painful to fill paragraphs, while
+     stretching or shrinking the surrounding box "by hand", as needed.
+     This piece of Python code eases my life on this.  It may be used
+     interactively from within Emacs through the Pymacs interface, or in
+     batch as a script which filters a single region to be reformatted.
+
+     In batch, the reboxing is driven by command options and arguments
+     and expects a complete, self-contained boxed comment from a file.
+     Emacs function `rebox-region' also presumes that the region encloses
+     a single boxed comment.  Emacs `rebox-comment' is different, as it
+     has to chase itself the extent of the surrounding boxed comment.
+
+.  , Python side.
+
+     The Python code is too big to be inserted in this documentation: see
+     file `Pymacs/rebox.py' in the Pymacs distribution.  You will observe
+     in the code that Pymacs specific features are used exclusively from
+     within the `pymacs_load_hook' function and the `Emacs_Rebox' class.
+     In batch mode, `Pymacs' is not even imported.  Here, we mean to
+     discuss some of the design choices in the context of Pymacs.
+
+     In batch mode, as well as with `rebox-region', the text to handle is
+     turned over to Python, and fully processed in Python, with practically
+     no Pymacs interaction while the work gets done.  On the other hand,
+     `rebox-comment' is rather Pymacs intensive: the comment boundaries
+     are chased right from the Emacs buffer, as directed by the function
+     `Emacs_Rebox.find_comment'.  Once the boundaries are found, the
+     remainder of the work is essentially done on the Python side.
+
+     Once the boxed comment has been reformatted in Python, the old comment
+     is removed in a single delete operation, the new comment is inserted in
+     a second operation, this occurs in `Emacs_Rebox.process_emacs_region'.
+     But by doing so, if point was within the boxed comment before the
+     reformatting, its precise position is lost.  To well preserve point,
+     Python might have driven all reformatting details directly in the
+     Emacs buffer.  We really preferred doing it all on the Python side:
+     as we gain legibility by expressing the algorithms in pure Python,
+     the same Python code may be used in batch or interactively, and we
+     avoid the slowdown that would result from heavy use of Emacs services.
+
+     To avoid completely loosing point, I kludged a `Marker' class,
+     which goal is to estimate the new value of point from the old.
+     Reformatting may change the amount of white space, and either delete
+     or insert an arbitrary number characters meant to draw the box.
+     The idea is to initially count the number of characters between the
+     beginning of the region and point, while ignoring any problematic
+     character.  Once the comment has been reboxed, point is advanced from
+     the beginning of the region until we get the same count of characters,
+     skipping all problematic characters.  This `Marker' class works fully
+     on the Python side, it does not involve Pymacs at all, but it does
+     solve a problem that resulted from my choice of keeping the data on
+     the Python side instead of handling it directly in the Emacs buffer.
+
+     We want a comment reformatting to appear as a single operation, in
+     the context of Emacs Undo.  The method `Emacs_Rebox.clean_undo_after'
+     handles the general case for this.  Not that we do so much in practice:
+     a reformatting implies one `delete-region' and one `insert', and maybe
+     some other little adjustements at `Emacs_Rebox.find_comment' time.
+     Even if this method scans and mofifies an Emacs Lisp list directly in
+     the Emacs memory, the code doing this stays neat and legible.  However,
+     I found out that the undo list may grow quickly when the Emacs buffer
+     use markers, with the consequence of making this routine so Pymacs
+     intensive that most of the CPU is spent there.  I rewrote that
+     routine in Emacs Lisp so it executes in a single Pymacs interaction.
+
+     Function `Emacs_Rebox.remainder_of_line' could have been written in
+     Python, but it was probably not worth going away from this one-liner in
+     Emacs Lisp.  Also, given this routine is often called by `find_comment',
+     a few Pymacs protocol interactions are spared this way.  This function
+     is useful when there is a need to apply a regexp already compiled on
+     the Python side, it is probably better fetching the line from Emacs
+     and do the pattern match on the Python side, than transmitting the
+     source of the regexp to Emacs for it to compile and apply it.
+
+     For refilling, I could have either used the refill algorithm built
+     within in Emacs, programmed a new one in Python, or relied on Ross
+     Paterson's `fmt', distributed by GNU and available on most Linuxes.
+     In fact, `refill_lines' prefers the latter.  My own Emacs setup is
+     such that the built-in refill algorithm is _already_ overridden by GNU
+     `fmt', and it really does a much better job.  Experience taught me
+     that calling an external program is fast enough to be very bearable,
+     even interactively.  If Python called Emacs to do the refilling, Emacs
+     would itself call GNU `fmt' in my case, I preferred that Python calls
+     GNU `fmt' directly.  I could have reprogrammed GNU `fmt' in Python.
+     Despite interesting, this is an uneasy project: `fmt' implements
+     the Knuth refilling algorithm, which depends on dynamic programming
+     techniques; Ross fine tuned them, and took care of many details.
+     If GNU `fmt' fails, for not being available, say, `refill_lines'
+     falls back on a dumb refilling algorithm, which is better than none.
+
+.  , Emacs side.
+
+     The Emacs recipe appears under the `Emacs usage' section, near the
+     beginning of `Pymacs/rebox.py', so I do not repeat it here.
+
+..
+                                        François Pinard,
+                                        pinard@iro.umontreal.ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/README.html	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,11 @@
+<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--: Faire
+  from Webert import transform
+  title, text = transform.transform('README')
+:-->
+<html>
+ <head><title>%(title)s</title></head>
+ <body>
+%(text)s
+ </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,24 @@
+Pymacs has been written by François Pinard after an idea from Cedric Adjih,
+and much influenced by Brian McErlean.  Here is the list of contributors.
+
+Brian McErlean		b.mcerlean@kainos.com
+Carel Fellinger		cfelling@iae.nl
+Carey Evans		careye@spamcop.net
+Cedric Adjih		adjih-pam@crepuscule.com
+			http://www.crepuscule.com/pyemacs/
+Christian Tanzer	tanzer@swing.co.at
+Dave Sellars		dsellars@windriver.com
+Dirk Vleugels		dvl@2scale.net
+Eli Zaretskii		eliz@is.elta.co.il
+François Pinard		pinard@iro.umontreal.ca
+			http://www.iro.umontreal.ca/~pinard
+Gerd Möllmann		gerd@gnu.org
+John Wiegley		johnw@gnu.org
+Marcin Qrczak Kowalczyk	qrczak@knm.org.pl
+Paul Foley		mycroft@actrix.gen.nz
+			http://users.actrix.co.nz/mycroft/
+Paul Winkler		slinkp23@yahoo.com
+Richard Stallman	rms@gnu.org
+Stefan Reichör		xsteve@riic.at
+Steffen Ries		steffen.ries@sympatico.ca
+Syver Enstad		syver.enstad@asker.online.no
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS-rebox	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,8 @@
+`rebox' has been written by François Pinard.  Here is the list of
+contributors.  Also see `ChangeLog-rebox' for a more details.
+
+Akim Demaille		demaille@inf.enst.fr
+Marc Feeley		feeley@iro.umontreal.ca
+Paul Eggert		eggert@twinsun.com
+Paul Provost		provost@virtualprototypes.ca
+Ulrich Drepper		drepper@gnu.org
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/TODO	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,34 @@
+* TODO for `Pymacs'				allout -*- outline -*-
+
+.. Internal cleanup.
+
+. : `(pymacs-eval "dir()")' shows too many things.
+
+.. Type conversions.
+
+. : Convert LISP hash tables into Python dicts and vice-versa.
+
+.. Iterator protocol.
+
+. : Allow iterating over vectors.
+
+.. Rebox.
+
+. : Debug the Undo list cleanup!
+
+. : Try the fall back refiller.
+
+. : Unicode boxes (suggested by Bruno).
+.  , U+231C..U+231F
+.  , U+25xx
+
+.. Debugging facilities.
+
+. : *Pymacs*
+.  , Indent.
+.  , Interpret numbers.
+.  , Highlight.
+
+. : Test suite.  (Brian has one.)
+
+. : Python shell link to helper.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright İ 2001, 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+"""\
+Interface between Emacs LISP and Python - Python process starter.
+
+This small bootstrap is so Pymacs modules can be kept in compiled form.
+"""
+
+import sys
+from Pymacs import pymacs
+apply(pymacs.main, sys.argv[1:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services.bat	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+@python "%~dpn0" %*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs.el	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,631 @@
+;;; Interface between Emacs Lisp and Python - Lisp part.
+;;; Copyright İ 2001, 2002 Progiciels Bourbeau-Pinard inc.
+;;; François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software Foundation,
+;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+;;; See the Pymacs documentation (in `README') for more information.
+
+;;; Published functions.
+
+(defvar pymacs-load-path nil
+  "List of additional directories to search for Python modules.
+The directories listed will be searched first, in the order given.")
+
+(defvar pymacs-trace-transit nil
+  "Keep the communication buffer growing, for debugging.
+When this variable is nil, the `*Pymacs*' communication buffer gets erased
+before each communication round-trip.  Setting it to `t' guarantees that
+the full communication is saved, which is useful for debugging.")
+
+(defvar pymacs-forget-mutability nil
+  "Transmit copies to Python instead of Lisp handles, as much as possible.
+When this variable is nil, most mutable objects are transmitted as handles.
+This variable is meant to be temporarily rebound to force copies.")
+
+(defvar pymacs-mutable-strings nil
+  "Prefer transmitting Lisp strings to Python as handles.
+When this variable is nil, strings are transmitted as copies, and the
+Python side thus has no way for modifying the original Lisp strings.
+This variable is ignored whenever `forget-mutability' is set.")
+
+(defvar pymacs-timeout-at-start 30
+  "Maximum reasonable time, in seconds, for starting `pymacs-services'.
+A machine should be pretty loaded before one needs to increment this.")
+
+(defvar pymacs-timeout-at-reply 5
+  "Expected maximum time, in seconds, to get the first line of a reply.
+The status of `pymacs-services' is checked at every such timeout.")
+
+(defvar pymacs-timeout-at-line 2
+  "Expected maximum time, in seconds, to get another line of a reply.
+The status of `pymacs-services' is checked at every such timeout.")
+
+(defun pymacs-load (module &optional prefix noerror)
+  "Import the Python module named MODULE into Emacs.
+Each function in the Python module is made available as an Emacs function.
+The Lisp name of each function is the concatenation of PREFIX with
+the Python name, in which underlines are replaced by dashes.  If PREFIX is
+not given, it defaults to MODULE followed by a dash.
+If NOERROR is not nil, do not raise error when the module is not found."
+  (interactive
+   (let* ((module (read-string "Python module? "))
+	  (default (concat (car (last (split-string module "\\."))) "-"))
+	  (prefix (read-string (format "Prefix? [%s] " default)
+			       nil nil default)))
+     (list module prefix)))
+  (message "Pymacs loading %s..." module)
+  (let ((lisp-code (pymacs-call "pymacs_load_helper" module prefix)))
+    (cond (lisp-code (let ((result (eval lisp-code)))
+		       (message "Pymacs loading %s...done" module)
+		       result))
+	  (noerror (message "Pymacs loading %s...failed" module) nil)
+	  (t (error "Pymacs loading %s...failed" module)))))
+
+(defun pymacs-eval (text)
+  "Compile TEXT as a Python expression, and return its value."
+  (interactive "sPython expression? ")
+  (let ((value (pymacs-call "eval" text)))
+    (when (interactive-p)
+      (message "%S" value))
+    value))
+
+(defun pymacs-exec (text)
+  "Compile and execute TEXT as a sequence of Python statements.
+This functionality is experimental, and does not appear to be useful."
+  (interactive "sPython statements? ")
+  (let ((value (pymacs-serve-until-reply
+		`(progn (princ "exec ") (prin1 ,text)))))
+    (when (interactive-p)
+      (message "%S" value))
+    value))
+
+(defun pymacs-call (function &rest arguments)
+  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
+FUNCTION is a string denoting the Python function, ARGUMENTS are separate
+Lisp expressions, one per argument.  Immutable Lisp constants are converted
+to Python equivalents, other structures are converted into Lisp handles."
+  (pymacs-apply function arguments))
+
+(defun pymacs-apply (function arguments)
+  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
+FUNCTION is a string denoting the Python function, ARGUMENTS is a list of
+Lisp expressions.  Immutable Lisp constants are converted to Python
+equivalents, other structures are converted into Lisp handles."
+  (pymacs-serve-until-reply `(pymacs-print-for-apply ',function ',arguments)))
+
+;;; Integration details.
+
+;; Python functions and modules should ideally look like Lisp functions and
+;; modules.  This page tries to increase the integration seamlessness.
+
+(defadvice documentation (around pymacs-ad-documentation activate)
+  ;; Integration of doc-strings.
+  (let* ((reference (pymacs-python-reference function))
+	 (python-doc (when reference
+		       (pymacs-eval (format "doc_string(%s)" reference)))))
+    (if (or reference python-doc)
+	(setq ad-return-value
+	      (concat
+	       "It interfaces to a Python function.\n\n"
+	       (when python-doc
+		 (if raw python-doc (substitute-command-keys python-doc)))))
+      ad-do-it)))
+
+(defun pymacs-python-reference (object)
+  ;; Return the text reference of a Python object if possible, else nil.
+  (when (functionp object)
+    (let* ((definition (indirect-function object))
+	   (body (and (pymacs-proper-list-p definition)
+		      (> (length definition) 2)
+		      (eq (car definition) 'lambda)
+		      (cddr definition))))
+      (when (and body (listp (car body)) (eq (caar body) 'interactive))
+	;; Skip the interactive specification of a function.
+	(setq body (cdr body)))
+      (when (and body
+		 ;; Advised functions start with a string.
+		 (not (stringp (car body)))
+		 ;; Python trampolines hold exactly one expression.
+		 (= (length body) 1))
+	(let ((expression (car body)))
+	  ;; EXPRESSION might now hold something like:
+	  ;;    (pymacs-apply (quote (pymacs-python . N)) ARGUMENT-LIST)
+	  (when (and (pymacs-proper-list-p expression)
+		     (= (length expression) 3)
+		     (eq (car expression) 'pymacs-apply)
+		     (eq (car (cadr expression)) 'quote))
+	    (setq object (cadr (cadr expression))))))))
+  (when (eq (car-safe object) 'pymacs-python)
+    (format "python[%d]" (cdr object))))
+
+;; The following functions are experimental -- they are not satisfactory yet.
+
+(defun pymacs-file-handler (operation &rest arguments)
+  ;; Integration of load-file, autoload, etc.
+  ;; Emacs might want the contents of some `MODULE.el' which does not exist,
+  ;; while there is a `MODULE.py' or `MODULE.pyc' file in the same directory.
+  ;; The goal is to generate a virtual contents for this `MODULE.el' file, as
+  ;; a set of Lisp trampoline functions to the Python module functions.
+  ;; Python modules can then be loaded or autoloaded as if they were Lisp.
+  ;(message "** %S %S" operation arguments)
+  (cond ((and (eq operation 'file-readable-p)
+	      (let ((module (substring (car arguments) 0 -3)))
+		(or (pymacs-file-force operation arguments)
+		    (file-readable-p (concat module ".py"))
+		    (file-readable-p (concat module ".pyc"))))))
+	((and (eq operation 'load)
+	      (not (pymacs-file-force
+		    'file-readable-p (list (car arguments))))
+	      (file-readable-p (car arguments)))
+	 (let ((lisp-code (pymacs-call "pymacs_load_helper"
+				       (substring (car arguments) 0 -3)
+				       nil)))
+	   (unless lisp-code
+	     (error "Python import error"))
+	   (eval lisp-code)))
+	((and (eq operation 'insert-file-contents)
+	      (not (pymacs-file-force
+		    'file-readable-p (list (car arguments))))
+	      (file-readable-p (car arguments)))
+	 (let ((lisp-code (pymacs-call "pymacs_load_helper"
+				       (substring (car arguments) 0 -3)
+				       nil)))
+	   (unless lisp-code
+	     (error "Python import error"))
+	   (insert (prin1-to-string lisp-code))))
+	(t (pymacs-file-force operation arguments))))
+
+(defun pymacs-file-force (operation arguments)
+  ;; Bypass the file handler.
+  (let ((inhibit-file-name-handlers
+	 (cons 'pymacs-file-handler
+	       (and (eq inhibit-file-name-operation operation)
+		    inhibit-file-name-handlers)))
+	(inhibit-file-name-operation operation))
+    (apply operation arguments)))
+
+;(add-to-list 'file-name-handler-alist '("\\.el\\'" . pymacs-file-handler))
+
+;;; Gargabe collection of Python IDs.
+
+;; Python objects which have no Lisp representation are allocated on the
+;; Python side as `python[INDEX]', and INDEX is transmitted to Emacs, with
+;; the value to use on the Lisp side for it.  Whenever Lisp does not need a
+;; Python object anymore, it should be freed on the Python side.  The
+;; following variables and functions are meant to fill this duty.
+
+(defvar pymacs-use-hash-tables nil
+  "Automatically set to t if hash tables are available.")
+
+(defvar pymacs-used-ids nil
+  "List of received IDs, currently allocated on the Python side.")
+
+(defvar pymacs-weak-hash nil
+  "Weak hash table, meant to find out which IDs are still needed.")
+
+(defvar pymacs-gc-wanted nil
+  "Flag if it is time to clean up unused IDs on the Python side.")
+
+(defvar pymacs-gc-running nil
+  "Flag telling that a Pymacs garbage collection is in progress.")
+
+(defvar pymacs-gc-timer nil
+  "Timer to trigger Pymacs garbage collection at regular time intervals.
+The timer is used only if `post-gc-hook' is not available.")
+
+(defun pymacs-schedule-gc ()
+  (unless pymacs-gc-running
+    (setq pymacs-gc-wanted t)))
+
+(defun pymacs-garbage-collect ()
+  ;; Clean up unused IDs on the Python side.
+  (when pymacs-use-hash-tables
+    (let ((pymacs-gc-running t)
+	  (pymacs-forget-mutability t)
+	  (ids pymacs-used-ids)
+	  used-ids unused-ids)
+      (while ids
+	(let ((id (car ids)))
+	  (setq ids (cdr ids))
+	  (if (gethash id pymacs-weak-hash)
+	      (setq used-ids (cons id used-ids))
+	    (setq unused-ids (cons id unused-ids)))))
+      ;;(message "** pymacs-garbage-collect %d %d"
+      ;;         (length used-ids) (length unused-ids))
+      (setq pymacs-used-ids used-ids
+	    pymacs-gc-wanted nil)
+      (when unused-ids
+	(pymacs-apply "free_python" unused-ids)))))
+
+(defun pymacs-defuns (arguments)
+  ;; Take one argument, a list holding a number of items divisible by 3.  The
+  ;; first argument is an INDEX, the second is a NAME, the third is the
+  ;; INTERACTION specification, and so forth.  Register Python INDEX with a
+  ;; function with that NAME and INTERACTION on the Lisp side.  The strange
+  ;; calling convention is to minimise quoting at call time.
+  (while (>= (length arguments) 3)
+    (let ((index (nth 0 arguments))
+	  (name (nth 1 arguments))
+	  (interaction (nth 2 arguments)))
+      (fset name (pymacs-defun index interaction))
+      (setq arguments (nthcdr 3 arguments)))))
+
+(defun pymacs-defun (index interaction)
+  ;; Register INDEX on the Lisp side with a Python object that is a function,
+  ;; and return a lambda form calling that function.  If the INTERACTION
+  ;; specification is nil, the function is not interactive.  Otherwise, the
+  ;; function is interactive, INTERACTION is then either a string, or the
+  ;; index of an argument-less Python function returning the argument list.
+  (let ((object (pymacs-python index)))
+    (cond ((null interaction)
+	   `(lambda (&rest arguments)
+	      (pymacs-apply ',object arguments)))
+	  ((stringp interaction)
+	   `(lambda (&rest arguments)
+	      (interactive ,interaction)
+	      (pymacs-apply ',object arguments)))
+	  (t `(lambda (&rest arguments)
+		(interactive (pymacs-call ',(pymacs-python interaction)))
+		(pymacs-apply ',object arguments))))))
+
+(defun pymacs-python (index)
+  ;; Register on the Lisp side a Python object having INDEX, and return it.
+  ;; The result is meant to be recognised specially by `print-for-eval', and
+  ;; in the function position by `print-for-apply'.
+  (let ((object (cons 'pymacs-python index)))
+    (when pymacs-use-hash-tables
+      (puthash index object pymacs-weak-hash)
+      (setq pymacs-used-ids (cons index pymacs-used-ids)))
+    object))
+
+;;; Generating Python code.
+
+;; Many Lisp expressions cannot fully be represented in Python, at least
+;; because the object is mutable on the Lisp side.  Such objects are allocated
+;; somewhere into a vector of handles, and the handle index is used for
+;; communication instead of the expression itself.
+
+(defvar pymacs-lisp nil
+  "Vector of handles to hold transmitted expressions.")
+
+(defvar pymacs-freed-list nil
+  "List of unallocated indices in Lisp.")
+
+;; When the Python CG is done with a Lisp object, a communication occurs so to
+;; free the object on the Lisp side as well.
+
+(defun pymacs-allocate-lisp (expression)
+  ;; This function allocates some handle for an EXPRESSION, and return its
+  ;; index.
+  (unless pymacs-freed-list
+    (let* ((previous pymacs-lisp)
+	   (old-size (length previous))
+	   (new-size (if (zerop old-size) 100 (+ old-size (/ old-size 2))))
+	   (counter new-size))
+      (setq pymacs-lisp (make-vector new-size nil))
+      (while (> counter 0)
+	(setq counter (1- counter))
+	(if (< counter old-size)
+	    (aset pymacs-lisp counter (aref previous counter))
+	  (setq pymacs-freed-list (cons counter pymacs-freed-list))))))
+  (let ((index (car pymacs-freed-list)))
+    (setq pymacs-freed-list (cdr pymacs-freed-list))
+    (aset pymacs-lisp index expression)
+    index))
+
+(defun pymacs-free-lisp (&rest indices)
+  ;; This function is triggered from Python side for Lisp handles which lost
+  ;; their last reference.  These references should be cut on the Lisp side as
+  ;; well, or else, the objects will never be garbage-collected.
+  (while indices
+    (let ((index (car indices)))
+      (aset pymacs-lisp index nil)
+      (setq pymacs-freed-list (cons index pymacs-freed-list)
+	    indices (cdr indices)))))
+
+(defun pymacs-print-for-apply-expanded (function arguments)
+  ;; This function acts like `print-for-apply', but produce arguments which
+  ;; are expanded copies whenever possible, instead of handles.  Proper lists
+  ;; are turned into Python lists, vectors are turned into Python tuples.
+  (let ((pymacs-forget-mutability t))
+    (pymacs-print-for-apply function arguments)))
+
+(defun pymacs-print-for-apply (function arguments)
+  ;; This function prints a Python expression calling FUNCTION, which is a
+  ;; string naming a Python function, or a Python reference, over all its
+  ;; ARGUMENTS, which are Lisp expressions.
+  (let ((separator "")
+	argument)
+    (if (eq (car-safe function) 'pymacs-python)
+	(princ (format "python[%d]" (cdr function)))
+      (princ function))
+    (princ "(")
+    (while arguments
+      (setq argument (car arguments)
+	    arguments (cdr arguments))
+      (princ separator)
+      (setq separator ", ")
+      (pymacs-print-for-eval argument))
+    (princ ")")))
+
+(defun pymacs-print-for-eval (expression)
+  ;; This function prints a Python expression out of a Lisp EXPRESSION.
+  (let (done)
+    (cond ((not expression)
+	   (princ "None")
+	   (setq done t))
+	  ((numberp expression)
+	   (princ expression)
+	   (setq done t))
+	  ((stringp expression)
+	   (when (or pymacs-forget-mutability
+		     (not pymacs-mutable-strings))
+	     (let ((text (copy-sequence expression)))
+	       (set-text-properties 0 (length text) nil text)
+	       (princ (mapconcat 'identity
+				 (split-string (prin1-to-string text) "\n")
+				 "\\n")))
+	     (setq done t)))
+	  ((symbolp expression)
+	   (let ((name (symbol-name expression)))
+	     ;; The symbol can only be transmitted when in the main oblist.
+	     (when (eq expression (intern-soft name))
+	       (cond
+		((save-match-data
+		   (string-match "^[A-Za-z][-A-Za-z0-9]*$" name))
+		 (princ "lisp.")
+		 (princ (mapconcat 'identity (split-string name "-") "_")))
+		(t (princ "lisp[")
+		   (prin1 name)
+		   (princ "]")))
+	       (setq done t))))
+	  ((vectorp expression)
+	   (when pymacs-forget-mutability
+	     (let ((limit (length expression))
+		   (counter 0))
+	       (princ "(")
+	       (while (< counter limit)
+		 (unless (zerop counter)
+		   (princ ", "))
+		 (pymacs-print-for-eval (aref expression counter)))
+	       (when (= limit 1)
+		 (princ ","))
+	       (princ ")")
+	       (setq done t))))
+	  ((eq (car-safe expression) 'pymacs-python)
+	   (princ "python[")
+	   (princ (cdr expression))
+	   (princ "]"))
+	  ((pymacs-proper-list-p expression)
+	   (when pymacs-forget-mutability
+	     (princ "[")
+	     (pymacs-print-for-eval (car expression))
+	     (while (setq expression (cdr expression))
+	       (princ ", ")
+	       (pymacs-print-for-eval (car expression)))
+	     (princ "]")
+	     (setq done t))))
+    (unless done
+      (let ((class (cond ((vectorp expression) "Vector")
+			 ((and pymacs-use-hash-tables
+			       (hash-table-p expression))
+			  "Table")
+			 ((bufferp expression) "Buffer")
+			 ((pymacs-proper-list-p expression) "List")
+			 (t "Lisp"))))
+	(princ class)
+	(princ "(")
+	(princ (pymacs-allocate-lisp expression))
+	(princ ")")))))
+
+;;; Communication protocol.
+
+(defvar pymacs-transit-buffer nil
+  "Communication buffer between Emacs and Python.")
+
+;; The principle behind the communication protocol is that it is easier to
+;; generate than parse, and that each language already has its own parser.
+;; So, the Emacs side generates Python text for the Python side to interpret,
+;; while the Python side generates Lisp text for the Lisp side to interpret.
+;; About nothing but expressions are transmitted, which are evaluated on
+;; arrival.  The pseudo `reply' function is meant to signal the final result
+;; of a series of exchanges following a request, while the pseudo `error'
+;; function is meant to explain why an exchange could not have been completed.
+
+;; The protocol itself is rather simple, and contains human readable text
+;; only.  A message starts at the beginning of a line in the communication
+;; buffer, either with `>' for the Lisp to Python direction, or `<' for the
+;; Python to Lisp direction.  This is followed by a decimal number giving the
+;; length of the message text, a TAB character, and the message text itself.
+;; Message direction alternates systematically between messages, it never
+;; occurs that two successive messages are sent in the same direction.  The
+;; first message is received from the Python side, it is `(version VERSION)'.
+
+(defun pymacs-start-services ()
+  ;; This function gets called automatically, as needed.
+  (let ((buffer (get-buffer-create "*Pymacs*")))
+    (with-current-buffer buffer
+      (buffer-disable-undo)
+      (save-match-data
+	;; Launch the Python helper.
+	(let ((process (apply 'start-process "pymacs" buffer "pymacs-services"
+			      (mapcar 'expand-file-name pymacs-load-path))))
+	  (process-kill-without-query process)
+	  ;; Receive the synchronising reply.
+	  (while (progn
+		   (goto-char (point-min))
+		   (not (re-search-forward "<\\([0-9]+\\)\t" nil t)))
+	    (unless (accept-process-output process pymacs-timeout-at-start)
+	      (error "Pymacs helper did not start within %d seconds."
+		     pymacs-timeout-at-start)))
+	  (let ((marker (process-mark process))
+		(limit-position (+ (match-end 0)
+				   (string-to-number (match-string 1)))))
+	    (while (< (marker-position marker) limit-position)
+	      (unless (accept-process-output process pymacs-timeout-at-start)
+		(error "Pymacs helper probably was interrupted at start.")))))
+	;; Check that synchronisation occurred.
+	(goto-char (match-end 0))
+	(let ((reply (read (current-buffer))))
+	  (if (and (pymacs-proper-list-p reply)
+		   (= (length reply) 2)
+		   (eq (car reply) 'pymacs-version))
+	      (unless (string-equal (cadr reply) "@VERSION@")
+		(error "Pymacs Lisp version is @VERSION@, Python is %s."
+		       (cadr reply)))
+	    (error "Pymacs got an invalid initial reply.")))))
+    (setq pymacs-use-hash-tables (and (fboundp 'make-hash-table)
+				      (fboundp 'gethash)
+				      (fboundp 'puthash)))
+    (when pymacs-use-hash-tables
+      (if pymacs-weak-hash
+	  ;; A previous Pymacs session occurred in *this* Emacs session.  Some
+	  ;; IDs may hang around, which do not correspond to anything on the
+	  ;; Python side.  Python should not recycle such IDs for new objects.
+	  (when pymacs-used-ids
+	    (let ((pymacs-transit-buffer buffer)
+		  (pymacs-forget-mutability t))
+	      (pymacs-apply "zombie_python" pymacs-used-ids)))
+	(setq pymacs-weak-hash (make-hash-table :weakness 'value)))
+      (if (boundp 'post-gc-hook)
+	  (add-hook 'post-gc-hook 'pymacs-schedule-gc)
+	(setq pymacs-gc-timer (run-at-time 20 20 'pymacs-schedule-gc))))
+    ;; If nothing failed, only then declare the Pymacs has started!
+    (setq pymacs-transit-buffer buffer)))
+
+(defun pymacs-terminate-services ()
+  ;; This function is mainly provided for documentation purposes.
+  (interactive)
+  (garbage-collect)
+  (pymacs-garbage-collect)
+  (when (or (not pymacs-used-ids)
+	    (yes-or-no-p "\
+Killing the helper might create zombie objects.  Kill? "))
+    (cond ((boundp 'post-gc-hook)
+	   (remove-hook 'post-gc-hook 'pymacs-schedule-gc))
+	  ((timerp pymacs-gc-timer)
+	   (cancel-timer pymacs-gc-timer)))
+    (when pymacs-transit-buffer
+      (kill-buffer pymacs-transit-buffer))
+    (setq pymacs-gc-running nil
+	  pymacs-gc-timer nil
+	  pymacs-transit-buffer nil
+	  pymacs-lisp nil
+	  pymacs-freed-list nil)))
+
+(defun pymacs-serve-until-reply (inserter)
+  ;; This function evals INSERTER to print a Python request.  It sends it to
+  ;; the Python helper, and serves all sub-requests coming from the
+  ;; Python side, until either a reply or an error is finally received.
+  (unless (and pymacs-transit-buffer
+	       (buffer-name pymacs-transit-buffer)
+	       (get-buffer-process pymacs-transit-buffer))
+    (pymacs-start-services))
+  (when pymacs-gc-wanted
+    (pymacs-garbage-collect))
+  (let (done value)
+    (while (not done)
+      (let* ((text (pymacs-round-trip inserter))
+	     (reply (condition-case info
+			(eval text)
+		      (error (cons 'pymacs-oops (prin1-to-string info))))))
+	(cond ((not (consp reply))
+	       (setq inserter
+		     `(pymacs-print-for-apply 'reply '(,reply))))
+	      ((eq 'pymacs-reply (car reply))
+	       (setq done t value (cdr reply)))
+	      ((eq 'pymacs-error (car reply))
+	       (error "Python: %s" (cdr reply)))
+	      ((eq 'pymacs-oops (car reply))
+	       (setq inserter
+		     `(pymacs-print-for-apply 'error '(,(cdr reply)))))
+	      ((eq 'pymacs-expand (car reply))
+	       (setq inserter
+		     `(pymacs-print-for-apply-expanded 'reply
+						       '(,(cdr reply)))))
+	      (t (setq inserter
+		       `(pymacs-print-for-apply 'reply '(,reply)))))))
+    value))
+
+(defun pymacs-reply (expression)
+  ;; This pseudo-function returns `(pymacs-reply . EXPRESSION)'.
+  ;; `serve-until-reply' later recognises this form.
+  (cons 'pymacs-reply expression))
+
+(defun pymacs-error (expression)
+  ;; This pseudo-function returns `(pymacs-error . EXPRESSION)'.
+  ;; `serve-until-reply' later recognises this form.
+  (cons 'pymacs-error expression))
+
+(defun pymacs-expand (expression)
+  ;; This pseudo-function returns `(pymacs-expand . EXPRESSION)'.
+  ;; `serve-until-reply' later recognises this form.
+  (cons 'pymacs-expand expression))
+
+(defun pymacs-round-trip (inserter)
+  ;; This function evals INSERTER to print a Python request.  It sends it to
+  ;; the Python helper, awaits for any kind of reply, and returns it.
+  (with-current-buffer pymacs-transit-buffer
+    (unless pymacs-trace-transit
+      (erase-buffer))
+    (let* ((process (get-buffer-process pymacs-transit-buffer))
+	   (status (process-status process))
+	   (marker (process-mark process))
+	   (moving (= (point) marker))
+	   send-position reply-position reply)
+      (save-excursion
+	(save-match-data
+	  ;; Encode request.
+	  (setq send-position (marker-position marker))
+	  (let ((standard-output marker))
+	    (eval inserter))
+	  (goto-char marker)
+	  (unless (= (preceding-char) ?\n)
+	    (princ "\n" marker))
+	  ;; Send request text.
+	  (goto-char send-position)
+	  (insert (format ">%d\t" (- marker send-position)))
+	  (setq reply-position (marker-position marker))
+	  (process-send-region process send-position marker)
+	  ;; Receive reply text.
+	  (while (and (eq status 'run)
+		      (progn
+			(goto-char reply-position)
+			(not (re-search-forward "<\\([0-9]+\\)\t" nil t))))
+	    (unless (accept-process-output process pymacs-timeout-at-reply)
+	      (setq status (process-status process))))
+	  (when (eq status 'run)
+	    (let ((limit-position (+ (match-end 0)
+				     (string-to-number (match-string 1)))))
+	      (while (and (eq status 'run)
+			  (< (marker-position marker) limit-position))
+		(unless (accept-process-output process pymacs-timeout-at-line)
+		  (setq status (process-status process))))))
+	  ;; Decode reply.
+	  (if (not (eq status 'run))
+	      (error "Pymacs helper status is `%S'." status)
+	    (goto-char (match-end 0))
+	    (setq reply (read (current-buffer))))))
+      (when (and moving (not pymacs-trace-transit))
+	(goto-char marker))
+      reply)))
+
+(defun pymacs-proper-list-p (expression)
+  ;; Tell if a list is proper, id est, that it is `nil, or ends with `nil'.
+  (cond ((not expression))
+	((consp expression) (not (cdr (last expression))))))
+
+(provide 'pymacs)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/rebox	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# Copyright İ 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2002.
+
+"""\
+Handling of boxed comments in various box styles.
+"""
+
+import sys
+from Pymacs import rebox
+apply(rebox.main, tuple(sys.argv[1:]))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/setup-emacs.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+# Copyright İ 2001, 2002 Progiciels Bourbeau-Pinard inc.
+# François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+"""\
+Installer tool for Pymacs `pymacs.el'.
+
+Usage: setup [OPTION]
+
+  -H   Display this help, then exit.
+  -V   Display package name and version, then exit.
+
+  -i         Interactively check selected options with user.
+  -n         Dry run: merely display selected options.
+  -g GROUP   Install with write permissions for that user GROUP.
+  -e         Load `.emacs' before checking Emacs `load-path'.
+
+  -l LISPDIR   Install `pymacs.el' in LISPDIR.
+  -E EMACS     Use that executable for EMACS, if not `emacs'.
+"""
+
+import os, string, sys
+
+sys.path.insert(0, '.')
+from Pymacs import package, version
+del sys.path[0]
+
+AUTOCONF = ()                           # neither a string nor None
+
+class run:
+    interactive = 0
+    dry = 0
+    group = None
+    dot_emacs = 0
+    lispdir = AUTOCONF
+    emacs = 'emacs'
+
+def main(*arguments):
+    import getopt
+    options, arguments = getopt.getopt(arguments, 'E:HVeg:il:n')
+    for option, value in options:
+        if option == '-E' and value:
+            run.emacs = value
+        elif option == '-H':
+            sys.stdout.write(__doc__)
+            sys.exit(0)
+        elif option == '-V':
+            sys.stdout.write('%s-%s' % (package, version))
+            sys.exit(0)
+        elif option == '-e':
+            run.dot_emacs = 1
+        elif option == '-g' and value:
+            run.group = value
+        elif option == '-i':
+            run.interactive = 1
+        elif option == '-l' and value:
+            if value in ('none', 'None'):
+                run.lispdir = None
+            else:
+                run.lispdir = [value]
+    auto_configure()
+    if run.interactive:
+        check_with_user()
+    check_choices()
+    if not run.dry:
+        complete_install()
+
+def auto_configure():
+    if run.lispdir is AUTOCONF:
+        run.lispdir = []
+        import tempfile
+        script = tempfile.mktemp()
+        if sys.platform == 'win32':
+            # Win32 names starting with tilde and Emacs are unhappy together.
+            path, file = os.path.split(script)
+            script = os.path.join(path, 'a' + file)
+        try:
+            open(script, 'w').write('(message "%S" load-path)')
+            load_config = ''
+            if run.dot_emacs:
+                config = os.path.join(os.environ['HOME'], '.emacs')
+                for name in config, config + '.el', config + '.elc':
+                    if os.path.isfile(name):
+                        # Quote!  Spaces are common in Win32 file names.
+                        load_config = ' -l "%s"' % name
+                    break
+            # Quote!  Spaces are common in Win32 file names.
+            text = os.popen('%s -batch%s -l "%s" 2>&1'
+                            % (run.emacs, load_config, script)).read()
+        finally:
+            os.remove(script)
+        position = string.find(text, '("')
+        if position >= 0:
+            text = text[position:]
+        if text[-1] == '\n':
+            text = text[:-1]
+        assert text[0] == '(' and text[-1] == ')', text
+        for path in string.split(text[1:-1]):
+            assert path[0] == '"' and path[-1] == '"', path
+            path = path[1:-1]
+            if os.access(path, 7):
+                run.lispdir.append(path)
+
+def check_with_user():
+    sys.stderr.write("""\
+Install tool for %s version %s.
+"""
+                     % (package, version))
+    run.lispdir = user_select('lispdir', run.lispdir, """\
+This is where `pymacs.el', the Emacs side code of Pymacs, should go:
+somewhere on your Emacs `load-path'.
+""")
+
+def user_select(name, values, message):
+    write = sys.stderr.write
+    readline = sys.stdin.readline
+    if values is None:
+        write("""\
+
+Enter a value for `%s', or merely type `Enter' if you do not want any.
+"""
+              % name)
+        write(message)
+        while 1:
+            write('%s? ' % name)
+            text = string.strip(readline())
+            if not text:
+                return None
+            if os.access(os.path.expanduser(text), 7):
+                return [text]
+            write("""\
+
+This directory does not exist, or is not writable.  Please reenter it.
+""")
+    if len(values) == 1:
+        return values
+    if values == []:
+        write("""\
+
+Pymacs is not likely to install properly, as the installer may not currently
+write in any directory for `%s'.  Running as `root' might help you.
+Or else, you will most probably have to revise a bit your work setup.
+"""
+              % name)
+        write(message)
+        return values
+    write("""\
+
+There are many possibilities for `%s', please select one of them by
+typing its number followed by `Enter'.  A mere `Enter' selects the first.
+"""
+          % name)
+    write(message)
+    write('\n')
+    for counter in range(len(values)):
+        write('%d. %s\n' % (counter + 1, values[counter]))
+    while 1:
+        write('[1-%d]? ' % len(values))
+        text = string.strip(readline())
+        if not text:
+            return [values[0]]
+        try:
+            counter = int(text)
+        except ValueError:
+            pass
+        else:
+            if 1 <= counter <= len(values):
+                return [values[counter-1]]
+        write("""\
+This is not a valid choice.  Please retry.
+""")
+
+def check_choices():
+    write = sys.stderr.write
+    error = 0
+    if run.lispdir is not None:
+        if run.lispdir and os.access(os.path.expanduser(run.lispdir[0]), 7):
+            run.lispdir = run.lispdir[0]
+        else:
+            write("\
+Use `-l LISPDIR' to select where `pymacs.el' should go.\n")
+            error = 1
+    if error:
+        write("ERROR: Installation aborted!\n"
+              "       Try `%s -i'.\n" % sys.argv[0])
+        sys.exit(1)
+    write(
+        '\n'
+        "Directory selection for installing Pymacs:\n"
+        "  lispdir   = %(lispdir)s\n"
+        '\n'
+        % run.__dict__)
+
+def complete_install():
+    run.substitute = {'PACKAGE': package, 'VERSION': version}
+    if run.lispdir:
+        goal = os.path.join(run.lispdir, 'pymacs.el')
+        install('pymacs.el', goal, 0644)
+        compile_lisp(goal)
+
+def install(source, destination, permissions):
+    sys.stderr.write('Installing %s\n' % destination)
+    write = open(destination, 'w').write
+    produce_at = 0
+    #print '*', run.substitute
+    for fragment in string.split(open(source).read(), '@'):
+        #print '**', produce_at, `fragment`
+        if produce_at:
+            replacement = run.substitute.get(fragment)
+            #print '***', replacement
+            if replacement is None:
+                write('@')
+                write(fragment)
+            else:
+                write(replacement)
+                produce_at = 0
+        else:
+            write(fragment)
+            produce_at = 1
+    write = None
+    set_attributes(destination, permissions)
+
+def compile_lisp(name):
+    sys.stderr.write('Compiling %s\n' % name)
+    os.system('%s -batch -f batch-byte-compile %s' % (run.emacs, name))
+    set_attributes(name + 'c', 0644)
+
+def set_attributes(name, permissions):
+    if run.group:
+        os.chown(name, run.group)
+        permissions = permissions | 0020
+    os.chmod(name, permissions)
+
+if __name__ == '__main__':
+    apply(main, sys.argv[1:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/Pymacs-0.20/setup.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import sys
+sys.path.insert(0, '.')
+from Pymacs import package, version
+del sys.path[0]
+
+from distutils.core import setup
+
+setup(name=package,
+      version=version,
+      description='Interface between Emacs LISP and Python.',
+      author='François Pinard',
+      author_email='pinard@iro.umontreal.ca',
+      url='http://www.iro.umontreal.ca/~pinard',
+      scripts=['pymacs-services', 'pymacs-services.bat', 'rebox'],
+      packages=['Pymacs'])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/bike.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,430 @@
+" Bicycle Repair Man integration for Vim
+" Version 0.3
+" Copyright (c) 2003 Marius Gedminas <mgedmin@delfi.lt>
+"
+" Needs Vim 6.x with python interpreter (Python 2.2 or newer)
+" Installation instructions: just drop it into $HOME/.vim/plugin and you
+" should see the Bicycle Repair Menu appear in GVim (or you can check if
+" any of the BikeXxx commands are defined in console mode Vim).  If bike.vim
+" fails to load and you want to see the reason, try
+"   let g:bike_exceptions = 1
+"   source ~/.vim/plugin/bike.vim
+"
+" Configuration options you can add to your .vimrc:
+"   let g:bike_exceptions = 1           " show tracebacks on exceptions
+"   let g:bike_progress = 1             " show import progress
+"
+" Commands defined:
+"
+"   BikeShowScope
+"       Show current scope.  Sample of usage:
+"         autocmd CursorHold *.py BikeShowScope
+"
+"   <range> BikeShowType
+"       Show selected expression type.  The range is ignored, '<,'> is always
+"       used.  Use this in visual block mode.
+"
+"   BikeFindRefs
+"       Finds all references of the function/method/class defined in current
+"       line.
+"
+"   BikeFindDef
+"       Finds the definition of the function/method/class under cursor.
+"
+"   BikeRename
+"       Renames the function/method/class defined in current line.  Updates
+"       all references in all files known (i.e. imported) to Bicycle Repair
+"       Man.
+"
+"   <range> BikeExtract
+"       Extracts a part of the function/method into a new function/method.
+"       The range is ignored, '<,'> is always used.  Use this in visual mode.
+"
+"   BikeUndo
+"       Globally undoes the previous refactoring.
+"
+" Issues:
+"  - Saves all modified buffers to disk without asking the user -- not nice
+"  - Does not reimport files that were modified outside of Vim
+"  - Uses mktemp() -- I think that produces deprecation warnings in Python 2.3
+"  - BikeShowType, BikeExtract ignores the specified range, that's confusing.
+"    At least BikeExtract ought to work...
+"  - BikeShowType/BikeExtract or their GUI counterparts work when not in
+"    visual mode by using the previous values of '<,'>.  Might be confusing.
+"  - Would be nice if :BikeImport<CR> asked to enter package
+"  - Would be nice if :BikeRename myNewName<CR> worked
+"  - The code is not very robust (grep for XXX)
+
+"
+" Default settings for global configuration variables                   {{{1
+"
+
+" Set to 1 to see full tracebacks
+if !exists("g:bike_exceptions")
+    let g:bike_exceptions = 0
+endif
+
+" Set to 1 to see import progress
+if !exists("g:bike_progress")
+    let g:bike_progress = 0
+endif
+
+"
+" Initialization                                                        {{{1
+"
+
+" First check that Vim is sufficiently recent, that we have python interpreted
+" support, and that Bicycle Repair Man is available.
+"
+" If something is wrong, fail silently, as error messages every time vim
+" starts are very annoying.  But if the user wants to see why bike.vim failed
+" to load, she can let g:bike_exceptions = 1
+if version < 600
+    if g:bike_exceptions
+        echo 'Bicycle Repair Man needs Vim 6.0'
+    endif
+    finish
+endif
+
+if !has("python")
+    if g:bike_exceptions
+        echo 'Bicycle Repair Man needs Vim with Python interpreter support (2.2 or newer)'
+    endif
+    finish
+endif
+
+let s:has_bike=1
+python << END
+import vim
+import sys
+try:
+    if sys.version_info < (2, 2):
+        raise ImportError, 'Bicycle Repair Man needs Python 2.2 or newer'
+    import bike
+    bikectx = bike.init()
+    bikectx.isLoaded        # make sure bike package is recent enough
+except ImportError:
+    vim.command("let s:has_bike=0")
+    if vim.eval('g:bike_exceptions') not in (None, '', '0'):
+        raise
+END
+if !s:has_bike
+    finish
+endif
+
+" Use sane cpoptions
+let s:cpo_save = &cpo
+set cpo&vim
+
+"
+" Menu                                                                  {{{1
+"
+silent! aunmenu Bicycle\ Repair\ Man
+
+" Shortcuts available: ab-----h-jk--nopq----vw--z
+amenu <silent> Bicycle\ &Repair\ Man.-SEP1-
+\       :
+amenu <silent> Bicycle\ &Repair\ Man.&Find\ References
+\       :call <SID>BikeFindRefs()<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Find\ &Definition
+\       :call <SID>BikeFindDef()<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&List<tab>:cl
+\       :cl<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Current<tab>:cc
+\       :cc<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Next<tab>:cn
+\       :cn<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Previous<tab>:cp
+\       :cp<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&First<tab>:cfirst
+\       :cfirst<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.Las&t<tab>:clast
+\       :clast<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Older\ List<tab>:colder
+\       :colder<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.N&ewer\ List<tab>:cnewer
+\       :cnewer<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Window.&Update<tab>:cw
+\       :cw<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Window.&Open<tab>:copen
+\       :copen<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Resu&lts.&Window.&Close<tab>:cclose
+\       :cclose<CR>
+amenu <silent> Bicycle\ &Repair\ Man.-SEP2-
+\       :
+amenu <silent> Bicycle\ &Repair\ Man.&Rename
+\       :call <SID>BikeRename()<CR>
+amenu <silent> Bicycle\ &Repair\ Man.E&xtract\ Method
+\       :call <SID>BikeExtract('method')<CR>
+amenu <silent> Bicycle\ &Repair\ Man.&Extract\ Function
+\       :call <SID>BikeExtract('function')<CR>
+amenu <silent> Bicycle\ &Repair\ Man.&Undo
+\       :call <SID>BikeUndo()<CR>
+amenu <silent> Bicycle\ &Repair\ Man.-SEP3-
+\       :
+amenu <silent> Bicycle\ &Repair\ Man.Settin&gs.Import\ &Progress.&Enable
+\       :let g:bike_progress = 1<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Settin&gs.Import\ &Progress.&Disable
+\       :let g:bike_progress = 0<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Settin&gs.Full\ &Exceptions.&Enable
+\       :let g:bike_exceptions = 1<CR>
+amenu <silent> Bicycle\ &Repair\ Man.Settin&gs.Full\ &Exceptions.&Disable
+\       :let g:bike_exceptions = 0<CR>
+
+" Note: The three rename commands are basically identical.  The two extract
+" commands are also identical behind the scenes.
+
+"
+" Commands                                                              {{{1
+"
+
+command! BikeShowScope          call <SID>BikeShowScope()
+command! -range BikeShowType    call <SID>BikeShowType()
+command! BikeFindRefs           call <SID>BikeFindRefs()
+command! BikeFindDef            call <SID>BikeFindDef()
+
+command! BikeRename             call <SID>BikeRename()
+command! -range BikeExtract     call <SID>BikeExtract('function')
+command! BikeUndo               call <SID>BikeUndo()
+
+"
+" Implementation                                                        {{{1
+"
+
+" Query functions                                                       {{{2
+
+function! s:BikeShowScope()
+" Shows the scope under cursor
+    python << END
+fn = vim.current.buffer.name
+row, col = vim.current.window.cursor
+try:
+    print bikectx.getFullyQualifiedNameOfScope(fn, row)
+except:
+    show_exc()
+END
+endf
+
+function! s:BikeShowType()
+" Shows the inferred type of the selected expression
+    if col("'<") == 0            " mark not set
+        echo "Select a region first!"
+        return
+    endif
+    if line("'<") != line("'>")  " multiline selection
+        echo "Multi-line regions not supported"
+        " XXX deficiency of bikefacade interface, expressions can easily span
+        " several lines in Python
+        return
+    endif
+    python << END
+fn = vim.current.buffer.name
+row1, col1 = vim.current.buffer.mark('<')
+row2, col2 = vim.current.buffer.mark('>')
+try:
+    print bikectx.getTypeOfExpression(fn, row1, col1, col2)
+except:
+    show_exc()
+END
+endf
+
+function! s:BikeFindRefs()
+" Find all references to the item defined on current line
+    wall
+    python << END
+fn = vim.current.buffer.name
+row, col = vim.current.window.cursor
+try:
+    refs = bikectx.findReferencesByCoordinates(fn, row, col)
+    quickfixdefs(refs)
+except:
+    show_exc()
+END
+endf
+
+function! s:BikeFindDef()
+" Find all definitions of the item under cursor.  Ideally there should be only
+" one.
+    wall
+    python << END
+fn = vim.current.buffer.name
+row, col = vim.current.window.cursor
+try:
+    defs = bikectx.findDefinitionByCoordinates(fn, row, col)
+    quickfixdefs(defs)
+except:
+    show_exc()
+END
+endf
+
+" Refactoring commands                                                  {{{2
+
+function! s:BikeRename()
+" Rename a function/method/class.
+
+    let newname = inputdialog('Rename to: ')
+    wall
+    python << END
+fn = vim.current.buffer.name
+row, col = vim.current.window.cursor
+newname = vim.eval("newname")
+if newname:
+    try:
+        bikectx.setRenameMethodPromptCallback(renameMethodPromptCallback)
+        bikectx.renameByCoordinates(fn, row, col, newname)
+    except:
+        show_exc()
+    saveChanges()
+else:
+    print "Aborted"
+END
+endf
+
+function! s:BikeExtract(what)
+" Extract a piece of code into a separate function/method.  The argument
+" a:what can be 'method' or 'function'.
+    if col("'<") == 0            " mark not set
+        echo "Select a region first!"
+        return
+    endif
+    let newname = inputdialog('New function name: ')
+    wall
+    python << END
+fn = vim.current.buffer.name
+row1, col1 = vim.current.buffer.mark('<')
+row2, col2 = vim.current.buffer.mark('>')
+newname = vim.eval("newname")
+if newname:
+    try:
+		bikectx.extractMethod(fn, row1, col1, row2, col2, newname)
+    except:
+        show_exc()
+    saveChanges()
+else:
+    print "Aborted"
+END
+endf
+
+function! s:BikeUndo()
+" Undoes the last refactoring
+    wall
+python << END
+try:
+    bikectx.undo()
+    saveChanges()
+except bike.UndoStackEmptyException, e:
+    print "Nothing to undo"
+END
+endf
+
+"
+" Helper functions                                                      {{{1
+"
+
+" Python helpers
+
+python << END
+
+import tempfile
+import os
+import linecache
+
+modified = {}   # a dictionary whose keys are the names of files modifed
+                # in Vim since the last import
+
+def show_exc():
+    """Print exception according to bike settings."""
+    if vim.eval('g:bike_exceptions') not in (None, '', '0'):
+        import traceback
+        traceback.print_exc()
+    else:
+        type, value = sys.exc_info()[:2]
+        if value is not None:
+            print "%s: %s" % (type, value)
+        else:
+            print type
+
+def writedefs(defs, filename):
+    """Write a list of file locations to a file."""
+    ef = None
+    curdir = os.getcwd()
+    if not curdir.endswith(os.sep):
+        curdir = curdir + os.sep
+    for d in defs:
+        if not ef:
+            ef = open(filename, "w")
+        fn = d.filename
+        if fn.startswith(curdir):
+            fn = fn[len(curdir):]
+        line = linecache.getline(fn, d.lineno).strip()
+        res ="%s:%d: %3d%%: %s" % (fn, d.lineno, d.confidence, line)
+        print res
+        print >> ef, res
+    if ef:
+        ef.close()
+    return ef is not None
+
+def quickfixdefs(defs):
+    """Import a list of file locations into vim error list."""
+    fn = tempfile.mktemp()      # XXX unsafe
+    if writedefs(defs, fn):
+        vim.command('let old_errorfile = &errorfile')
+        vim.command('let old_errorformat = &errorformat')
+        vim.command(r'set errorformat=\%f:\%l:\ \%m')
+        vim.command("cfile %s" % fn)
+        vim.command('let &errorformat = old_errorformat')
+        vim.command('let &errorfile = old_errorfile')
+        os.unlink(fn)
+    else:
+        print "Not found"
+
+def renameMethodPromptCallback(filename, line, col1, col2):
+    """Verify that the call in a given file position should be renamed."""
+    vim.command('e +%d %s' % (line, filename))
+    vim.command('normal %d|' % col1)
+    vim.command('match Search /\%%%dl\%%>%dc\%%<%dc' % (line, col1, col2+1))
+    vim.command('redraw')
+    ans = vim.eval('confirm("Cannot deduce instance type.  Rename this call?",'
+                   ' "&Yes\n&No", 1, "Question")')
+    vim.command('match none')
+    if ans == '1':
+        return 1
+    else:
+        return 0
+
+
+def saveChanges():
+    """Save refactoring changes to the file system and reload the modified
+    files in Vim."""
+    # bikectx.save() returns a list of modified file names.  We should make
+    # sure that all those files are reloaded iff they were open in vim.
+    files = map(os.path.abspath, bikectx.save())
+
+    opened_files = {}
+    for b in vim.buffers:
+        if b.name is not None:
+            opened_files[os.path.abspath(b.name)] = b.name
+
+    for f in files:
+        try:
+            # XXX might fail when file name contains funny characters
+            vim.command("sp %s | q" % opened_files[f])
+        except KeyError:
+            pass
+
+    # Just in case:
+    vim.command("checktime")
+    vim.command("e")
+
+END
+
+" Make sure modified files are reimported into BRM
+autocmd BufWrite * python modified[os.path.abspath(vim.current.buffer.name)] = 1
+
+"
+" Cleanup                                                               {{{1
+"
+
+" Restore cpoptions
+let &cpo = s:cpo_save
+unlet s:cpo_save
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/bikeemacs.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,333 @@
+# Bicycle Repair Man integration with (X)Emacs
+# By Phil Dawes (2002)
+# Uses the fabulous Pymacs package by François Pinard
+
+from Pymacs import lisp, Let
+import bike
+reload(bike)
+from bike import bikefacade
+import StringIO, traceback
+import sys
+
+class EmacsLogger:
+    def __init__(self):
+        self.msg = ""
+    
+    def write(self,output):
+        self.msg +=output
+        if output.endswith("\n"):
+            lisp.message(self.msg)
+            self.msg = ""
+
+class NullLogger:
+    def write(self,output):
+        pass
+        
+logger = EmacsLogger()
+
+
+class ExceptionCatcherWrapper:
+
+    def __init__(self,myobj):
+        self.myobj = myobj
+    
+    def __getattr__(self,name):
+        return ExceptionInterceptor(self.myobj,name)
+        
+
+class ExceptionInterceptor:
+    def __init__(self,targetobj,name):
+        self.targetobj = targetobj
+        self.name = name
+    
+    def __call__(self,  *params, **kwparams ):
+        try:
+            return self.makeCall(params)
+        except:
+            traceback.print_exc()
+            lisp.error(str(sys.exc_info()[1]))
+
+    def makeCall(self,params):
+        argsstr="(self.targetobj"
+        for i in range(len(params)):
+            argsstr += ",params["+`i`+"]"
+        argsstr+=")"
+        return eval("self.targetobj.__class__."+self.name+argsstr)
+
+
+class BRMEmacs(object):
+    
+    def __init__(self,brmctx):
+        self.ctx = brmctx
+
+        lisp.require(lisp["python-mode"])
+        lisp("""
+        (defvar brm-menu nil "Menu for Bicycle Repair Man")
+         (easy-menu-define
+          brm-menu py-mode-map "Bicycle Repair Man"
+          '("BicycleRepairMan"
+                   "Queries"
+                   ["Find-References" brm-find-references]
+                   ["Find-Definition" brm-find-definition]
+                   "---"
+                   "Refactoring"
+                   ["Rename" brm-rename t]
+                   ["Extract-Method" brm-extract-method t]
+                   ["Extract-Local-Variable" brm-extract-local-variable t]
+                   ["Inline-Local-Variable" brm-inline-local-variable t]
+                   ["Undo Last Refactoring" brm-undo t]
+
+        ))
+        (add-hook 'python-mode-hook (lambda () (easy-menu-add brm-menu)))
+        """)
+        #           ["Move-Class-To-New-Module" brm-move-class t]
+        #           ["Move-Function-To-New-Module" brm-move-class t]
+
+        self.ctx.setProgressLogger(logger)
+
+
+    def rename(self,newname):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+        line,col = _getCoords()
+        brmctx.setRenameMethodPromptCallback(promptCallback)
+        try:
+            self.ctx.renameByCoordinates(filename,line,col,newname)
+            savedFiles = brmctx.save()
+            _revertSavedFiles(savedFiles)
+            lisp.set_marker(lisp.mark_marker(),None)
+        except bikefacade.CouldntLocateASTNodeFromCoordinatesException:
+            print >>logger,"Couldn't find AST Node. Are you renaming the declaration?"
+
+    def kill(self):        
+        self.ctx = None
+        self.ctx = bike.init()
+        self.ctx.setProgressLogger(logger)
+
+    def undo(self):
+        brmctx.undo()
+        savedFiles = brmctx.save()
+        _revertSavedFiles(savedFiles)
+
+    def find_references(self):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+        line,col = _getCoords()
+        refs = brmctx.findReferencesByCoordinates(filename,line,col)
+        _switchToConsole()
+        numRefs = 0
+        for ref in refs:
+            _insertRefLineIntoConsole(ref)
+            numRefs +=1
+        lisp.insert("Done - %d refs found\n"%numRefs)
+
+
+    def find_definition(self):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+        line,col = _getCoords()
+        defns = brmctx.findDefinitionByCoordinates(filename,line,col)
+
+        try:
+            firstdefn = defns.next()
+            lisp.find_file_other_window(firstdefn.filename)
+            lisp.goto_line(firstdefn.lineno)
+            lisp.forward_char(firstdefn.colno)
+        except StopIteration:
+            pass
+        else:
+            numRefs = 1
+            for defn in defns:
+                if numRefs == 1:
+                    _switchToConsole()
+                    _insertRefLineIntoConsole(firstdefn)
+                _insertRefLineIntoConsole(defn)
+                numRefs += 1
+
+
+    def inline_local_variable(self):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+        line,col = _getCoords()
+        brmctx.inlineLocalVariable(filename,line,col)
+        lisp.set_marker(lisp.mark_marker(),None)
+        _revertSavedFiles(brmctx.save())
+
+    def extract_local_variable(self,name):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+
+        bline,bcol = _getPointCoords()
+        lisp.exchange_point_and_mark()
+        eline,ecol = _getPointCoords()
+        lisp.exchange_point_and_mark()
+
+        brmctx.extractLocalVariable(filename,bline,bcol,eline,ecol,name)
+        lisp.set_marker(lisp.mark_marker(),None)
+        _revertSavedFiles(brmctx.save())
+        
+    def extract_method(self,name):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+
+        bline,bcol = _getPointCoords()
+        lisp.exchange_point_and_mark()
+        eline,ecol = _getPointCoords()
+        lisp.exchange_point_and_mark()
+
+        brmctx.extract(filename,bline,bcol,eline,ecol,name)
+        lisp.set_marker(lisp.mark_marker(),None)
+        _revertSavedFiles(brmctx.save())
+
+        
+    def move_class(self,newfilename):
+        lisp.save_some_buffers()
+        filename = lisp.buffer_file_name()
+        line,col = _getCoords()
+        brmctx.moveClassToNewModule(filename,line,newfilename)
+        _revertSavedFiles(brmctx.save())
+        
+
+
+brmctx = bike.init()
+
+brmemacs = None
+
+is_xemacs = (lisp.emacs_version().find("GNU") == -1)
+currently_saving=0
+
+# fix pop_excursion to work with xemacs
+class Let(Let):
+    def pop_excursion(self):
+        method, (buffer, point_marker, mark_marker) = self.stack[-1]
+        assert method == 'excursion', self.stack[-1]
+        del self.stack[-1]
+        lisp.set_buffer(buffer)
+        lisp.goto_char(point_marker)
+        lisp.set_mark(mark_marker)
+        lisp.set_marker(point_marker, None)
+        if mark_marker is not None:   # needed for xemacs
+            lisp.set_marker(mark_marker, None)
+
+
+
+def init():
+    global brmemacs
+    brmemacs = ExceptionCatcherWrapper(BRMEmacs(brmctx))
+
+    
+def kill():
+    """
+    Removes the bicyclerepairman context (freeing the state),
+    and reinitialises it.
+    """
+    brmemacs.kill()
+kill.interaction=""
+
+
+def promptCallback(filename,line,colbegin,colend):
+    let = Let().push_excursion()   # gets popped when let goes out of scope
+    buffer = lisp.current_buffer()
+    if let:
+        ans = 0
+        lisp.find_file(filename)
+        lisp.goto_line(line)
+        lisp.move_to_column(colbegin)
+        lisp.set_mark(lisp.point() + (colend - colbegin))
+        if is_xemacs:
+            lisp.activate_region()
+        ans = lisp.y_or_n_p("Couldn't deduce object type - rename this method reference? ")
+    del let
+    lisp.switch_to_buffer(buffer)
+    return ans
+
+def rename(newname):
+    return brmemacs.rename(newname)
+rename.interaction="sNew name: "
+
+
+def undo():
+    return brmemacs.undo()
+undo.interaction=""
+
+
+def _revertSavedFiles(savedFiles):
+    global currently_saving
+    currently_saving = 1
+    for file in savedFiles:
+        buf = lisp.find_buffer_visiting(file)
+        if buf:
+            lisp.set_buffer(buf)
+            lisp.revert_buffer(None,1)
+    currently_saving = 0
+
+def find_references():
+    brmemacs.find_references()    
+find_references.interaction=""
+
+def _getCoords():
+    line = lisp.count_lines(1,lisp.point())
+    col = lisp.current_column()
+    if col == 0:            
+        line += 1  # get round 'if col == 0, then line is 1 out' problem
+
+    if mark_exists() and lisp.point() > lisp.mark():
+        lisp.exchange_point_and_mark()
+        col = lisp.current_column()
+        lisp.exchange_point_and_mark()
+    return line,col
+
+def mark_exists():
+    if is_xemacs:
+        return lisp.mark()
+    else:
+        return lisp("mark-active") and lisp.mark()
+
+
+
+def _switchToConsole():
+    consolebuf = lisp.get_buffer_create("BicycleRepairManConsole")
+    lisp.switch_to_buffer_other_window(consolebuf)
+    lisp.compilation_mode("BicycleRepairMan")
+    lisp.erase_buffer()
+    lisp.insert("Bicycle Repair Man\n")
+    lisp.insert("(Hint: Press Return a Link)\n")
+    
+def find_definition():
+    brmemacs.find_definition()
+find_definition.interaction=""
+
+def _insertRefLineIntoConsole(ref):
+    lisp.insert(ref.filename+":"+str(ref.lineno)+":    "+str(ref.confidence)+"% confidence\n")
+    _redisplayFrame()
+
+def _redisplayFrame():
+    lisp.sit_for(0)
+
+def inline_local_variable():
+    brmemacs.inline_local_variable()
+inline_local_variable.interaction=""
+
+def extract_local_variable(name):
+    brmemacs.extract_local_variable(name)
+extract_local_variable.interaction="sVariable name: "
+
+
+def extract_method(name):
+    brmemacs.extract_method(name)
+extract_method.interaction="sName of function: "
+
+
+def move_class(newfilename):
+    return brmemacs.move_class(newfilename)
+move_class.interaction="fTarget file: "
+
+
+
+def _getPointCoords():
+    bline = lisp.count_lines(1,lisp.point())
+    bcol = lisp.current_column()
+    if bcol == 0:  # get round line is one less if col is 0 problem
+        bline += 1
+    return bline,bcol
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/test/README	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,89 @@
+Test Steps for testing idle integration
+---------------------------------------
+
+N.B. this test script is not expected to test all of bicyclerepairman
+- the pyunit tests do that. It is merely there to test the integration
+with idle (which doesnt get tested by pyunit).
+
+
+------------- Rename * -----------------------------------------
+
+- Load scrap.py
+
+- Rename Class to MyRenamedClass
+     (Check it renames the class)
+
+- Undo the rename
+
+- Create scrap3.py, containing the following:
+
+---------------------------
+import scrap
+
+a = scrap.MyClass()
+a.myMethod()
+--------------------------
+
+- Go back to scrap.py and rename the method to MyRenamedMethod
+     (Check that it prompts for rename in scrap2.py - rename the
+     first, but not the second)
+	 (Check that it renames all the methods in scrap2.py and scrap3.py
+	 except for the one you said no to)
+
+- Undo the rename
+     (Check that it undid all the renamings in all the files)
+
+------------- Find References ----------------------------------
+
+
+- Goto scrap.py, select 'find references'. Check that it tells you to
+highlight a class/function/method.
+
+- Highlight 'myMethod' and try again Check that it displays a list of
+references to this method.
+
+
+------------- Find Definition ----------------------------------
+
+- Goto scrap2.py, click 'myMethod' on d.myMethod(), then select 'find
+definition'. Check that it displays both the myMethod in MyClass and
+in AnotherClass.
+
+
+- Goto scrap2.py, click 'myMethod' on e.myMethod(), then select 'find
+definition'. Check that it takes you to the definition, and doesn't
+display a list of myMethod() references.
+
+
+------------- Extract Method / Function ------------------------
+
+- Load extractMethod.py into idle
+
+- select 'Extract Method' without first selecting a region
+      (Check that it tells you to select the region)
+
+- Use extractMethod to extract the marked line from the function
+
+- Use extractMethod to extract the lines of code from the method
+
+- Undo the extract Method
+
+- Undo the extract Function
+
+- Undo again - confirm that a dialog box pops up telling you the stack
+is empty.
+
+
+------------- Extract / Inline local variable ------------------
+
+- Load extractMethod.py into the ide
+
+- In the function 'inlineVariableTest', extract the marked code into a
+variable
+
+- Inline the variable back into the code
+
+----------------------------------------------------------------
+
+- exit from the ide, and delete scrap3.py from the directory
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/test/extractmethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,16 @@
+def myFunction():
+    a = 3
+    print "hello"+a  # extract me
+
+class MyClass:
+    def myMethod(self):
+        b = 12      # extract me
+        c = 3       # and me
+        d = 2       # and me
+        print b, c
+
+
+def inlineVariableTest():
+    a = b + 3 - 5
+    # --^^^^^  - Extract this into variable
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/test/scrap.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,19 @@
+class MyClass:
+    def myMethod(self, foo):
+        pass
+
+a = MyClass()
+
+a.myMethod()
+
+
+class AnotherClass:
+    def myMethod(self,foo):
+        pass
+
+def testFunction():
+    print "hello"
+
+
+print "hello"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ide-integration/test/scrap2.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,20 @@
+from scrap import MyClass, testFunction
+
+b = MyClass()
+
+b.myMethod()
+
+
+c = abcde()
+
+c.myMethod()
+
+
+d = defgh()
+
+d.myMethod()
+
+
+e = MyClass()
+
+e.myMethod()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/setup.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+import sys
+import os,glob
+from distutils.core import setup
+
+# check version
+if sys.version_info[0] < 2 or sys.version_info[0] == 2 and sys.version_info[1] < 2:
+    print "Python versions below 2.2 not supported"
+    sys.exit(0)
+
+
+setup(name="bicyclerepair",
+      version="0.9",
+      description="Bicycle Repair Man, the Python refactoring tool",
+      maintainer="Phil Dawes",
+      maintainer_email="pdawes@users.sourceforge.net",
+      url="http://bicyclerepair.sourceforge.net",
+      packages=['','bike','bike.refactor','bike.parsing','bike.query','bike.transformer'],
+      package_dir = {'bike':'bike','':'ide-integration'}
+      )
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import sys,os
+
+# check version
+if sys.version_info[0] < 2 or sys.version_info[0] == 2 and sys.version_info[1] < 2:
+    print "Python versions below 2.2 not supported"
+    sys.exit(0)
+
+if not os.path.abspath(".") in sys.path:
+    sys.path.append(os.path.abspath("."))
+
+
+from bike import logging
+
+from bike.test_testutils import *
+from bike.parsing.testall import *
+from bike.query.testall import *
+from bike.refactor.testall import *
+from bike.testall import *
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.WARN)
+    unittest.main()
--- a/vim/sadness/ropevim/rope.vim	Tue Nov 16 17:53:55 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-let $PYTHONPATH = "/Users/sjl/lib/dotfiles/vim/sadness/ropevim/pylibs:".$PYTHONPATH
-source /Users/sjl/lib/dotfiles/vim/sadness/ropevim/src/ropevim/ropevim.vim
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/sadness.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,7 @@
+let $rope_pypath = $HOME."/.vim/sadness/ropevim/pylibs"
+let $bike_pypath = $HOME."/.vim/sadness/bike"
+
+let $PYTHONPATH = $rope_pypath.":".$bike_pypath.":".$PYTHONPATH
+source $HOME/.vim/sadness/ropevim/src/ropevim/ropevim.vim
+
+source $HOME/.vim/sadness/bike/ide-integration/bike.vim