Skip to content

Commit

Permalink
More useful examples
Browse files Browse the repository at this point in the history
  • Loading branch information
deanishe committed Sep 17, 2017
1 parent 5c08ba9 commit f447ed5
Show file tree
Hide file tree
Showing 26 changed files with 658 additions and 4,746 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# ignore binary
/fuzzy-custom
/bookmarks
138 changes: 138 additions & 0 deletions examples/bookmarks/bookmarks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//
// Copyright (c) 2017 Dean Jackson <[email protected]>
//
// MIT Licence. See http://opensource.org/licenses/MIT
//
// Created on 2017-09-17
//

package main

import (
"fmt"
"log"
"net/url"
"os"

"github.com/DHowett/go-plist"
"github.com/deanishe/awgo/fuzzy"
)

var (
// Where Safari stores its bookmarks
bookmarksPath = os.ExpandEnv("$HOME/Library/Safari/Bookmarks.plist")
)

// Bookmarks is a slice of Bookmark structs that implements fuzzy.Interface.
type Bookmarks []*Bookmark

// Implement sort.Interface.
func (b Bookmarks) Len() int { return len(b) }
func (b Bookmarks) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b Bookmarks) Less(i, j int) bool { return b[i].Title < b[j].Title }

// SortKey implements fuzzy.Interface.
func (b Bookmarks) SortKey(i int) string {
return fmt.Sprintf("%s %s", b[i].Title, b[i].Domain)
}

// Filter filters bookmarks against query using a fuzzy.Sorter.
func (b Bookmarks) Filter(query string) Bookmarks {
hits := b[:0]
srt := fuzzy.New(b)
res := srt.Sort(query)
for i, r := range res {
if !r.Match {
continue
}
hits = append(hits, b[i])
}
return hits
}

// Bookmark is a Safari bookmark.
type Bookmark struct {
Title string // Bookmark title
Domain string // Domain of URL
URL string // Bookmark URL
}

// entry is an node in Safari's Bookmarks.plist file. This struct
// matches all types of nodes in the file.
type entry struct {
Title string `plist:"Title"`
Type string `plist:"WebBookmarkType"`
URL string `plist:"URLString"`
UUID string `plist:"WebBookmarkUUID"`
URIDict map[string]string `plist:"URIDictionary"`
Children []*entry `plist:"Children"`
}

// loadBookmarks parses the Safari bookmarks file.
func loadBookmarks() (Bookmarks, error) {
file, err := os.Open(bookmarksPath)
if err != nil {
return nil, err
}

root := entry{}
entries := []*entry{}
dec := plist.NewDecoder(file)
if err := dec.Decode(&root); err != nil {
return nil, err
}

// Recursively parse tree. The children of root are the top-level folders.
for _, e := range root.Children {
if e.Title == "BookmarksBar" || e.Title == "BookmarksMenu" {
entries = append(entries, extractLeafEntries(e)...)
}
}

// Convert raw entries to bookmarks
bkm := []*Bookmark{}
// Ignore dupes
seen := map[string]bool{}

for _, e := range entries {
// Use title & URL for dupe key, as you probably want bookmarks
// with different titles to stil be shown, even if the URL is
// a duplicate
key := e.Title + e.URL
if seen[key] == true {
continue
}

// Convert entry to Bookmark
var title string
if e.Title != "" {
title = e.Title
} else {
title = e.URIDict["title"]
}
u, err := url.Parse(e.URL)
if err != nil {
log.Printf("couldn't parse URL \"%s\" (%s): %v", e.URL, title, err)
continue
}

seen[key] = true
bkm = append(bkm, &Bookmark{Title: title, Domain: u.Host, URL: e.URL})
}

return bkm, nil
}

// extractLeafEntries recursively finds all bookmarks under root.
func extractLeafEntries(root *entry) []*entry {
entries := []*entry{}
for _, e := range root.Children {
// Bookmarks have type "WebBookmarkTypeLeaf"
if e.Type == "WebBookmarkTypeLeaf" {
entries = append(entries, e)
} else if len(e.Children) > 0 { // Recursively add children
entries = append(entries, extractLeafEntries(e)...)
}
}
return entries
}
Binary file added examples/bookmarks/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 13 additions & 10 deletions examples/fuzzy-custom/info.plist → examples/bookmarks/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
<key>createdby</key>
<string>Dean Jackson</string>
<key>description</key>
<string>Explore Top iTunes Podcasts</string>
<string>Filter Safari Bookmarks</string>
<key>disabled</key>
<false/>
<key>name</key>
<string>AwGo Demo: Custom Fuzzy Search</string>
<string>AwGo Demo: Bookmarks</string>
<key>objects</key>
<array>
<dict>
Expand All @@ -44,7 +44,7 @@
<key>escaping</key>
<integer>102</integer>
<key>keyword</key>
<string>workflows</string>
<string>bookmarks</string>
<key>queuedelaycustom</key>
<integer>3</integer>
<key>queuedelayimmediatelyinitially</key>
Expand All @@ -54,17 +54,17 @@
<key>queuemode</key>
<integer>1</integer>
<key>runningsubtext</key>
<string>Loading workflows</string>
<string>Loading bookmarks</string>
<key>script</key>
<string>./fuzzy-custom "$1"</string>
<string>./bookmarks "$1"</string>
<key>scriptargtype</key>
<integer>1</integer>
<key>scriptfile</key>
<string></string>
<key>subtext</key>
<string>Search a list of Alfred workflows</string>
<string>Search your Safari bookmarks</string>
<key>title</key>
<string>Alfred Workflows on GitHub</string>
<string>Safari Bookmarks</string>
<key>type</key>
<integer>0</integer>
<key>withspace</key>
Expand Down Expand Up @@ -98,9 +98,12 @@
</dict>
</array>
<key>readme</key>
<string>Filter a list of workflows from GitHub.
<string>AwGo: Search Safari bookmarks
=============================
Based on search results for the topic "alfred-workflow".</string>
This workflow demonstrates implementing fuzzy.Interface on your own structs.
See file bookmarks.go.</string>
<key>uidata</key>
<dict>
<key>1ECEC7CE-5E5D-4F07-A284-F5976DADCC2B</key>
Expand All @@ -113,7 +116,7 @@ Based on search results for the topic "alfred-workflow".</string>
<key>3BF10786-C7AA-4EAF-AF73-08CFB7CA918F</key>
<dict>
<key>note</key>
<string>Filter list of workflows</string>
<string>Filter your Safari bookmarks</string>
<key>xpos</key>
<integer>40</integer>
<key>ypos</key>
Expand Down
98 changes: 98 additions & 0 deletions examples/bookmarks/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Copyright (c) 2017 Dean Jackson <[email protected]>
//
// MIT Licence. See http://opensource.org/licenses/MIT
//
// Created on 2017-09-09
//

/*
Workflow bookmarks demonstrates implementing fuzzy.Interface.
It loads your Safari bookmarks from ~/Library/Safari/Bookmarks.plist
into the Bookmarks struct, which implements fuzzy.Interface and a
Filter() method, which returns another Bookmarks struct containing
all bookmarks that match the given query.
See bookmarks.go for the implementation.
*/
package main

import (
"fmt"
"log"

"github.com/deanishe/awgo"
"github.com/docopt/docopt-go"
)

var (
helpURL = "http://www.deanishe.net"
maxResults = 200
wf *aw.Workflow
icon = &aw.Icon{ // Icon for bookmark filetype
Value: "com.apple.safari.bookmark",
Type: aw.IconTypeFileType,
}
)

var (
usage = `bookmarks [options] [<query>]
Usage:
bookmarks <query>
bookmarks -h|--version
Options:
-h, --help Show this message and exit
--version Show version number and exit
`
)

func init() {
wf = aw.New(aw.HelpURL(helpURL), aw.MaxResults(maxResults))
}

func run() {
var query string

// Parse command-line arguments
args, err := docopt.Parse(usage, wf.Args(), true, wf.Version(), false)
if err != nil {
wf.Fatal(fmt.Sprintf("couldn't parse CLI flags: %v", err))
}

if s, ok := args["<query>"].(string); ok {
query = s
}
log.Printf("[main] query=%s", query)

// Load bookmarks
bookmarks, err := loadBookmarks()
if err != nil {
wf.FatalError(err)
}
log.Printf("%d total bookmark(s)", len(bookmarks))

// Filter bookmarks based on user query
if query != "" {
bookmarks = bookmarks.Filter(query)
}

// Generate results for Alfred
for _, b := range bookmarks {
wf.NewItem(b.Title).
Subtitle(b.URL).
Arg(b.URL).
UID(b.Title + b.URL).
Icon(icon).
Valid(true)
}

wf.WarnEmpty("No matching bookmarks", "Try a different query?")
wf.SendFeedback()
}

func main() {
wf.Run(run)
}
6 changes: 3 additions & 3 deletions examples/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
//

/*
Each subdirectory contains a complete, but trivial, Alfred workflow
demonstrating a feature of AwGo.
Each subdirectory contains a trivial, but complete, Alfred workflow
demonstrating a feature of AwGo and/or a useful workflow idiom.
After building the executable, copy or symlink the directory to Alfred's
workflow directory to try it out.
Expand All @@ -21,7 +21,7 @@ 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
workflow-install -s /path/to/example/workflow
which will symlink the workflow to Alfred's workflow directory.
*/
Expand Down
Loading

0 comments on commit f447ed5

Please sign in to comment.