Permalink
Browse files

Adding autojump binary to the profile and support for the bin directory

  • Loading branch information...
1 parent 5f4d4ac commit b0153969cdc16f51e650da582363a6470fa75bc9 @spf13 committed May 5, 2010
Showing with 217 additions and 28 deletions.
  1. +34 −18 README.textile
  2. +6 −6 autojump.conf
  3. +172 −0 bin/autojump
  4. +5 −4 init
View
52 README.textile
@@ -1,19 +1,39 @@
h1. My Bash Profile
-This is the profile that I'm now using across a number of machines that I administer. Most of the tricks I use are fairly general and could be reused by anyone.
+This is Steve Francia's fork of Mat Schaffer's profile.
+
+h2. Features
+
+* Reactive prompt - includes date and exit code of last command and git branch.
+* Tab completion for Git and Subversion
+* Tab completion for Rake, Maven 2 and Ant
+* Tab completion for ssh hosts on OS X.
+* Git aliases
+* 'safeedit' function that makes a timestamped backup copy of a file before editing
+* Basic java set up on solaris and Darwin
+* Maven memory settings
+* 'profile_push' function for pushing these files out to other servers
+* 'link_dotfiles' command that will create symlinks for all the files listed in the dotfiles directory
+* Auto setup of .foward file on Linux and Solaris
+* Integration with "CDArgs":http://www.skamphausen.de/cgi-bin/ska/CDargs
+* "Autojump":http://wiki.github.com/joelthelion/autojump/
+
+h3. Enhancements
+* Bundling a bin directory so that autojump, etc work out of the box.
+* Tab completion for "git flow":http://github.com/nvie/gitflow
h2. What's it look like?
!http://cloud.github.com/downloads/matschaffer/profile/diagram.png(Feature Diagram)!
-h2. Usage
+h2. Installation
<pre>
# Go home
cd ~
# Clone mine or your own fork
-git clone git://github.com/matschaffer/profile.git .profile.d
+git clone git://github.com/spf13/profile.git .profile.d
# All *.conf files are loaded alphabetically, so this will retain your original settings
mv .profile .profile.d/z_myoldsettings.conf
@@ -26,29 +46,25 @@ ln -s .profile.d/init .profile
source .profile
</pre>
-From here you can now put any @*.conf@ in @~/.profile.d@ and it'll get loaded in alphabetical order. You can also put conf files in @~/.profile.d/`uname`@ to get platform-specific configuration or @~/.profile.d/$USER@ to get user-specific configuration. The load order (defined in the @init@ file) is:
+h2. Usage
+Once installed you can now put any @*.conf@ in @~/.profile.d@ and it'll get loaded in alphabetical order. You can also put conf files in @~/.profile.d/`uname`@ to get platform-specific configuration or @~/.profile.d/$USER@ to get user-specific configuration. The load order (defined in the @init@ file) is:
# .profile.d/init
# .profile.d/<notextile>*</notextile>.conf
# .profile.d/$USER/<notextile>*</notextile>.conf
# .profile.d/`uname`/<notextile>*</notextile>.conf
# .profile.d/$USER/`uname`/<notextile>*</notextile>.conf
-h2. Features
+h3. Additional Installation
-* Reactive prompt - includes date and exit code of last command and git branch.
-* Tab Completion for Git and Subversion
-* Tab completion for Rake, Maven 2 and Ant
-* Tab completion for ssh hosts on OS X.
-* Git aliases
-* 'safeedit' function that makes a timestamped backup copy of a file before editing
-* Basic java set up on solaris and Darwin
-* Maven memory settings
-* 'profile_push' function for pushing these files out to other servers
-* 'link_dotfiles' command that will create symlinks for all the files listed in the dotfiles directory
-* Auto setup of .foward file on Linux and Solaris
-* Integration with "CDArgs":http://www.skamphausen.de/cgi-bin/ska/CDargs
-* "Autojump":http://wiki.github.com/joelthelion/autojump/
+h4. To install AutoJump
+AutoJump comes ready to use out of the box. If you wish to update it follow the following steps
+1. Goto http://github.com/joelthelion/autojump
+2. Download autojump.
+3. Extract/Create in the following locations.
+ * autojump to /usr/bin
+ * autojump.sh to /etc/profile.d # already done for you ;)
+ * autojump.1 to /usr/share/man/man1
h2. Planned features
View
12 autojump.conf
@@ -18,12 +18,12 @@
#along with autojump. If not, see <http://www.gnu.org/licenses/>.
_autojump()
{
- local cur
- COMPREPLY=()
- unset COMP_WORDS[0] #remove "j" from the array
- cur=${COMP_WORDS[*]}
- IFS=$'\n' read -d '' -a COMPREPLY < <(autojump --bash --completion "$cur")
- return 0
+ local cur
+ cur=${COMP_WORDS[*]:1}
+ while read i
+ do
+ COMPREPLY=("${COMPREPLY[@]}" "${i}")
+ done < <(autojump --bash --completion $cur)
}
complete -F _autojump j
AUTOJUMP='{ (autojump -a "$(pwd -P)"&)>/dev/null 2>>${HOME}/.autojump_errors;} 2>/dev/null'
View
172 bin/autojump
@@ -0,0 +1,172 @@
+#!/usr/bin/python
+#Copyright Joel Schaerer 2008, 2009
+#This file is part of autojump
+
+#autojump 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 3 of the License, or
+#(at your option) any later version.
+#
+#autojump 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 autojump. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import division
+import cPickle
+import getopt
+from sys import argv,exit,stderr
+import os
+import signal
+max_keyweight=1000
+dead_dirs=False #global variable (evil ;-) to know if we should save the dict at the end
+
+def signal_handler(arg1,arg2):
+ print "Received SIGINT, trying to continue"
+signal.signal(signal.SIGINT,signal_handler) #Don't break on sigint
+
+def uniqadd(list,key):
+ if key not in list:
+ list.append(key)
+
+def dicadd(dic,key,increment=1):
+ dic[key]=dic.get(key,0.)+increment
+
+def match(path,pattern,path_dict,ignore_case=False,only_end=False):
+ try:
+ if os.path.realpath(os.curdir)==path : return False
+ except OSError: #sometimes the current path doesn't exist anymore. In that case, jump if possible.
+ pass
+ if only_end:
+ match_string = "/".join(path.split('/')[-1-pattern.count('/'):])
+ else:
+ match_string = path
+ #import re
+ #if re.search(pattern,match_string),re.IGNORECASE if ignore_case else 0) is None:
+ match=(match_string.lower().find(pattern.lower()) != -1)\
+ if ignore_case\
+ else (match_string.find(pattern) != -1)
+ if not match:
+ return False
+ else:
+ if os.path.exists(path) : return True
+ else: #clean up dead directories
+ del path_dict[path]
+ global dead_dirs
+ dead_dirs=True
+ return False
+
+def save(path_dict,dic_file):
+ f=open(dic_file+".tmp",'w')
+ cPickle.dump(path_dict,f,-1)
+ f.flush()
+ os.fsync(f)
+ f.close()
+ try:
+ os.rename(dic_file+".tmp",dic_file) #cf. http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/
+ import time #backup file
+ if not os.path.exists(dic_file+".bak") or time.time()-os.path.getmtime(dic_file+".bak")>86400:
+ import shutil
+ shutil.copy(dic_file,dic_file+".bak")
+ except OSError:
+ pass #Fail quietly, this usually means a concurrent autojump process already did the job
+
+def forget(path_dict,dic_file):
+ """Gradually forget about directories. Only call from the actual jump since it can take time"""
+ keyweight=sum(path_dict.values()) #Gradually forget about old directories
+ if keyweight>max_keyweight:
+ for k in path_dict.keys():
+ path_dict[k]*=0.9*max_keyweight/keyweight
+ save(path_dict,dic_file)
+
+def find_matches(dirs,patterns,path_dict,result_list,ignore_case,max_matches):
+ """Find max_matches paths that match the pattern, and add them to the result_list"""
+ for path,count in dirs:
+ if len(result_list) >= max_matches : break
+ #For the last pattern, only match the end of the pattern
+ if all(match(path,p,path_dict,ignore_case, only_end = (n==len(patterns)-1)) for n,p in enumerate(patterns)):
+ uniqadd(result_list,path)
+
+def open_dic(dic_file,error_recovery=False):
+ try:
+ aj_file=open(dic_file)
+ path_dict=cPickle.load(aj_file)
+ aj_file.close()
+ return path_dict
+ except (IOError,EOFError,cPickle.UnpicklingError):
+ if not error_recovery and os.path.exists(dic_file+".bak"):
+ print >> stderr, 'Problem with autojump database, trying to recover from backup...'
+ import shutil
+ shutil.copy(dic_file+".bak",dic_file)
+ return open_dic(dic_file,True)
+ else: return {} #if everything fails, return an empty file
+
+#Main code
+try:
+ optlist, args = getopt.getopt(argv[1:], 'a',['stat','import','completion', 'bash'])
+except getopt.GetoptError, e:
+ print "Unknown command line argument: %s" % e
+ exit(1)
+
+dic_file=os.path.expanduser("~/.autojump_py")
+path_dict=open_dic(dic_file)
+if ('-a','') in optlist:
+ if(args[-1] != os.path.expanduser("~")): # home dir can be reached quickly by "cd" and may interfere with other directories
+ dicadd(path_dict,args[-1])
+ save(path_dict,dic_file)
+elif ('--stat','') in optlist:
+ a=path_dict.items()
+ a.sort(key=lambda e:e[1])
+ for path,count in a[-100:]:
+ print "%.1f:\t%s" % (count,path)
+ print "Total key weight: %d" % sum(path_dict.values())
+elif ('--import','') in optlist:
+ for i in open(args[-1]).readlines():
+ dicadd(path_dict,i[:-1])
+ cPickle.dump(path_dict,open(dic_file,'w'),-1)
+else:
+ import re
+ completion=False
+ userchoice=-1 #i if the pattern is of the form __pattern__i, otherwise -1
+ results=[]
+ if ('--completion','') in optlist:
+ completion=True
+ else:
+ forget(path_dict,dic_file) #gradually forget about old directories
+ if not args: patterns=[""]
+ else: patterns=args
+
+ #if the last pattern is a full path, jump there
+ if len(patterns[-1])>0 and patterns[-1][0]=="/" and os.path.exists(patterns[-1]):
+ if not completion : print patterns[-1]
+ else:
+ endmatch=re.search("__([0-9]+)",patterns[-1])
+ if endmatch:
+ userchoice=int(endmatch.group(1))
+ patterns[-1]=re.sub("__[0-9]+.*","",patterns[-1])
+ else:
+ endmatch=re.match("(.*)__",patterns[-1])
+ if endmatch: patterns[-1]=endmatch.group(1)
+
+ dirs=path_dict.items()
+ dirs.sort(key=lambda e:e[1],reverse=True)
+ max_matches = 9 if completion else 1
+ find_matches(dirs,patterns,path_dict,results,False,max_matches)
+ dirs=path_dict.items() #we need to recreate the list since the first iteration potentially deletes paths
+ dirs.sort(key=lambda e:e[1],reverse=True)
+ if completion or not results: #if not found, try ignoring case. On completion always show all results
+ find_matches(dirs,patterns,path_dict,results,ignore_case=True,max_matches=max_matches)
+ if dead_dirs and not completion: #save the dict if there were some non-existent directories in the database
+ save(path_dict,dic_file)
+
+ if completion and ('--bash', '') in optlist: quotes='"'
+ else: quotes=""
+
+ if userchoice!=-1:
+ if len(results) > userchoice-1 : print quotes+results[userchoice-1]+quotes
+ elif len(results) > 1 and completion:
+ print "\n".join(("%s__%d__%s" % (patterns[-1],n+1,r) for n,r in enumerate(results[:8])))
+ elif results: print quotes+results[0]+quotes
View
9 init
@@ -1,15 +1,16 @@
+PROFILE_PATH="${HOME}/.profile.d"
+PLATFORM=`uname`
+
+export PATH=$PATH:$PROFILE_PATH/bin
+
load_conf() {
for conf in "$1"/*.conf; do
[ -e "${conf}" ] && source "${conf}"
done
return 0
}
-PROFILE_PATH="${HOME}/.profile.d"
-PLATFORM=`uname`
-
load_conf "${PROFILE_PATH}"
load_conf "${PROFILE_PATH}/${USER}"
load_conf "${PROFILE_PATH}/${PLATFORM}"
load_conf "${PROFILE_PATH}/${USER}/${PLATFORM}"
-

0 comments on commit b015396

Please sign in to comment.