diff --git a/.gitignore b/.gitignore index 0d20b64..bafa1a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.pyc +*~ +*.orig +*.swp diff --git a/snapopen.plugin b/snapopen.plugin index f99bffa..973e700 100644 --- a/snapopen.plugin +++ b/snapopen.plugin @@ -1,5 +1,5 @@ [Plugin] -Loader=python +Loader=python3 Module=snapopen IAge=3 Name=Snap Open diff --git a/snapopen/__init__.py b/snapopen/__init__.py index a456927..44f9ddc 100644 --- a/snapopen/__init__.py +++ b/snapopen/__init__.py @@ -1,11 +1,14 @@ from gi.repository import GObject, Gedit, Gtk, Gio, Gdk import os, os.path -from urllib import pathname2url +from urllib.request import pathname2url import tempfile max_result = 50 app_string = "Snap open" +def send_message(window, object_path, method, **kwargs): + return window.get_message_bus().send_sync(object_path, method, **kwargs) + ui_str=""" @@ -22,7 +25,7 @@ class SnapOpenPluginInstance: def __init__( self, plugin, window ): self._window = window self._plugin = plugin - self._rootdir = "file://" + os.getcwd() + self._dirs = [] # to be filled self._tmpfile = os.path.join(tempfile.gettempdir(), 'snapopen.%s.%s' % (os.getuid(),os.getpid())) self._show_hidden = False self._liststore = None; @@ -96,7 +99,7 @@ def _init_ui( self ): #mouse event on list def on_list_mouse( self, widget, event ): - if event.type == gtk.gdk._2BUTTON_PRESS: + if event.type == Gdk.EventType._2BUTTON_PRESS: self.open_selected_item( event ) #key selects from list (passthrough 3 args) @@ -125,6 +128,7 @@ def on_pattern_entry( self, widget, event ): self._liststore.clear() maxcount = 0 + print(cmd) hits = os.popen(cmd).readlines() for file in hits: file = file.rstrip().replace("./", "") #remove cwd prefix @@ -145,24 +149,98 @@ def on_pattern_entry( self, widget, event ): if iter != None: self._hit_list.get_selection().select_iter(iter) + def get_git_base_dir( self, path ): + """ Get git base dir if given path is inside a git repo. None otherwise. """ + try: + cmd = "cd '%s' 2> /dev/null; git rev-parse --show-toplevel 2> /dev/null" % path + print(cmd) + gitdir = os.popen(cmd).readlines() + except: + gitdir = '' + if len(gitdir) > 0: + return gitdir[0].replace("\n","") + return None + + def map_to_git_base_dirs( self ): + """ Replace paths with respective git repo base dirs if it exists """ + # use git repo base dir is more suitable if we are inside a git repo, for any dir we have guessed before + dirs = [] + for d in self._dirs: + gitdir = self.get_git_base_dir(d) + if gitdir is None: + dirs.append(d) + else: + dirs.append(gitdir) + self._dirs = dirs + # we could have introduced duplicates here + self.ensure_unique_entries() + + def ensure_unique_entries( self ): + """ Remove duplicates from dirs list """ + # this also looks for paths already included in other paths + unique = [] + for d in self._dirs: + d = d.replace("file://","").replace("//","/") + should_append = True + for i,u in enumerate(unique): # replace everyone with its wider parent + if u in d: # already this one, or a parent + should_append = False + elif d in u: # replace with the parent + unique[i] = d + should_append = False + + if should_append: + unique.append(d) + + self._dirs = set(unique) + + def get_dirs_string( self ): + """ Gets the quoted string built with dir list, ready to be passed on to 'find' """ + string = '' + for d in self._dirs: + string += "'%s' " % d + return string + #on menuitem activation (incl. shortcut) def on_snapopen_action( self ): self._init_ui() - fbroot = self.get_filebrowser_root() + # build paths list + self._dirs = [] + + # append current local open files dirs + for doc in self._window.get_documents(): + location = doc.get_location() + if location and doc.is_local(): + self._dirs.append( location.get_parent().get_uri() ) + # append filebrowser root if available + fbroot = self.get_filebrowser_root() if fbroot != "" and fbroot is not None: - self._rootdir = fbroot - self._snapopen_window.set_title(app_string + " (File Browser root)") - else: - self._snapopen_window.set_title(app_string + " (Working dir): " + self._rootdir) + self._dirs.append(fbroot) - # cache the file list in the background + # ensure_unique_entries is executed after mapping to git base dir + # but it's cheaper, then do it before too, avoiding extra work + self.ensure_unique_entries() + + # replace each path with its git base dir if exists + self.map_to_git_base_dirs() + + # append gedit dir (usually too wide for a quick search) if we have nothing so far + if len(self._dirs) == 0: + self._dirs = [ os.getcwd() ] + + # build filters list #modify lines below as needed, these defaults work pretty well - imagefilter = " ! -iname '*.jpg' ! -iname '*.jpeg' ! -iname '*.gif' ! -iname '*.png' ! -iname '*.psd' ! -iname '*.tif' " - dirfilter = " ! -path '*.svn*' ! -path '*.git*' " - binfilter = " ! -iname '*.o' ! -iname '*.so' ! -iname '*.lo' ! -iname '*.Plo' ! -iname '*.a' ! -iname '*.pyc' " - os.popen("cd %s; find . -type f %s > %s 2> /dev/null &" % (self._rootdir.replace("file://", ""), imagefilter + dirfilter + binfilter, self._tmpfile)) + filters = " ! -iname '*.jpg' ! -iname '*.jpeg' ! -iname '*.gif' ! -iname '*.png' ! -iname '*.psd' ! -iname '*.tif' " + filters += " ! -path '*.svn*' ! -path '*.git*' " + filters += " ! -iname '*.o' ! -iname '*.so' ! -iname '*.lo' ! -iname '*.Plo' ! -iname '*.a' ! -iname '*.pyc' " + filters += " ! -iname '*~' ! -iname '*.swp' " + + # cache the file list in the background + cmd = "find %s -type f %s > %s 2> /dev/null &" % (self.get_dirs_string(), filters, self._tmpfile) + print(cmd) + os.popen(cmd) self._snapopen_window.show() self._glade_entry_name.select_region(0,-1) @@ -194,29 +272,19 @@ def old_get_tab_from_uri(self, window, uri): #opens (or switches to) the given file def _open_file( self, filename ): - uri = self._rootdir + "/" + pathname2url(filename) + #uri = self._rootdir + "/" + pathname2url(filename) + uri = "file://" + pathname2url(filename) gio_file = Gio.file_new_for_uri(uri) tab = self._window.get_tab_from_location(gio_file) if tab == None: tab = self._window.create_tab_from_location( gio_file, None, 0, 0, False, False ) self._window.set_active_tab( tab ) -# FILEBROWSER integration + # filebrowser integration def get_filebrowser_root(self): - base = u'org.gnome.gedit.plugins.filebrowser' - - settings = Gio.Settings.new(base) - root = settings.get_string('virtual-root') - - if root is not None: - filter_mode = settings.get_strv('filter-mode') - - if 'hide-hidden' in filter_mode: - self._show_hidden = False - else: - self._show_hidden = True - - return root + res = send_message(self._window, '/plugins/filebrowser', 'get_root') + if res.location is not None: + return res.location.get_path() # STANDARD PLUMMING class SnapOpenPlugin(GObject.Object, Gedit.WindowActivatable): @@ -229,16 +297,17 @@ def __init__(self): GObject.Object.__init__(self) def _get_instance( self ): - return self.window.get_data( self.DATA_TAG ) + return self.window.DATA_TAG def _set_instance( self, instance ): - self.window.set_data( self.DATA_TAG, instance ) + self.window.DATA_TAG = instance def do_activate( self ): self._set_instance( SnapOpenPluginInstance( self, self.window ) ) def do_deactivate( self ): - self._get_instance().deactivate() + if self._get_instance(): + self._get_instance().deactivate() self._set_instance( None ) def do_update_ui( self ): diff --git a/snapopen/snapopen.ui b/snapopen/snapopen.ui index d6f77c7..77e4439 100644 --- a/snapopen/snapopen.ui +++ b/snapopen/snapopen.ui @@ -2,8 +2,8 @@ - 500 - 360 + 900 + 400 False 11 Snap Open file...