mirror of
				https://github.com/wting/autojump
				synced 2025-06-13 12:54:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			294 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env 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/>.
 | |
| 
 | |
| import subprocess
 | |
| import cPickle
 | |
| import os.path
 | |
| import os
 | |
| import sys
 | |
| import pygtk
 | |
| pygtk.require('2.0')
 | |
| import gtk
 | |
| 
 | |
| defaults={}
 | |
| actions={}
 | |
| 
 | |
| #decorator truff
 | |
| def action(validator,name=None):
 | |
|     if name is None:
 | |
|         def wrapper(action):
 | |
|             actions[action.__name__]=(action,validator)
 | |
|     else:
 | |
|         def wrapper(action):
 | |
|             actions[name]=(action,validator)
 | |
|     return wrapper
 | |
| 
 | |
| #validator helper
 | |
| def has_child_dir(dirname,recursion=0):
 | |
|     def wrapper(path):
 | |
|         k=recursion
 | |
|         ii=""
 | |
|         while k>=0:
 | |
|             if os.path.isdir(os.path.join(path,ii,dirname)): return True
 | |
|             k-=1
 | |
|             ii=os.path.join("..",ii)
 | |
|         return False
 | |
|     return wrapper
 | |
| 
 | |
| 
 | |
| def has_child_file(filename):
 | |
|     def wrapper(path):
 | |
|         return os.path.isfile(os.path.join(path,filename))
 | |
|     return wrapper
 | |
| 
 | |
| #do the work
 | |
| def load_paths(filename="~/.autojump_py",maxpath=10):
 | |
|     dic_file=os.path.expanduser(filename)
 | |
| 
 | |
|     try:
 | |
|         aj_file=open(dic_file)
 | |
|         path_dict=cPickle.load(aj_file)
 | |
|         aj_file.close()
 | |
|     except IOError:
 | |
|         pass
 | |
| 
 | |
|     path_dict=path_dict.items()
 | |
|     path_dict.sort(key=lambda x: x[1],reverse=True)
 | |
| 
 | |
|     return [path for path,score in path_dict[:maxpath]]
 | |
| 
 | |
| def load_settings_file(filename="~/.jumpapplet_py"):
 | |
|     print "loading settings"
 | |
|     global defaults
 | |
|     dic_file=os.path.expanduser(filename)
 | |
| 
 | |
|     try:
 | |
|         aj_file=open(dic_file,'r')
 | |
|         defaults=cPickle.load(aj_file)
 | |
|         aj_file.close()
 | |
|     except IOError:
 | |
|         print "no config file"
 | |
|         pass
 | |
| 
 | |
|     if not "terminal" in defaults: defaults["terminal"]="gnome-terminal"
 | |
|     if not "navigator" in defaults: defaults["navigator"]="nautilus"
 | |
|     if not "maxpath" in defaults: defaults["maxpath"]=15
 | |
|     if not "invert" in defaults: defaults["invert"]=False
 | |
|     if not "collapse" in defaults: defaults["collapse"]=True
 | |
| 
 | |
|     create_actions()
 | |
| 
 | |
| def save_settings_file(filename="~/.jumpapplet_py"):
 | |
|     print "saving settings"
 | |
|     dic_file=os.path.expanduser(filename)
 | |
| 
 | |
|     aj_file=open(dic_file,'w')
 | |
|     cPickle.dump(defaults,aj_file)
 | |
|     aj_file.close()
 | |
| 
 | |
| 
 | |
| def get_actions(path):
 | |
|     return [(name,action) for name,(action,validator) in actions.items() if validator(path)]
 | |
| 
 | |
| def popup(sender,button,activation):
 | |
|     paths=load_paths(maxpath=defaults["maxpath"])
 | |
| 
 | |
|     if defaults["collapse"]:
 | |
|         def collapse_home(path):
 | |
|             return path.replace(os.path.expanduser('~'),"~")
 | |
|     else:
 | |
|         def collapse_home(path):
 | |
|             return path
 | |
| 
 | |
| 
 | |
|     menu=gtk.Menu()
 | |
|     if defaults["invert"]:
 | |
|         item=gtk.MenuItem("quit")
 | |
|         item.connect("activate",quit)
 | |
|         menu.append(item)
 | |
|         item=gtk.MenuItem("settings")
 | |
|         item.connect("activate",settings)
 | |
|         menu.append(item)
 | |
| 
 | |
|         menu.append(gtk.SeparatorMenuItem())
 | |
|         
 | |
|         for path in reversed(paths):
 | |
|             actions=get_actions(path)
 | |
|             if not actions: continue
 | |
| 
 | |
|             item=gtk.MenuItem(collapse_home(path),use_underline=False)
 | |
|             submenu=gtk.Menu()
 | |
|             item.set_submenu(submenu)
 | |
|             for name,action in actions:
 | |
|                 subitem=gtk.MenuItem(name)
 | |
|                 subitem.connect("activate",action,path)
 | |
|                 submenu.append(subitem)
 | |
|             menu.append(item)
 | |
|     else:
 | |
|         for path in paths:
 | |
|             actions=get_actions(path)
 | |
|             if not actions: continue
 | |
| 
 | |
|             item=gtk.MenuItem(collapse_home(path),use_underline=False)
 | |
|             submenu=gtk.Menu()
 | |
|             item.set_submenu(submenu)
 | |
|             for name,action in actions:
 | |
|                 subitem=gtk.MenuItem(name)
 | |
|                 subitem.connect("activate",action,path)
 | |
|                 submenu.append(subitem)
 | |
|             menu.append(item)
 | |
| 
 | |
|         menu.append(gtk.SeparatorMenuItem())
 | |
|         
 | |
|         item=gtk.MenuItem("settings")
 | |
|         item.connect("activate",settings)
 | |
|         menu.append(item)
 | |
|         item=gtk.MenuItem("quit")
 | |
|         item.connect("activate",quit)
 | |
|         menu.append(item)
 | |
| 
 | |
|     menu.show_all()
 | |
|     menu.popup(None,None,gtk.status_icon_position_menu,button,activation,sender)
 | |
| 
 | |
| def settings(sender):
 | |
|     window=gtk.Window(gtk.WINDOW_TOPLEVEL)
 | |
|     window.set_title("jump applet settings")
 | |
|     window.set_border_width(3)
 | |
|     window.set_resizable(False)
 | |
| 
 | |
|     vbox=gtk.Table(6,2)
 | |
|     vbox.set_row_spacings(3)
 | |
|     window.add(vbox)
 | |
|     def add_string_setting(name,label,nsettings):
 | |
|         label=gtk.Label(label+' ')
 | |
|         label.set_alignment(1.,.5)
 | |
|         entry=gtk.Entry()
 | |
|         if name in defaults: entry.set_text(defaults[name])
 | |
| 
 | |
|         vbox.attach(label,0,1,nsettings,nsettings+1)
 | |
|         vbox.attach(entry,1,2,nsettings,nsettings+1)
 | |
|         return (name,entry)
 | |
| 
 | |
|     def add_integer_setting(name,label,nsettings):
 | |
|         label=gtk.Label(label+' ')
 | |
|         label.set_alignment(1.,.5)
 | |
|         entry=gtk.SpinButton()
 | |
|         entry.set_range(5,35)
 | |
|         entry.set_numeric(True)
 | |
|         entry.set_increments(1,5)
 | |
|         entry.set_snap_to_ticks(True)
 | |
|         if name in defaults: entry.set_value(defaults[name])
 | |
| 
 | |
|         vbox.attach(label,0,1,nsettings,nsettings+1)
 | |
|         vbox.attach(entry,1,2,nsettings,nsettings+1)
 | |
|         return (name,entry)
 | |
| 
 | |
|     def add_bool_setting(name,label,nsettings):
 | |
|         entry=gtk.CheckButton(label=label,use_underline=False)
 | |
|         if name in defaults: entry.set_active(defaults[name])
 | |
| 
 | |
|         vbox.attach(entry,0,2,nsettings,nsettings+1)
 | |
|         return (name,entry)
 | |
| 
 | |
|     entries=[]
 | |
|     entries.append(add_string_setting("terminal","terminal program",0))
 | |
|     entries.append(add_string_setting("navigator","navigator program",1))
 | |
|     entries.append(add_integer_setting("maxpath","number of directories",2))
 | |
|     entries.append(add_bool_setting("invert","list directories in reverse order",3))
 | |
|     entries.append(add_bool_setting("collapse","collapse home directory to ~",4))
 | |
|     button=gtk.Button("save")
 | |
|     button.connect("clicked",save_settings,entries,window)
 | |
|     vbox.attach(button,0,2,5,6)
 | |
| 
 | |
|     window.show_all();
 | |
| 
 | |
| def save_settings(sender,entries,window):
 | |
|     window.hide_all()
 | |
|     global defaults
 | |
|     for name,entry in entries:
 | |
|         try:
 | |
|             defaults[name]=int(entry.get_text())
 | |
|         except (ValueError,AttributeError):
 | |
|             try:
 | |
|                 defaults[name]=entry.get_active()
 | |
|             except AttributeError:
 | |
|                 defaults[name]=entry.get_text()
 | |
| 
 | |
|     save_settings_file()
 | |
|     create_actions()
 | |
| 
 | |
| def init():
 | |
|     load_settings_file()
 | |
|     if os.path.isfile("icon.png"): icon=gtk.status_icon_new_from_file("icon.png")
 | |
|     elif os.path.isfile("/usr/share/autojump/icon.png"): icon=gtk.status_icon_new_from_file("/usr/share/autojump/icon.png")
 | |
|     else: icon=gtk.status_icon_new_from_icon_name("help")
 | |
|     icon.set_visible(True)
 | |
|     icon.connect("popup-menu",popup)
 | |
| 
 | |
| def quit(sender):
 | |
|     gtk.main_quit()
 | |
| 
 | |
| ######################################################
 | |
| #insert other actions here using the action decorator#
 | |
| ######################################################
 | |
| def create_actions():
 | |
|     global actions
 | |
|     actions={}
 | |
| 
 | |
|     @action(has_child_dir(".git",recursion=3))
 | |
|     def gitk(sender,path):
 | |
|         if not os.fork():
 | |
|             os.chdir(path)
 | |
|             subprocess.Popen(['gitk']).wait()
 | |
|             sys.exit()
 | |
| 
 | |
|     @action(has_child_file("CMakeCache.txt"),"configure")
 | |
|     def cmake(sender,path):
 | |
|         if not os.fork():
 | |
|             os.chdir(path)
 | |
|             subprocess.Popen(['cmake-gui','.']).wait()
 | |
|             sys.exit()
 | |
| 
 | |
|     @action(os.path.isdir)
 | |
|     def terminal(sender,path):
 | |
|         print "launch terminal '%s'" % defaults["terminal"]
 | |
|         if not os.fork():
 | |
|             try:
 | |
|                 if defaults["terminal"]=="konsole":
 | |
|                     subprocess.Popen([defaults["terminal"],"--workdir=%s"%path]).wait()
 | |
|                 else:
 | |
|                     os.chdir(path)
 | |
|                     subprocess.Popen([defaults["terminal"]]).wait()
 | |
|             except OSError:
 | |
|                 pass
 | |
|             sys.exit()
 | |
| 
 | |
|     @action(os.path.isdir)
 | |
|     def navigator(sender,path):
 | |
|         print "launch navigator '%s'" % defaults["navigator"]
 | |
|         if not os.fork():
 | |
|             try:
 | |
|                 subprocess.Popen([defaults["navigator"],path]).wait()
 | |
|             except OSError:
 | |
|                 pass
 | |
|             sys.exit()
 | |
| 
 | |
| if __name__=='__main__':
 | |
|     init()
 | |
|     gtk.main()
 |