Jump to content

Recommended Posts

Fuzzy search across folder subtrees.

 

Update 10/09/2016:

  • Added Alfred 3 support and removed Alfred 2 support.
  • Added ability to self-update.

 

Update 10/04/2014:

  • Added support for glob-style excludes. Unfortunately, these have to be added manually to the settings file at the moment.

Update 05/04/2014:

  • Now supports searching files as well as/instead of folders
  • You can now adjust the minimum query length to improve search performance.

demo.gif

This Workflow provides partial matching of path components, allowing you to drill down into your filesystem with a space-separated query. Each "word" of the query will be matched against the components of a directory or file's path, so a three-word query will only match at least three levels down from the specified root directory.

You can use a File Action to intiate a fuzzy search on a folder or to assign a keyword to perform a fuzzy search on that folder.

Download

Get the Workflow from GitHub or Packal.

Commands

  • fuzzy — List your Fuzzy Folders
  • — Edit Fuzzy Folder settings
  • ⌘+↩ — Start a Fuzzy Folder search with the associated keyword
  • ⌥+↩ — Delete the keyword–Fuzzy Folder combination
  • fzyup — Recreate the Script Filters from your saved configuration (useful after an update)
  • fzyhelp — Open the help file in your browser

Settings

You can specify these settings globally as defaults for all Fuzzy Folders or on a per-folder basis. For ad-hoc searches via the Fuzzy Search Here file action, the default settings always apply.

Use keyword fuzzy to view and edit settings.

  • Minimum query length — The last "word" of a query must be this long to trigger a search. Default is 1, but increase this number if the search is too slow. This is very often the case if you're searching a large subtree and/or also choose to search files.
  • Search scope — Choose to search only for folders, files or both. Note: In most cases, searches including files are significantly slower. Consider increasing the minimum query length to speed up slow searches.

File Actions

  • Fuzzy Search Here — Fuzzy search this folder
  • Add Fuzzy Folder — Set a keyword for this folder for faster fuzzy searching

Search result actions

  • — Open folder in Finder
  • ⌘+↩ — Browse folder in Alfred

Bugs, questions, feedback

You can open an issue on GitHub, or post in this thread.

Licensing, other stuff

This Workflow is made available under the MIT Licence.

The icon was made by Jono Hunt.

It uses docopt and Alfred-Workflow.

Edited by deanishe
Workflow updated

Share this post


Link to post

Ta. I'm going to have to refactor out the code that manages the saved settings and adds Script Filters to info.plist based on them.

That could be very handy in a lot of workflows.

Share this post


Link to post

Ta. I'm going to have to refactor out the code that manages the saved settings and adds Script Filters to info.plist based on them.

That could be very handy in a lot of workflows.

That would be very handy. I'll keep my eyes on that code...

Share this post


Link to post

:)

The code that generates the Script Filters is pretty straightforward, just scattered around a bit.

I must admit, I think there's something deeply cool about a Workflow that can rewrite itself. I want to upgrade my Smart Folders workflow to the same "technology". I use that one a lot, and one of the things that puts me off fiddling with the code is having to recreate my custom Script Filters all the time.

Share this post


Link to post

Could you elaborate any on the methodology of such code? What does it look for in the settings? What does it add to the Script Filter info in the info.plist based on that data?

Share this post


Link to post

:)

The code that generates the Script Filters is pretty straightforward, just scattered around a bit.

I must admit, I think there's something deeply cool about a Workflow that can rewrite itself. I want to upgrade my Smart Folders workflow to the same "technology". I use that one a lot, and one of the things that puts me off fiddling with the code is having to recreate my custom Script Filters all the time.

Nice! Only issue I ran in to was that it seems to take a while to load the initial results. For example, when I typed 'e', it returned over 6,000 results and took a couple of seconds before any other characters were processed.

Unfortunately it doesn't look like you can limit the number of results with mdfind without dipping in to the C/Objective-C APIs. I suppose a quick and easy fix could be to ignore the search if the query's only one character long, since it'll likely be too noisy to find anything anyway.

 

Could you elaborate any on the methodology of such code? What does it look for in the settings? What does it add to the Script Filter info in the info.plist based on that data?

Basically, each script, keyword, action, etc. is stored as an object in a workflow’s info.plist. You can see them listed under <key>objects</key>. The important part is the uid field; Alfred associates each object with a unique ID (I believe it uses UUIDv4).

Alfred uses these UUIDs to keep track of each object’s relationship to another, which you can see below <key>connections</key>. Each of these relationships also has a unique ID, stored in the key field.

Alfred also keeps track of the graphical representation of the workflow’s objects under <key>uidata</key>. If you’re programmatically adding new objects, you’ll probably want to find the largest ypos of the objects, and increment it by about 120 so it aligns correctly each object is 96 px in height and typically has 26px of padding between other objects (though you can adjust this).

Share this post


Link to post

Could you elaborate any on the methodology of such code? What does it look for in the settings? What does it add to the Script Filter info in the info.plist based on that data?

info.plist is laid out just as Clinton describes it.

When you add or delete a Fuzzy Folder (or manually trigger an update with fzyup), the script deletes all the Script Filters from the objects array in info.plist it recognises as having put their itself (using a regex on the script command and a list of the Workflow's own keywords that it shouldn't delete) and the corresponding connections and positioning data.

Then it adds new Script Filters based on the Fuzzy Folders you've set up with corresponding connections to the Browse in Alfred action via its UID (which is hard-coded in the script), and gives them all a position in the UI (otherwise they'd all be in the same place). The position of the first one is hard-coded into the script.

Finally, info.plist is overwritten with the the updated version. Alfred picks up the changes after a few seconds.

 

Nice! Only issue I ran in to was that it seems to take a while to load the initial results. For example, when I typed 'e', it returned over 6,000 results and took a couple of seconds before any other characters were processed.

Unfortunately it doesn't look like you can limit the number of results with mdfind without dipping in to the C/Objective-C APIs. I suppose a quick and easy fix could be to ignore the search if the query's only one character long, since it'll likely be too noisy to find anything anyway.

I'm reluctant to require a minimum query length, as one-letter queries are something I use quite a lot (as in the demo in the OP). The thing regarding noise is that mdfind is only run with the last "word" of the query; the script then filters the results from mdfind based on the preceding words.

I see a few possibilities to improve performance:

  1. Kill the mdfind process after a few hundred results if there's only one word in the query. This won't help much, though, as most of the delay occurs before mdfind actually starts returning results.
  2. Cache the results from mdfind for a few seconds. Again, I don't think there's much to be gained by this, as mdfind caches its own results (subsequent runs with the same query are instant), and presumably knows more about how long its cache is valid.
  3. Don't send thousands of results to Alfred. This is a no-brainer, I guess.

I'll profile the code to see where most time is wasted, and add an option for the user to specify a minimum query length.

Edited by deanishe

Share this post


Link to post

Well, that is pretty much what I was looking for and couldn't find, so I fell back on my own decidedly iffy design skills.

Where'd you get the icon? Please don't tell me it's built in…

Share this post


Link to post

Brilliant! Thanks very much. I've updated the workflow accordingly. Not much point in your updating, I suppose, unless you want to see your name in the help file :)

What software did you use, btw?

Edited by deanishe

Share this post


Link to post

Nice! Only issue I ran in to was that it seems to take a while to load the initial results. For example, when I typed 'e', it returned over 6,000 results and took a couple of seconds before any other characters were processed.

Unfortunately it doesn't look like you can limit the number of results with mdfind without dipping in to the C/Objective-C APIs. I suppose a quick and easy fix could be to ignore the search if the query's only one character long, since it'll likely be too noisy to find anything anyway.

 

 

You can now specify a minimum query length to improve search performance.

Share this post


Link to post

Added a feature for power users: glob-style exclusions similar to .gitignore files.

I say power users because currently you have to add exclude patterns by hand to the settings.json file.

How to do that is documented in the README on GitHub and in the included help file (use fzyhelp in Alfred).

Just be sure to edit the file in a proper code editor and not TextEdit (which will break the file).

Edited by deanishe

Share this post


Link to post

Is there a way to "unfuzzy" a folder ?

 

 

p.s. By the way - this is currently the lifesaver for me. Thanks!

Edited by Norris

Share this post


Link to post

Hi deanishe!

 

As I was trying to make the workflow work I got this log in the console:

[ERROR: alfred.workflow.input.scriptfilter] Code 0: 21:06:40 ff.py:974 DEBUG    wf.args : [u'manage', u'']
21:06:40 ff.py:975 DEBUG    args : {u'<dir>': None,
 u'<profile>': None,
 u'<query>': u'',
 u'add': False,
 u'alfred-browse': False,
 u'alfred-search': False,
 u'choose': False,
 u'keyword': False,
 u'load-profile': False,
 u'load-settings': False,
 u'manage': True,
 u'open-help': False,
 u'remove': False,
 u'search': False,
 u'settings': False,
 u'update': False,
 u'update-setting': False}
21:06:40 ff.py:310 DEBUG    dirpath : None  query : u''

I finally can use the workflow but I thought you might be interested in this feedback.

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...