Sublime Forum

Fuzzy filesystem find?

#1

Is there an equivalent mode in ST2 to the Vim FuzzyFinder plugin? Looking for a quick file nav, without using projects. The default file open dialog is not fast for file finding.

0 Likes

#2

Short vid example: http://vimeo.com/2938498)

0 Likes

#3

This could be a very simple plugin. I’ll make it and report back. I probably won’t use it since I use Alfred.app but others might appreciate it.

0 Likes

#4

BTW, you could always just add your whole folder to sublime text and use the goto anything.

0 Likes

#5

I had considered that, but the advantage to a plugin like FuzzyFinder is that I can navigate to anything on my filesystem without a project. Not sure if there is overhead in a such a project.

I am actually surprised that Goto Anything does not include the filesystem (optionally).

0 Likes

#6

I would also be interested in a faster way to navigate to non-project folders & files from within Sublime*, although I’m not sure what exactly I’m looking for.

There’s a plugin called Sublime-File-Navigator, which may (or may not) be close to what the OP was asking for. (I dsicovered it recently, and it hasn’t gotten much use, so I don’t really have any opinion on it just yet.)

Alex

  • I also wish I could use multiple selections when editing filenames. But that’s another story.
0 Likes

#7

Sublime-File-Navigator seems to still be project based, as attempting to use it without a project presents an error dialog. I rarely use projects in any of the editors I use, and so far, FuzzyFinder (Vim) seems to work in this mode best.

0 Likes

#8

Sorry I never got back to this post. I started the plugin but ended up hitting a snag that will require some workarounds…

0 Likes

#9

I may give this a shot when I get some time. I don’t imagine this would be too difficult to do…but I guess we shall see :smile:.

0 Likes

#10

Here is a quick script I threw together for navigating files on your computer. It has only been loosely tested on Windows. I will do some testing on Unix/Linux later. If you find issues or have suggestions let me know.

If people like it, I might create a repo. if not…I guess I will just keep it to myself :smile:.

gist.github.com/3085459

0 Likes

#11

Slight update; you can now specify the starting location for the command; if none is given, it picks the root. That’s it for today. I will give unix/linux a test tonight and update tomorrow if I found any issues. I will also fix any bugs if any are reported.

0 Likes

#12

Oh, and if you thought the plugin was going to fuzzy search your entire computer…that is just not practical. I should clarify that it allows you to navigate and drill down into folders on your filesystem. It allows you to use the quick panel to fuzzy search the directory for files and folders.

In order to fuzzy search your entire computer to give you the same feel in a project, you would have to create some indexing service and keep all paths in some kind of database. I personally don’t want yet another indexing service on my computer.

Since the plugin allows you to feed in its starting point, you can create commands to search different locations you commonly navigate in, or just start from root. Technically you could create a command that could grab the path of the current file being edited and and have it feed this plugin the path to start your navigation in that folder.

0 Likes

#13

Here’s the code I use for this (put into “quickopen.py” in your User package).
It’s only tested on Linux/OS X.

It would be nice to have this as a built-in feature.

import os, os.path, fnmatch

global have_ctypes

class FilesystemPaletteCommand(sublime_plugin.WindowCommand):
    def run(self, directory=None, **kwargs):
        self.home = os.path.expanduser("~")
        self._build_exclude_settings(**kwargs)

        if directory is None:
            self.open_panel(self._current_directory())
        else:
            self.open_panel(os.path.expanduser(directory))

    def open_panel(self, directory):
        self._dir = directory
        self._build_items()
        view = self.window.active_view()
        if view is not None:
            view.set_status("browse_dir", "Browsing: " + self._find_shortest_name(self._dir))
        self.window.show_quick_panel(self._items, self._on_panel_select)

    # -- private methods
    def _build_exclude_settings(self, show_excluded_files=False, show_excluded_directories=False,
                                      show_binary=True, show_hidden=False):
        self.exclude_hidden = not show_hidden
        self.exclude_patterns = set()
        settings = sublime.load_settings("Global.sublime-settings")
        if not show_excluded_files:
            self.exclude_patterns.update(settings.get("file_exclude_patterns", ]))
        if not show_excluded_directories:
            self.exclude_patterns.update(settings.get("folder_exclude_patterns", ]))
        if not show_binary:
            self.exclude_patterns.update(settings.get("binary_file_patterns", ]))

    def _on_panel_select(self, index):
        if self.window.active_view():
            self.window.active_view().set_status("browse_dir", "")

        # Abort
        if index == -1:
            return

        filename = self._items[index][0]
        path = os.path.realpath(os.path.join(self._dir, filename))

        # Parent Directory
        if filename.startswith(u"..  →"):
            self.open_panel(os.path.join(self._dir, ".."))
            return

        # Home Directory
        if filename.startswith(u"~  →"):
            self.open_panel(self.home)
            return

        if os.path.isdir(path):
            self.open_panel(path)
        else:
            self.window.open_file(path)

    def _current_directory(self):
        view = self.window.active_view()
        if view and view.file_name() is not None:
            return os.path.dirname(view.file_name())
        else:
            return self.home

    def _build_items(self):
        self._dir = os.path.realpath(self._dir)
        shortdir = self._find_shortest_name(self._dir)
        parent = os.path.dirname(self._dir)

        self._items = ]
        if self._dir != '/':
            self._items.append()
        if parent != self.home and self._dir != self.home:
            self._items.append()
        for item in os.listdir(self._dir):
            if self._do_include_item(self._dir, item):
                path = os.path.join(shortdir, item)
                if os.path.isdir(os.path.join(self._dir, item)):
                    self._items.append([item + "/", path])
                else:
                    self._items.append([item, path])

    def _do_include_item(self, directory, name):
        if self.exclude_hidden and is_hidden(directory, name):
            return False
        for pattern in self.exclude_patterns:
            if fnmatch.fnmatch(name, pattern):
                return False
        return True

    def _find_shortest_name(self, directory):
        if directory.startswith(self.home):
            return directory.replace(self.home, "~", 1)
        return directory

# http://stackoverflow.com/questions/284115/cross-platform-hidden-file-detection
def is_hidden(directory, name):
    return name.startswith('.') or (have_ctypes and has_hidden_attribute(os.path.join(directory, name)))

def has_hidden_attribute(filepath):
    try:
        attrs = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath))
        assert attrs != -1
        result = bool(attrs & 2)
    except (AttributeError, AssertionError):
        result = False
    return result
1 Like

#14

I have updated my gist at gist.github.com/3085459. It works with Windows/Linux/OSX.

You can also feed it exclude patterns to weed out folders/files you don’t want to see. I will probably add something in the future that will distinguish folders from files. But it works pretty well.

Since windows doesn’t really have a root folder, it will just show all of your local drives instead of root. I have provided an example context menu though that can allow right clicking in a file and open the navigation panel in the folder of the current file.

This is probably my last post in regards to this unless someone shows some interest.

0 Likes

#15

I’ll chime in and show some interest. Thanks Facelessuser. Yours works better than mine (especially because yours is actually complete/functional). This is another case where viewtopic.php?f=4&t=7139&start=0 this would come in handy. Some placeholder text with the current path would provide some context. Right now its hard to tell what folder you’re in. Also, I’m curious as to why you just made a context-menu to activate it. Personally, though, I don’t think I’ll use this much since I’m happy with just using alfred.app on OSX.

0 Likes

#16

-Updated to show full file path.
-Updated to show document file size
-Updated to show file count of each folder
-Updated to exclude file/folder that is not accessible
-Updated context menu example to open fuzzy nav in computer root, or open at current open file

@COD312
I added the context menu in case to show how you could have a reveal in explorer type command. If you want to access a file close relative to the current open file in ST2. I have now updated it to allow opening it in root, or the current file. It was just an example is all.

0 Likes

#17

@facelessuser

I’ve been watching development of this plugin. The only reason I didn’t pipe up earlier is:

a) I didn’t want to be the guy who moans about more features again (but, as you’ll see, I am)
b) Until you added the command to open from the current directory, the plugin was unusable for me (starting from the root every time was nuts and I couldn’t figure how to change the behavior)
c) I was expecting it to fuzzy search – not my computer, but at least my home dir (on Linux)

I would be very interested in replacing the native OS open and save dialogs. They are slow and clunky compared with the rest of Sublime. (Admittedly, all my home computers are quite old.) I would like to be able to open and save folders and files quickly, without using the mouse, and in a consistent manner across OSs.

This plugin already does quite a few things quite well. Here’s a few features I would like, off the top of my head: (Feel free to disregard everything :smile: )

  • When opening from an untitled file with “open from current file’s folder”, use the folder of the last active tab (as the default open does now); currently, nothing happens.
  • Use right and left arrow keys to, respectively, open files/folders and go back to the previous folder. (I don’t know if the overlay supports this.) Probably should only work if no text has been entered.
  • Set up often used folders, so you can navigate faster. Maybe something like ~ (/home/username or “My Documents”), ~d[evices] (/media or “My Computer”).
  • Create new folders and files by entering a “New Folder Name/” or “new file.extension”
  • Find something useful for TAB to do. Maybe auto-fill panel with highlighted file/folder, so I can quickly save “my very long project - draft 1” as “my very long project - draft 2”
  • Hide dotted files and folders by default and enable them by typing “.”. I generally don’t want to see them, except when I do; which I would likely realize (if this is a setting that can only be switched outside of the overlay) after I have spent the time navigating to appropriate directory.
  • I would like some GoTo-like super efficient fuzziness, although I must admit that right now I am more likely to hit Ctrl+O than Ctrl+P when I need to open a file.

Oh, I should add that I preferred the learner, earlier version as there’s a slight delay between folder switches now. Maybe a binding/setting to turn the extra info on and off? I think that a simpler way to separate folders from files would be to indent the latter by a few spaces.

@fjl I also tried your plugin, but I couldn’t get it to work.

0 Likes

#18

@ quodlibet, unfortunately, the quick_panel doesn’t support a lot of what you’re requesting. There is no on_change for quick_panels, which means you can’t really update the quickpanel dynamically. I tried getting around this using a combination of text_commands + on_query_context + on_modified… but I ran into some issues.

0 Likes

#19

Maybe, I will look into to this, but this will not always work because the last active tab might very well be the untitled document.

Can’t do due to limitations. That would be neat, but currently not possible.

You can already do this by issue the command with the start parameter. You can create as many commands as you want. The example below is for the context menu, but you can create shortcut commands, etc.
[pre=#000000] {
“caption”: “Fuzzy Nav”,
“command”: “fuzzy_file_nav”,
“args”: {
“start”: “/home/username”,
“regex_exclude”: “.*\.(DS_STORE|svn|git)$”]
}
},[/pre]

I can probably create a wrapper command that can take an array of paths and let you choose which of your favorites you want to drill down, and then issue the nav command with that path in the start parameter.

This is possible, I will consider this.

Unfortunately, quick panel won’t let me.

Dynamic updated of the list is not possible, that is why I just have a regex exclusion pattern. You could create two commands, one that filters out hidden files, and one that shows them.

Not sure what you mean here.

Yeah, that is why I added the other option. It is very configurable. That option is just an example.

I might allow a deep directory search option in the future that you could toggle on. But searching a lot of folders may take a while. I won’t promise this feature, but maybe.

Yeah, I am still goofing around with it. Directories are now first followed by files, but I will consider the space suggestion. I do understand the info problem, though it does have the extra benefit of allowing me to determine if a folder is accessible. I can probably disable it as an option and just catch when you try to access a folder that is inaccessible.

Thanks for the interest, and no worries about being “that guy”; actual criticism and suggestions makes stuff better. I may move this to a more formal repo and start adding some features and create a specific thread for this plugin.

0 Likes

#20

[quote=“facelessuser”]
Thanks for the interest, and no worries about being “that guy”; actual criticism and suggestions makes stuff better.[/quote]

I’ve bound Ctrl+O to FuzzyFileNav on my computers at home and I’ll do the same at work tomorrow. I’ll let you know in a couple of days if I have any hair left :neutral_face:

[quote]

Maybe, I will look into to this, but this will not always work because the last active tab might very well be the untitled document.[/quote]

Ah, I see the difficulty. I meant the last saved tab.

[quote]

This is possible, I will consider this.[/quote]

If its doable, this seems a more elegant solution than the one SublimeFileNavigator uses, which puts the options in the panel. It also seems unambiguous, since you cannot type past a directory (e.g., /home/foo).

That said, having used FuzzyFileNav for a couple (?) hours now as my open command, I miss being able to type through directories. E.g., /home/foo/docs. (Does this make sense?)

I think binding two commands, one to Ctrl+O for opening from the current dir and one to, say, Ctrl+Shift+O for opening favorite folders (much like your FavoriteFiles > Open) should do the trick. If I understand you, the wrapper would be this layer of favorite folders before you start navigating the filesystem, right?

[quote]

Not sure what you mean here.[/quote]

Yeah. That makes two of us. There’s something “off” about using the plugin, but I can’t quite put my finger on it.

I actually meant both at the same time:

Some Dir
Other Dir
Another Dir
    File.txt
    Other file.sh
    Et cetera.html

I think there needs to be a very clear distinction between files and folders. Maybe some slashes would help (e.g., Some Dir/).

The point that C0D312 raised about determining the current directory is related here. If you decide to go with less info (or provide an option to do so), it’s pretty difficult to tell which directory you’re at. (It’s pretty difficult as it is.) One, probably bad, idea might be to tack the current directory under the .. since it appears in all situations (including the root folder).

Alex

0 Likes