mirror of
				https://github.com/wting/autojump
				synced 2025-06-13 12:54:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			293 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
 | 
						|
#Copyright Joel Schaerer and Pierre Gueth 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()
 | 
						|
        path_dict=path_dict.items()
 | 
						|
        path_dict.sort(key=lambda x: x[1],reverse=True)
 | 
						|
 | 
						|
        return [path for path,score in path_dict[:maxpath]]
 | 
						|
    except IOError:
 | 
						|
        return []
 | 
						|
 | 
						|
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.ImageMenuItem(stock_id=gtk.STOCK_QUIT)
 | 
						|
        item.connect("activate",quit)
 | 
						|
        menu.append(item)
 | 
						|
        item=gtk.ImageMenuItem(stock_id=gtk.STOCK_PREFERENCES)
 | 
						|
        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.ImageMenuItem(stock_id=gtk.STOCK_PREFERENCES)
 | 
						|
        item.connect("activate",settings)
 | 
						|
        menu.append(item)
 | 
						|
        item=gtk.ImageMenuItem(stock_id=gtk.STOCK_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.Dialog("jump applet preferences",None,gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_SAVE,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
 | 
						|
    window.set_border_width(3)
 | 
						|
    window.set_resizable(False)
 | 
						|
    if os.path.isfile("icon.png"): window.set_icon_from_file("icon.png")
 | 
						|
    elif os.path.isfile("/usr/share/autojump/icon.png"): window.set_icon_from_file("/usr/share/autojump/icon.png")
 | 
						|
 | 
						|
    vbox=gtk.Table(5,2)
 | 
						|
    vbox.set_row_spacings(3)
 | 
						|
    window.get_child().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))
 | 
						|
 | 
						|
    window.connect("response",save_settings,entries,window)
 | 
						|
    window.show_all();
 | 
						|
 | 
						|
def save_settings(sender,response,entries,window):
 | 
						|
    window.hide_all()
 | 
						|
    if response!=gtk.RESPONSE_OK: return
 | 
						|
 | 
						|
    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()
 |