Jump to content

Fuzzy search helper for Script Filters

Recommended Posts

Add fuzzy search to your Script Filters

This is a simple script you can add to your Script Filters to replace "Alfred filters results" with a fuzzy search algorithm.






How it works

Instead of calling your script directly, you call it via fuzzy.py, which caches your script's output for the duration of the user session (as long as the user is using your workflow), and filters the titles of the items emitted by your script against the user's query using a fuzzy algorithm.

Example usage

fuzzy.py only works in Script Filters, and you should run it as a bash/zsh script (i.e. with Language = /bin/bash or Language = /bin/zsh).
Instead of running your own script directly, place ./fuzzy.py in front of it.
For example, if your Script Filter script looks like this:

/usr/bin/python myscript.py

You would replace it with:

# export user query to `query` environment variable, so `fuzzy.py` can read it
export query="$1"
# or if you're using "with input as {query}"
# export query="{query}"
# call your original script via `fuzzy.py`
./fuzzy.py /usr/bin/python myscript.py

Note: Don't forget to turn off "Alfred filters results"!



As the script is written in Python and uses a more complex matching algorithm, it can only handle a few thousands items at most before it becomes irritatingly sluggish (Alfred can handle many tens of thousands).

If there's interest in the script, I will rewrite it in a compiled language. My Go library uses the same algorithm, and it can comfortably handle 20K+ items.

You can grab a demo workflow from GitHub to see it in action.

See the GitHub repo for more information.

Link to post
  • 4 months later...

I've run into a hitch.  I want to use this to search a list of categories, then again within the same workflow to search elements within a category.  But the second run is always displaying the cached results of the first.  I tried duplicating the script and running each separately but it seems to still use the same session_id and hence display the cached results instead of the results of the second run.


Any quick & easy ways to reset the session ID?  I suppose I could duplicate it & change the os.getpid() to something else. 




I ungraciously and crudely solved the problem by


1. duplicating the file,

2. editing the duplicate copy

a. changing line 45 to 

SID = 'fuzzy_session_id_2'

b. changing the end of line 311 to 


I call the original in the first run and the modified duplicate in the second.  I'm sure it could be done more gracefully/elegantly/pythonically but that approach works for me.

Edited by dfay
Link to post
8 minutes ago, dfay said:

Any quick & easy ways to reset the session ID?


8 minutes ago, dfay said:

I suppose I could duplicate it & change the os.getpid() to something else


Wouldn't work. That's only used to set the session ID when none exists. The problem is that both Script Filters are reading the session ID from the same variable (and therefore using the same cache).


I've added a new session_var option. Put export session_var=filter2 (or some such) in your downstream Script Filter, so it stores its session ID in a different variable to the first one (and therefore uses a different cache).


1 hour ago, dfay said:

In case others need this info -- you can keep the fuzzy searching without sorting the results by deleting (or commenting out) the line 




Hmm. If you only want match/no match, without the ranking, you can do that 10x more quickly with re:

pat =  '.*' + '.*'.join(query) + '.*'
match = re.compile(pat, re.I).match


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...