Skip to content

Commit

Permalink
Add better example for customised fuzzy search
Browse files Browse the repository at this point in the history
  • Loading branch information
deanishe committed Sep 12, 2017
1 parent dfd09fb commit fb65180
Show file tree
Hide file tree
Showing 20 changed files with 4,557 additions and 58 deletions.
16 changes: 12 additions & 4 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ Upcoming features
These features may be implemented:
- TODO: Alfred/AppleScript helpers?
- TODO: Implement standard-compliant pre-release comparison in SemVer?
Usage
Expand Down Expand Up @@ -74,16 +73,22 @@ The Item struct isn't intended to be used as the workflow's data model,
just as a way to encapsulate search results for Alfred. In particular,
its variables are only settable, not gettable.
Most package-level functions call the methods of the same name on the default
Workflow struct. If you want to use custom options, you can create a new
Workflow with New(), or get the default Workflow with DefaultWorkflow()
and configure it with Workflow.Configure().
Fuzzy filtering
Subpackage fuzzy provides a fuzzy search algorithm modelled on Sublime
Text's search. Implement fuzzy.Interface to make an object fuzzy-sortable.
Text's search. Implement fuzzy.Interface to make a struct fuzzy-sortable.
The Feedback struct implements this interface.
Workflow and Feedback structs provide an additional Filter() method,
which fuzzy-sorts Items and removes any that do not match the query.
Feedback and Workflow structs provide an additional Filter() method,
which fuzzy-sorts the contained Items and removes any that do not match
the query.
See examples/fuzzy-simple for a basic demonstration.
Expand All @@ -106,6 +111,7 @@ calls to sending methods are logged and ignored. Sending methods are:
Fatalf()
FatalError()
Warn()
WarnEmpty() // if there are no items
The Workflow struct (more precisely, its Feedback struct) retains the
Item, so you don't need to. Just populate it and then call
Expand All @@ -125,6 +131,8 @@ message (and icon), but does not terminate the workflow. However,
because the JSON has already been sent to Alfred, you can't send any
more results after calling Warn().
WarnEmpty() calls Warn() if there are no (other) Items to send to Alfred.
If you want to include a warning with other results, use NewWarningItem().
Expand Down
28 changes: 28 additions & 0 deletions examples/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// Copyright (c) 2017 Dean Jackson <[email protected]>
//
// MIT Licence. See http://opensource.org/licenses/MIT
//
// Created on 2017-09-08
//

/*
Each subdirectory contains a complete, but trivial, Alfred workflow
demonstrating a feature of AwGo.
After building the executable, copy or symlink the directory to Alfred's
workflow directory to try it out.
You can use the following script to simplify installing/symlinking workflows
that are still in development:
https://gist.github.com/deanishe/35faae3e7f89f629a94e
If you've installed that script on your $PATH, you can try out the examples by
running:
workflow-install -s /path/to/example
which will symlink the workflow to Alfred's workflow directory.
*/
package examples
14 changes: 6 additions & 8 deletions examples/fuzzy-cached/fuzzy-cached.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
//

/*
Command fuzzy-cached demonstrates custom fuzzy-sortable structs and handling
larger datasets in AwGo, caching the data in a format that's
more quickly loaded.
Command fuzzy-cached is a complete Alfred 3 workflow.
It demonstrates custom fuzzy-sortable structs and handling larger datasets
in AwGo, caching the data in a format that's more quickly loaded.
It filters a list of the books from the Gutenberg project. The list
(a TSV file) is downloaded on first run, parsed and cached to disk
Expand All @@ -22,8 +23,6 @@ acceptable performance, imo.
A dataset of this size would be better off in an sqlite database, which
can easily handle this amount of data.
This demo is a complete Alfred 3 workflow.
*/
package main

Expand Down Expand Up @@ -85,8 +84,7 @@ type Book struct {
ID int
Author string
Title string
// Page where you can download the book in multiple formats.
URL string
URL string // Page where you can download the book in multiple formats.
}

// Books is a slice of Book structs that implements fuzzy.Interface.
Expand All @@ -101,7 +99,7 @@ func (b Books) Less(i, j int) bool { return b[i].Title < b[j].Title }
// Swap implements sort.Interface
func (b Books) Swap(i, j int) { b[i], b[j] = b[j], b[i] }

// SortKey implements Sortable interface
// SortKey implements fuzzy.Interface.
func (b Books) SortKey(i int) string {
return fmt.Sprintf("%s %s", b[i].Author, b[i].Title)
}
Expand Down
4 changes: 3 additions & 1 deletion examples/fuzzy-cached/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<key>description</key>
<string>Filter Gutenberg Ebooks</string>
<key>disabled</key>
<false/>
<true/>
<key>name</key>
<string>AwGo Demo: Fuzzy Search (Very Large) Cached Dataset</string>
<key>objects</key>
Expand Down Expand Up @@ -54,6 +54,8 @@
<dict>
<key>alfredfiltersresults</key>
<false/>
<key>alfredfiltersresultsmatchmode</key>
<integer>0</integer>
<key>argumenttrimmode</key>
<integer>0</integer>
<key>argumenttype</key>
Expand Down
2 changes: 2 additions & 0 deletions examples/fuzzy-custom/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore binary
/fuzzy-custom
90 changes: 90 additions & 0 deletions examples/fuzzy-custom/alfred_workflows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python
# encoding: utf-8
#
# Copyright (c) 2017 Dean Jackson <[email protected]>
#
# MIT Licence. See http://opensource.org/licenses/MIT
#
# Created on 2017-09-12
#

"""Fetch list of Alfred workflows on GitHub."""

from __future__ import print_function, absolute_import

import json
import os
import sys

import requests

# Base search URL
API_URL = 'https://api.github.com/search/repositories?per_page=100'
# What to search for
QUERY = 'topic:alfred-workflow'
# Where to save results
OUTPUT = os.path.join(os.path.dirname(__file__), 'workflows.json')
# Enable beta API features (needed for topics)
HEADERS = {'Accept': 'application/vnd.github.mercy-preview+json'}


def log(s, *args):
"""Simple STDERR logger."""
if args:
s = s % args
print(s, file=sys.stderr)


def fetch():
"""Retrieve search results from GitHub."""
results = []
page_count = 0
page_number = 1
while True:
if page_count and page_number > page_count:
break

log('fetching page %d ...', page_number)

r = requests.get(API_URL, {'q': QUERY, 'page': page_number},
headers=HEADERS)
log('[%s] %s', r.status_code, r.url)
r.raise_for_status()

data = r.json()
page_number += 1

# populate page_count
if not page_count:
total_results = data.get('total_count', 100)
page_count = total_results / 100
if total_results % 100:
page_count += 1

log('%d results on %d pages', total_results, page_count)

# extract workflows
for d in data.get('items', []):
results.append(dict(
name=d['name'],
description=d['description'],
owner=d['owner']['login'],
url=d['html_url'],
stars=d['stargazers_count'],
topics=d.get('topics', []),
lang=d.get('language') or '',
))

return results


def main():
"""Fetch Alfred workflows from GitHub."""
results = fetch()
with open(OUTPUT, 'wb') as fp:
json.dump(results, fp, indent=2, sort_keys=True)

log('saved %d workflows to %s', len(results), OUTPUT)

if __name__ == '__main__':
main()
Loading

0 comments on commit fb65180

Please sign in to comment.