Jump to content
vitor

Invisible info for Alfred to filter with

Recommended Posts

Posted (edited)

Alfred filters results in Script Filters is a great time saver. However, it’s rather limited as it only filters from the title. Initially I was hoping it would work at least on subtitle as well (i.e. on all visible info).


Even better would be to add a new JSON key — filter_info — that would not be shown anywhere but where we could store info that would be used to filter the item, in addition to its title.

 

Another idea would be add a new option to Run Behaviour that’d let us pick what keys to consider when auto-filtering.


As an example use case, I would use it on my Pinboard Workflow to allow pages to be filtered by description and tags.

Edited by vitor

Share this post


Link to post
Share on other sites

I've been thinking for some time about writing a helper program to replace Alfred's search. 

 

Apart from only searching titles, word-starts-with isn't a good fit for a lot of workflows.

Share this post


Link to post
Share on other sites
13 hours ago, deanishe said:

I've been thinking for some time about writing a helper program to replace Alfred's search. 

 

I’m picturing a single binary (alfred_filter) that’d take two arguments: a string to search and an Alfred-formated JSON, and the tool would return the JSON with only the items that matched. Is that what you had in mind?


In addition to my original idea, it could also be an addition to “Run Behaviour” that’d let us pick what keys to consider when auto-filtering.

Share this post


Link to post
Share on other sites
Posted (edited)
1 hour ago, vitor said:

Is that what you had in mind?

 

That was my first idea. I don't think it's a great solution, however, as your script would run every time, and I'd like to emulate the behaviour of "Alfred filters results" (i.e. your script is only run once per workflow "session").

 

So what I'm thinking is a single binary that you pass your command to (fuzzy is the filter program):

export FUZZY_MAX_RESULTS=200
export FUZZY_SEARCH_KEY=title
export FUZZY_QUERY="$1"
./fuzzy ./my_script_filter.sh --option --another-option

It would basically work like "Alfred filters results". It runs your script once to get all items, and caches the output for the duration of the workflow session (i.e. until the user closes Alfred or runs a different workflow).

 

Configuring via envvars seems the simplest way, though command-line options would work, too. By default it would search the title field of each item, but you could configure it to search a different field, say, fuzzy_keywords.

 

I already have session-scoped data in Alfred-Workflow, and it works really well.

 

i could cobble together a proof-of-concept in Go with bits of code ripped out of my Go library, but I think the production version would have to be written in Swift/Objective-C, as Go binaries are always statically-compiled and therefore huge (we're probably talking ~5MB). Python/Ruby/PHP etc. would be far too slow.

 

Edited by deanishe

Share this post


Link to post
Share on other sites
8 hours ago, deanishe said:

we're probably talking ~5MB

 

If it’s fast enough, I’d rather have those extra 5MBs and the better filtering than not.

Share this post


Link to post
Share on other sites
40 minutes ago, vitor said:

 

If it’s fast enough, I’d rather have those extra 5MBs and the better filtering than not.

 

Me, too. But I'm thinking big here, and I intend to either (a) totally supplant "Alfred filters results" by providing an objectively superior solution or, ideally, (b) get @Andrew to implement a more useful search algorithm than word-in-title-starts-with. As such, I don't want users to have a dozen or more workflows containing the exact same 5MB binary if it can be avoided.

 

IMO, Alfred's built-in "Alfred filters results" feature is mediocre in terms of result quality. Alfred itself augments it with a fuzzy-like search for core items like applications.

 

Like much of Alfred, the "Alfred filters results" search prioritises performance, and imo, it comes down squarely on the wrong side of the speed-quality equation.

 

Alfred may be able to comfortably handle 50K results with its "Alfred filters results" search, while a fuzzy search in a comparably fast language can "only" handle ~15K with comparable speed (i.e. without perceptible delay), but that trade-off for fuzzy search vs "word starts with" is totally worth it 99% of the time for me, especially when Alfred's native search is title-only.

 

I also have reservations similar to Go regarding Swift. I'm not sure which versions of OS X/macOS have the Swift libraries, which would allow a dynamically-compiled binary. Having to statically compile the Swift binary would add 2–3MB to its size.

 

Does anyone know which OS X/macOS versions include the Swift libraries?

Share this post


Link to post
Share on other sites

I'm happy to improve the "Alfred Filters Results", I've opened a ticket. I like @vitor's idea of a filter field in the JSON which could define an array of match phrases.

 

I've raised an internal ticket to look into this - be sure to @ me in here if you have any further thoughts or ideas :)

 

Cheers,

Andrew

Share this post


Link to post
Share on other sites

Unsurprisingly, I'd like Alfred's filter to work in a similar way to the one in my Go library. Specifically, that means a separate field for search terms and a fuzzy search algorithm like Sublime Text's.

 

The main issue I have with Alfred's current algorithm is that it differs from the first-/capital-letters search I'm used to from Alfred's core search and most workflows.

 

The fuzzy algorithm linked above is slower than word-starts-with or first-/capital-letters searches, but supports both those "modes" and is much more flexible besides.

Share this post


Link to post
Share on other sites

So thinking about this a little more, when "Alfred filters results" is selected, it'll be something along the lines of a top level "filter" object which contains type, match and limit.

 

The type would be "words" (default, as per current matching), "fuzzy" which matches the App fuzzy settings, and "regex" which would allow fully custom matching. If using regex, you'd populate a regex field too.


Populating "limit" would stop the matches after this number of matches is met. Leaving this out would mean match on all returned results as per current matching

 

Populating a "match" field per result item with either a string or array would define what each row is matched against. Leaving this out would default to each result title as per current matching.

 

To switch the mode to match the title on how Alfred matches on applications, you'd use:

{
	"filter": {
		"type": "fuzzy"
	}
}

An example of a fully populated filter in the JSON output could be the following, which does regex matching per result on the given terms.

{
	"filter": {
		"type": "regex",
		"regex": "/someregex/",
		"limit": 40
	},
	"items": [
		{
			...
			"match": ["match term 1", "match term 2"],
			...
		}
	]
}

There is a good chance I'd also add a global workflow setting to change the default matching mode to "fuzzy" when the "filter" object is missing from the JSON.

 

Cheers,

Andrew

Share this post


Link to post
Share on other sites

... Thinking about this even more, the filter options may actually just go off a cog next to the "Alfred filters results" button, leaving the optional "match" field in the JSON.

Share this post


Link to post
Share on other sites

Looks interesting. A few questions:

 

  1. Does match need to be an array, rather than a string? How would ["term1", "term2"] differ from ["term1 term2"]?
  2. How would regex work? How would that interact with a user-entered query (as used by fuzzy and words modes)?
  3. How would regex matches be ranked?
  4. How about limit? From the description, it sounds like Alfred would take the first N matches and drop any remaining items on the floor, rather than only show the N best matches? I think it's unlikely that people would want the first matches rather than the best ones.

Share this post


Link to post
Share on other sites
1 minute ago, Andrew said:

... Thinking about this even more, the filter options may actually just go off a cog next to the "Alfred filters results" button, leaving the optional "match" field in the JSON.

 

I think that would make more sense: being able to change the filter method of a Script Filter on the fly doesn't strike me as being particularly useful.

Share this post


Link to post
Share on other sites
2 minutes ago, deanishe said:

I think that would make more sense: being able to change the filter method of a Script Filter on the fly doesn't strike me as being particularly useful.

 

That's exactly what I was thinking.

Share this post


Link to post
Share on other sites
5 minutes ago, deanishe said:

Looks interesting. A few questions:

 

  1. Does match need to be an array, rather than a string? How would ["term1", "term2"] differ from ["term1 term2"]?
  2. How would regex work? How would that interact with a user-entered query (as used by fuzzy and words modes)?
  3. How would regex matches be ranked?
  4. How about limit? From the description, it sounds like Alfred would take the first N matches and drop any remaining items on the floor, rather than only show the N best matches? I think it's unlikely that people would want the first matches rather than the best ones.

 

1. Match can be terms or a string, and it will be OR'ed... so "term1" would match and "term2" would match, but "term1 term2" wouldn't match. But as I said, it'll take just a string so you could do either.

 

2. regex would take the user's query and match it against the title, or whatever has been populated in the match field. This would ultimately give you full control over which results match.

 

3. Not sure yet, but it'd likely be same as current sorting, at least in the first iteration (where it uses Alfred's knowledge).

 

4. (and continuation of 3) this is certainly something to think about, perhaps for a later iteration though as it adds quite a bit of complexity. Something I'd be interested in tackling though.

Share this post


Link to post
Share on other sites
Posted (edited)
2 hours ago, Andrew said:

it adds quite a bit of complexity

 

How so? Score-sort-truncate is barely more complex than score-break-sort, unless you aren't doing score and/or sort.

 

2 hours ago, Andrew said:

Something I'd be interested in tackling though.

 

By way of a bug, early versions of Alfred-Workflow's filter returned the first N matches, not the best N. You get a lot of crappy and unexpected results (e.g. exact matches that should be the top results are completely missing).

 

Better to have no limit than a first-N-matches limit, imo. As noted, it's rare that you would want the first N matches of any quality over the best N matches. I think it would lead to lots of questions along the lines of, "Why doesn't Alfred find 'John Smith' when I enter 'john'?", because Alfred has stopped looking after it found N people who work at Johnson & Johnson.

 

Edited by deanishe

Share this post


Link to post
Share on other sites

@deanishe we may be talking about slightly different things... With script filters, Alfred doesn't do any magical ranking of 'closeness' of typed query to the result. I thought this was what you were referring to, and something I was saying could be interesting to take on as a future iteration.

 

I now see what you mean, using Alfred's knowledge, you wouldn't want to drop/truncate results before looking at the knowledge.

 

It may be best to just leave off the limit.

 

Cheers,

Andrew

Share this post


Link to post
Share on other sites
7 minutes ago, Andrew said:

I thought this was what you were referring to

 

It was. I assumed Alfred applies some sort of ranking to results, especially fuzzy matches, even if only applying its knowledge.

Share this post


Link to post
Share on other sites

@deanishe it does do result ranking (and latching) in a number of different ways using usage knowledge, but not closeness of typed query to match... so in answer to your question of how would regex be ranked, it would be ranked in the same way as Alfred currently does things in that if the result matches the regex (yes or no, not weighted), then it's passed along to the knowledge which subsequently sorts all the results.

Share this post


Link to post
Share on other sites

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

×