awgo: github.com/deanishe/awgo Index | Examples | Files | Directories

package aw

import "github.com/deanishe/awgo"

Package aw is a "plug-and-play" development library/framework for Alfred 3 https://www.alfredapp.com/

It combines features for interacting with Alfred (feedback, settings, AppleScript API) with simple APIs for common workflow functionality (fuzzy search, caching, processes & updates) to make it easy to create a top-shelf workflow in very little time indeed.

AwGo is an opinionated framework that expects to be used in a certain way in order to eliminate boilerplate. It *will* panic if not run in a valid, minimally Alfred-like environment. At a minimum the following environment variables should be set to meaningful values:

alfred_workflow_bundleid
alfred_workflow_cache
alfred_workflow_data

// And if you're using the update API
alfred_workflow_version

NOTE: AwGo is currently in development. The API *will* change and should not be considered stable until v1.0. Until then, vendoring AwGo (e.g. with dep or vgo) is strongly recommended.

Docs: https://godoc.org/github.com/deanishe/awgo

Source: https://github.com/deanishe/awgo

Issues: https://github.com/deanishe/awgo/issues

Licence: https://github.com/deanishe/awgo/blob/master/LICENCE

Be sure to also check out the _examples/ subdirectory, which contains some simple, but complete, workflows that demonstrate the features of AwGo and useful workflow idioms.

Features

As of AwGo 0.14, all applicable features of Alfred 3.6 are supported.

The main features are:

- Simple access to workflow settings.
- Fluent API for generating Alfred JSON.
- Fuzzy filtering.
- Simple, but powerful, API for caching/saving workflow data.
- Run scripts and script code.
- Call Alfred's AppleScript API from Go.
- Read and write workflow settings from info.plist.
- Workflow update API with built-in support for GitHub releases.
- Pre-configured logging for easier debugging, with a rotated log file.
- Catches panics, logs stack trace and shows user an error message.
- "Magic" queries/actions for simplified development and user support.
- Some default icons based on macOS system icons.

Usage

Typically, you'd call your program's main entry point via Workflow.Run(). This way, the library will rescue any panic, log the stack trace and show an error message to the user in Alfred.

// script_filter.go

package main

// Import name is "aw"
import "github.com/deanishe/awgo"

// aw.Workflow is the main API
var wf *aw.Workflow

func init() {
	// Create a new *Workflow using default configuration
	// (workflow settings are read from the environment variables
	// set by Alfred)
	wf = aw.New()
}

func main() {
	// Wrap your entry point with Run() to catch and log panics and
	// show an error in Alfred instead of silently dying
	wf.Run(run)
}

func run() {
	// Create a new item
	wf.NewItem("Hello World!")
	// And send the results to Alfred
	wf.SendFeedback()
}

In the Script box (Language = "/bin/bash"):

./script_filter

Script Filters

To generate results for Alfred to show in a Script Filter, use the feedback API of Workflow:

// Create new items
NewItem()
NewFileItem()
NewWarningItem()

// Sorting/filtering results
Filter()

// Send feedback to Alfred
SendFeedback()

// Warning/error calls that drop all other Items on the floor
// and send feedback immediately
Warn()
WarnEmpty()
Fatal()      // exits program
Fatalf()     // exits program
FatalError() // exits program

You can set workflow variables (via feedback) with Workflow.Var, Item.Var and Modifier.Var.

See Workflow.SendFeedback for more documentation.

Run Script actions

Alfred requires a different JSON format if you wish to set workflow variables.

Use the ArgVars (named for its equivalent element in Alfred) struct to generate output from Run Script actions.

Be sure to set TextErrors to true to prevent Workflow from generating Alfred JSON if it catches a panic:

wf.Configure(TextErrors(true))

See ArgVars for more information.

Configuration

New() creates a *Workflow using the default values and workflow settings read from environment variables set by Alfred.

You can change defaults by passing one or more Options to New(). If you do not want to use Alfred's environment variables, or they aren't set (i.e. you're not running the code in Alfred), use NewFromEnv() with a custom Env implementation.

A Workflow can be re-configured later using its Configure() method.

Check out the _examples/ subdirectory for some simple, but complete, workflows which you can copy to get started.

See the documentation for Option for more information on configuring a Workflow.

Fuzzy filtering

AwGo can filter Script Filter feedback using a Sublime Text-like fuzzy matching algorithm.

Workflow.Filter() sorts feedback Items against the provided query, removing those that do not match.

Sorting is performed by subpackage fuzzy via the fuzzy.Sortable interface.

See _examples/fuzzy for a basic demonstration.

See _examples/bookmarks for a demonstration of implementing fuzzy.Sortable on your own structs and customising the fuzzy sort settings.

Logging

AwGo automatically configures the default log package to write to STDERR (Alfred's debugger) and a log file in the workflow's cache directory.

The log file is necessary because background processes aren't connected to Alfred, so their output is only visible in the log. It is rotated when it exceeds 1 MiB in size. One previous log is kept.

AwGo detects when Alfred's debugger is open (Workflow.Debug() returns true) and in this case prepends filename:linenumber: to log messages.

Workflow settings

The Config struct (which is included in Workflow as Workflow.Config) provides an interface to the workflow's settings from the Workflow Environment Variables panel. https://www.alfredapp.com/help/workflows/advanced/variables/#environment

Alfred exports these settings as environment variables, and you can read them ad-hoc with the Config.Get*() methods, and save values back to Alfred with Config.Set().

Using Config.To() and Config.From(), you can "bind" your own structs to the settings in Alfred:

// Options will be populated from workflow/environment variables
type Options struct {
	Server   string `env:"HOSTNAME"`
	Port     int    // use default: PORT
	User     string `env:"USERNAME"`
	Password string `env:"-"` // ignore
}

cfg := NewConfig()
opts := &Options{}

// Populate Config's fields from the corresponding environment variables.
if err := cfg.To(opts); err != nil {
	// handle error
}

And to save a struct's fields to the workflow's settings in Alfred:

// Defaults
opts = &Options{
	Server:   "localhost",
	Port:     6000,
}

// Save Options to Alfred
if err := cfg.From(opts); err != nil {
	// handle error
}

See the documentation for Config.To and Config.From for more information, and _examples/settings for a demo workflow based on the API.

Alfred actions

The Alfred struct provides methods for the rest of Alfred's AppleScript API. Amongst other things, you can use it to tell Alfred to open, to search for a query, or to browse/action files & directories.

See documentation of the Alfred struct for more information.

Storing data

AwGo provides a basic, but useful, API for loading and saving data. In addition to reading/writing bytes and marshalling/unmarshalling to/from JSON, the API can auto-refresh expired cache data.

See Cache and Session for the API documentation.

Workflow has three caches tied to different directories:

Workflow.Data     // Cache pointing to workflow's data directory
Workflow.Cache    // Cache pointing to workflow's cache directory
Workflow.Session  // Session pointing to cache directory tied to session ID

These all share the same API. The difference is in when the data go away.

Data saved with Session are deleted after the user closes Alfred or starts using a different workflow. The Cache directory is in a system cache directory, so may be deleted by the system or "System Maintenance" tools.

The Data directory lives with Alfred's application data and would not normally be deleted.

Scripts and background jobs

Subpackage util provides several functions for running script files and snippets of AppleScript/JavaScript code. See util for documentation and examples.

AwGo offers a simple API to start/stop background processes via Workflow's RunInBackground(), IsRunning() and Kill() methods. This is useful for running checks for updates and other jobs that hit the network or take a significant amount of time to complete, allowing you to keep your Script Filters extremely responsive.

See _examples/update and _examples/workflows for demonstrations of this API.

Index

Examples

Package Files

alfred.go background.go cache.go config.go config_bind.go doc.go env.go feedback.go icons.go magic.go workflow.go workflow_feedback.go workflow_options.go workflow_paths.go workflow_update.go

Constants

const (
    // Workflow info assigned in Alfred Preferences
    EnvVarName     = "alfred_workflow_name"     // Name of workflow
    EnvVarBundleID = "alfred_workflow_bundleid" // Bundle ID
    EnvVarVersion  = "alfred_workflow_version"  // Workflow version

    EnvVarUID = "alfred_workflow_uid" // Random UID assigned by Alfred

    // Workflow storage directories
    EnvVarCacheDir = "alfred_workflow_cache" // For temporary data
    EnvVarDataDir  = "alfred_workflow_data"  // For permanent data

    // Set to 1 when Alfred's debugger is open
    EnvVarDebug = "alfred_debug"

    // Theme info. Colours are in rgba format, e.g. "rgba(255,255,255,1.0)"
    EnvVarTheme            = "alfred_theme"                      // ID of user's selected theme
    EnvVarThemeBG          = "alfred_theme_background"           // Background colour
    EnvVarThemeSelectionBG = "alfred_theme_selection_background" // BG colour of selected item

    // Alfred info
    EnvVarAlfredVersion = "alfred_version"       // Alfred's version number
    EnvVarAlfredBuild   = "alfred_version_build" // Alfred's build number
    EnvVarPreferences   = "alfred_preferences"   // Path to "Alfred.alfredpreferences" file
    // Machine-specific hash. Machine preferences are stored in
    // Alfred.alfredpreferences/local/<hash>
    EnvVarLocalhash = "alfred_preferences_localhash"
)

Environment variables containing workflow and Alfred info.

Read the values with os.Getenv(EnvVarName) or via Alfred:

// Returns a string
Alfred.Get(EnvVarName)
// Parse string into a bool
Alfred.GetBool(EnvVarDebug)
const (
    DefaultLogPrefix   = "\U0001F37A"    // Beer mug
    DefaultMaxLogSize  = 1048576         // 1 MiB
    DefaultMaxResults  = 0               // No limit, i.e. send all results to Alfred
    DefaultSessionName = "AW_SESSION_ID" // Workflow variable session ID is stored in
    DefaultMagicPrefix = "workflow:"     // Prefix to call "magic" actions
)

Default Workflow settings. Can be changed with the corresponding Options.

See the Options and Workflow documentation for more information.

const AwGoVersion = "0.14.0"

AwGoVersion is the semantic version number of this library.

Variables

var (
    // Workflow's own icon
    IconWorkflow = &Icon{"icon.png", IconTypeImage}

    // System icons
    IconAccount   = &Icon{Value: sysIcons + "Accounts.icns"}
    IconBurn      = &Icon{Value: sysIcons + "BurningIcon.icns"}
    IconClock     = &Icon{Value: sysIcons + "Clock.icns"}
    IconColor     = &Icon{Value: sysIcons + "ProfileBackgroundColor.icns"}
    IconColour    = &Icon{Value: sysIcons + "ProfileBackgroundColor.icns"}
    IconEject     = &Icon{Value: sysIcons + "EjectMediaIcon.icns"}
    IconError     = &Icon{Value: sysIcons + "AlertStopIcon.icns"}
    IconFavorite  = &Icon{Value: sysIcons + "ToolbarFavoritesIcon.icns"}
    IconFavourite = &Icon{Value: sysIcons + "ToolbarFavoritesIcon.icns"}
    IconGroup     = &Icon{Value: sysIcons + "GroupIcon.icns"}
    IconHelp      = &Icon{Value: sysIcons + "HelpIcon.icns"}
    IconHome      = &Icon{Value: sysIcons + "HomeFolderIcon.icns"}
    IconInfo      = &Icon{Value: sysIcons + "ToolbarInfo.icns"}
    IconNetwork   = &Icon{Value: sysIcons + "GenericNetworkIcon.icns"}
    IconNote      = &Icon{Value: sysIcons + "AlertNoteIcon.icns"}
    IconSettings  = &Icon{Value: sysIcons + "ToolbarAdvanced.icns"}
    IconSwirl     = &Icon{Value: sysIcons + "ErasingIcon.icns"}
    IconSwitch    = &Icon{Value: sysIcons + "General.icns"}
    IconSync      = &Icon{Value: sysIcons + "Sync.icns"}
    IconTrash     = &Icon{Value: sysIcons + "TrashIcon.icns"}
    IconUser      = &Icon{Value: sysIcons + "UserIcon.icns"}
    IconWarning   = &Icon{Value: sysIcons + "AlertCautionIcon.icns"}
    IconWeb       = &Icon{Value: sysIcons + "BookmarkIcon.icns"}
)

Ready-to-use icons based on macOS system icons. These icons are all found in

/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources

The icons are the same as found in the Alfred-Workflow library for Python. Preview them here: http://www.deanishe.net/alfred-workflow/guide/icons.html#list-of-icons

func EnvVarForField Uses

func EnvVarForField(name string) string

EnvVarForField generates an environment variable name from a struct field name. This is documented to show how the automatic names are generated.

Rules for generating an environment variable name from a struct field name.

Code:

// Single-case words are upper-cased
fmt.Println(EnvVarForField("URL"))
fmt.Println(EnvVarForField("name"))
// Words that start with fewer than 3 uppercase chars are upper-cased
fmt.Println(EnvVarForField("Folder"))
fmt.Println(EnvVarForField("MTime"))
// But with 3+ uppercase chars, the last is treated as the first
// char of the next word
fmt.Println(EnvVarForField("VIPath"))
fmt.Println(EnvVarForField("URLEncoding"))
fmt.Println(EnvVarForField("SSLPort"))
// Camel-case words are split on case changes
fmt.Println(EnvVarForField("LastName"))
fmt.Println(EnvVarForField("LongHorse"))
fmt.Println(EnvVarForField("loginURL"))
fmt.Println(EnvVarForField("newHomeAddress"))
fmt.Println(EnvVarForField("PointA"))
// Digits are considered the end of a word, not the start
fmt.Println(EnvVarForField("b2B"))

Output:

URL
NAME
FOLDER
MTIME
VI_PATH
URL_ENCODING
SSL_PORT
LAST_NAME
LONG_HORSE
LOGIN_URL
NEW_HOME_ADDRESS
POINT_A
B2_B

func IsJobExists Uses

func IsJobExists(err error) bool

IsJobExists returns true if error is of type ErrJobExists.

func NewSessionID Uses

func NewSessionID() string

NewSessionID returns a pseudo-random string based on the current UNIX time in nanoseconds.

type Alfred Uses

type Alfred struct {
    Env
}

Alfred wraps Alfred's AppleScript API, allowing you to open Alfred in various modes or call External Triggers.

a := NewAlfred()

// Open Alfred
if err := a.Search(""); err != nil {
	// handle error
}

// Browse /Applications
if err := a.Browse("/Applications"); err != nil {
	// handle error
}

func NewAlfred Uses

func NewAlfred(env ...Env) *Alfred

NewAlfred creates a new Alfred from the environment.

It accepts one optional Env argument. If an Env is passed, Alfred is initialised from that instead of the system environment.

func (*Alfred) Action Uses

func (a *Alfred) Action(path ...string) error

Action tells Alfred to show File Actions for path(s).

func (*Alfred) Browse Uses

func (a *Alfred) Browse(path string) error

Browse tells Alfred to open path in navigation mode.

func (*Alfred) RunTrigger Uses

func (a *Alfred) RunTrigger(name, query string, bundleID ...string) error

RunTrigger runs an External Trigger in the given workflow. Query may be empty.

It accepts one optional bundleID argument, which is the bundle ID of the workflow whose trigger should be run. If not specified, it defaults to the current workflow's.

func (*Alfred) Search Uses

func (a *Alfred) Search(query string) error

Search runs Alfred with the given query. Use an empty query to just open Alfred.

func (*Alfred) SetTheme Uses

func (a *Alfred) SetTheme(name string) error

SetTheme tells Alfred to use the specified theme.

type ArgVars Uses

type ArgVars struct {
    // contains filtered or unexported fields
}

ArgVars lets you set workflow variables from Run Script actions. It emits the arg and variables you set in the format required by Alfred.

Use ArgVars.Send() to pass variables to downstream workflow elements.

Code:

// Set workflow variables from Alfred's Run Script Action
av := NewArgVars()
av.Arg("baz")        // Set output (i.e. next action's {query}) to "baz"
av.Var("foo", "bar") // Set workflow variable "foo" to "bar"
av.Send()

Output:

{"alfredworkflow":{"arg":"baz","variables":{"foo":"bar"}}}

func NewArgVars Uses

func NewArgVars() *ArgVars

NewArgVars returns an initialised ArgVars object.

func (*ArgVars) Arg Uses

func (a *ArgVars) Arg(s string) *ArgVars

Arg sets the arg/query to be passed to the next workflow action.

func (*ArgVars) MarshalJSON Uses

func (a *ArgVars) MarshalJSON() ([]byte, error)

MarshalJSON serialises ArgVars to JSON. You probably don't need to call this: use ArgVars.String() instead.

func (*ArgVars) Send Uses

func (a *ArgVars) Send() error

Send outputs arg and variables to Alfred by printing a response to STDOUT.

func (*ArgVars) String Uses

func (a *ArgVars) String() (string, error)

String returns a string representation.

If any variables are set, JSON is returned. Otherwise, a plain string is returned.

func (*ArgVars) Var Uses

func (a *ArgVars) Var(k, v string) *ArgVars

Var sets the value of a workflow variable.

func (*ArgVars) Vars Uses

func (a *ArgVars) Vars() map[string]string

Vars returns ArgVars' variables.

type Cache Uses

type Cache struct {
    Dir string // Directory to save data in
}

Cache implements a simple store/load API, saving data to specified directory.

There are two APIs, one for storing/loading bytes and one for marshalling and storing/loading and unmarshalling JSON.

Each API has basic Store/Load functions plus a LoadOrStore function which loads cached data if these exist and aren't too old, or retrieves new data via the provided function, then caches and returns these.

The `name` parameter passed to Load*/Store* methods is used as the filename for on-disk cache, so make sure they're filesystem-safe, and consider adding an appropriate extension to the name, e.g. use "name.txt" (or "name.json" with LoadOrStoreJSON).

Code:

var (
    // Cache "key" (filename) and the value to store
    name  = "LastOpened"
    value = time.Now()
)

// Create a temporary directory for Cache to use
dir, err := ioutil.TempDir("", "awgo-demo")
if err != nil {
    panic(err)
}
defer os.RemoveAll(dir)

// Create a new cache
c := NewCache(dir)

// Cache doesn't exist yet
fmt.Println(c.Exists(name)) // -> false

// The API uses bytes
data, _ := value.MarshalText()

if err := c.Store(name, data); err != nil {
    panic(err)
}

// Cache now exists
fmt.Println(c.Exists(name)) // -> true

// Load data from cache
data, err = c.Load(name)
if err != nil {
    panic(err)
}

v2 := time.Time{}
v2.UnmarshalText(data)

// Values are equal
fmt.Println(value.Equal(v2)) // -> true

Output:

false
true
true

func NewCache Uses

func NewCache(dir string) *Cache

NewCache creates a new Cache using given directory. Directory is created if it doesn't exist. Panics if directory can't be created.

func (Cache) Age Uses

func (c Cache) Age(name string) (time.Duration, error)

Age returns the age of the data cached at name.

func (Cache) Exists Uses

func (c Cache) Exists(name string) bool

Exists returns true if the named cache exists.

func (Cache) Expired Uses

func (c Cache) Expired(name string, maxAge time.Duration) bool

Expired returns true if the named cache does not exist or is older than maxAge.

func (Cache) Load Uses

func (c Cache) Load(name string) ([]byte, error)

Load reads data saved under given name.

func (Cache) LoadJSON Uses

func (c Cache) LoadJSON(name string, v interface{}) error

LoadJSON unmarshals a cache into v.

func (Cache) LoadOrStore Uses

func (c Cache) LoadOrStore(name string, maxAge time.Duration, reload func() ([]byte, error)) ([]byte, error)

LoadOrStore loads data from cache if they exist and are newer than maxAge. If data do not exist or are older than maxAge, reload is called, and the returned data are cached & returned.

If maxAge is 0, any cached data are always returned.

LoadOrStore loads data from cache if they're fresh enough, otherwise it calls the reload function for new data (which it caches).

Code:

var (
    name        = "Expiring"
    data        = []byte("test")
    maxAge      = time.Millisecond * 1000
    start       = time.Now()
    reloadCount int
)

// Create a temporary directory for Cache to use
dir, err := ioutil.TempDir("", "awgo-demo")
if err != nil {
    panic(err)
}
defer os.RemoveAll(dir)

// Create a new cache
c := NewCache(dir)

// Called by LoadOrStore when cache is empty or has expired
reload := func() ([]byte, error) {

    // Log call count
    reloadCount++
    fmt.Printf("reload #%d\n", reloadCount)

    return data, nil
}

// Cache is empty
fmt.Println(c.Exists(name)) // -> false

out, err := c.LoadOrStore(name, maxAge, reload)
if err != nil {
    panic(err)
}

// Reload was called and cache exists
fmt.Println(c.Exists(name)) // -> true

// Value is the same
fmt.Println(string(out) == string(data)) // -> true

// Load again, this time from cache, not reload
out, err = c.LoadOrStore(name, maxAge, reload)
if err != nil {
    panic(err)
}

// Value is the same
fmt.Println(string(out) == string(data)) // -> true

// Wait for cache to expire, then try again
time.Sleep(time.Millisecond + maxAge - time.Now().Sub(start))

// reload is called again
out, err = c.LoadOrStore(name, maxAge, reload)
if err != nil {
    panic(err)
}

// Value is the same
fmt.Println(string(out) == string(data)) // -> true

Output:

false
reload #1
true
true
true
reload #2
true

func (Cache) LoadOrStoreJSON Uses

func (c Cache) LoadOrStoreJSON(name string, maxAge time.Duration, reload func() (interface{}, error), v interface{}) error

LoadOrStoreJSON loads JSON-serialised data from cache if they exist and are newer than maxAge. If the data do not exist or are older than maxAge, reload is called, and the returned data are marshalled to JSON and cached, and unmarshalled into v.

If maxAge is 0, any cached data are loaded regardless of age.

LoadOrStoreJSON marshals JSON to/from the cache.

Code:

var (
    name   = "Host"
    maxAge = time.Second * 5
)

// Create a temporary directory for Cache to use
dir, err := ioutil.TempDir("", "awgo-demo")
if err != nil {
    panic(err)
}
defer os.RemoveAll(dir)

// struct to cache
type host struct {
    Hostname string
    Port     int
}

// Called by LoadOrStoreJSON. Returns default host.
// Normally, this function would do something that takes some time, like
// fetch data from the web or an application.
reload := func() (interface{}, error) {

    fmt.Println("reload")

    return &host{
        Hostname: "localhost",
        Port:     6000,
    }, nil
}

// Create a new cache
c := NewCache(dir)

// Cache is empty
fmt.Println(c.Exists(name)) // -> false

// Populate new host from cache/reload
h := &host{}
if err := c.LoadOrStoreJSON(name, maxAge, reload, h); err != nil {
    panic(err)
}

fmt.Println(h.Hostname)
fmt.Println(h.Port)

Output:

false
reload
localhost
6000

func (Cache) Store Uses

func (c Cache) Store(name string, data []byte) error

Store saves data under the given name. If data is nil, the file is deleted.

func (Cache) StoreJSON Uses

func (c Cache) StoreJSON(name string, v interface{}) error

StoreJSON serialises v to JSON and saves it to the cache. If v is nil, the cache is deleted.

type Config Uses

type Config struct {
    Env
    // contains filtered or unexported fields
}

Config loads workflow settings from Alfred's environment variables.

The Get* methods read a variable from the environment, converting it to the desired type, and the Set() method saves a variable to info.plist.

NOTE: Because calling Alfred via AppleScript is very slow (~0.2s/call), Config users a "Doer" API for setting variables, whereby calls are collected and all executed at once when Config.Do() is called:

cfg := NewConfig()
if err := cfg.Set("key1", "value1").Set("key2", "value2").Do(); err != nil {
    // handle error
}

Finally, you can use Config.To() to populate a struct from environment variables, and Config.From() to read a struct's fields and save them to info.plist.

func NewConfig Uses

func NewConfig(env ...Env) *Config

NewConfig creates a new Config from the environment.

It accepts one optional Env argument. If an Env is passed, Config is initialised from that instead of the system environment.

func (*Config) Do Uses

func (cfg *Config) Do() error

Do calls Alfred and runs the accumulated actions.

If an error was encountered while preparing any commands, it will be returned here. It also returns an error if there are no commands to run, or if the call to Alfred fails.

Succeed or fail, any accumulated scripts and errors are cleared when Do() is called.

func (*Config) From Uses

func (cfg *Config) From(v interface{}) error

From saves the fields of (tagged) struct v to the workflow's settings in Alfred.

All supported and unignored fields are saved, although empty variables (i.e. "") are not overwritten with Go zero values, e.g. "0" or "false".

func (*Config) Get Uses

func (cfg *Config) Get(key string, fallback ...string) string

Get returns the value for envvar "key". It accepts one optional "fallback" argument. If no envvar is set, returns fallback or an empty string.

If a variable is set, but empty, its value is used.

Basic usage of Config.Get. Returns an empty string if variable is unset.

Code:

// Set some test variables
os.Setenv("TEST_NAME", "Bob Smith")
os.Setenv("TEST_ADDRESS", "7, Dreary Lane")

// New Config from environment
cfg := NewConfig()

fmt.Println(cfg.Get("TEST_NAME"))
fmt.Println(cfg.Get("TEST_ADDRESS"))
fmt.Println(cfg.Get("TEST_NONEXISTENT")) // unset variable

// GetString is a synonym
fmt.Println(cfg.GetString("TEST_NAME"))

Output:

Bob Smith
7, Dreary Lane

Bob Smith

The fallback value is returned if the variable is unset.

Code:

// Set some test variables
os.Setenv("TEST_NAME", "Bob Smith")
os.Setenv("TEST_ADDRESS", "7, Dreary Lane")
os.Setenv("TEST_EMAIL", "")

// New Config from environment
cfg := NewConfig()

fmt.Println(cfg.Get("TEST_NAME", "default name"))       // fallback ignored
fmt.Println(cfg.Get("TEST_ADDRESS", "default address")) // fallback ignored
fmt.Println(cfg.Get("TEST_EMAIL", "test@example.com"))  // fallback ignored (var is empty, not unset)
fmt.Println(cfg.Get("TEST_NONEXISTENT", "hi there!"))   // unset variable

Output:

Bob Smith
7, Dreary Lane

hi there!

func (*Config) GetBool Uses

func (cfg *Config) GetBool(key string, fallback ...bool) bool

GetBool returns the value for envvar "key" as a boolean. It accepts one optional "fallback" argument. If no envvar is set, returns fallback or false.

Values are parsed with strconv.ParseBool().

Strings are parsed using strconv.ParseBool().

Code:

// Set some test variables
os.Setenv("LIKE_PEAS", "t")
os.Setenv("LIKE_CARROTS", "true")
os.Setenv("LIKE_BEANS", "1")
os.Setenv("LIKE_LIVER", "f")
os.Setenv("LIKE_TOMATOES", "0")
os.Setenv("LIKE_BVB", "false")
os.Setenv("LIKE_BAYERN", "FALSE")

// New Config from environment
cfg := NewConfig()

// strconv.ParseBool() supports many formats
fmt.Println(cfg.GetBool("LIKE_PEAS"))
fmt.Println(cfg.GetBool("LIKE_CARROTS"))
fmt.Println(cfg.GetBool("LIKE_BEANS"))
fmt.Println(cfg.GetBool("LIKE_LIVER"))
fmt.Println(cfg.GetBool("LIKE_TOMATOES"))
fmt.Println(cfg.GetBool("LIKE_BVB"))
fmt.Println(cfg.GetBool("LIKE_BAYERN"))

// Fallback
fmt.Println(cfg.GetBool("LIKE_BEER", true))

Output:

true
true
true
false
false
false
false
true

func (*Config) GetDuration Uses

func (cfg *Config) GetDuration(key string, fallback ...time.Duration) time.Duration

GetDuration returns the value for envvar "key" as a time.Duration. It accepts one optional "fallback" argument. If no envvar is set, returns fallback or 0.

Values are parsed with time.ParseDuration().

Durations are parsed using time.ParseDuration.

Code:

// Set some test variables
os.Setenv("DURATION_NAP", "20m")
os.Setenv("DURATION_EGG", "5m")
os.Setenv("DURATION_BIG_EGG", "")
os.Setenv("DURATION_MATCH", "1.5h")

// New Config from environment
cfg := NewConfig()

// returns time.Duration
fmt.Println(cfg.GetDuration("DURATION_NAP"))
fmt.Println(cfg.GetDuration("DURATION_EGG") * 2)
// fallback with unset variable
fmt.Println(cfg.GetDuration("DURATION_POWERNAP", time.Minute*45))
// or an empty one
fmt.Println(cfg.GetDuration("DURATION_BIG_EGG", time.Minute*10))
fmt.Println(cfg.GetDuration("DURATION_MATCH").Minutes())

Output:

20m0s
10m0s
45m0s
10m0s
90

func (*Config) GetFloat Uses

func (cfg *Config) GetFloat(key string, fallback ...float64) float64

GetFloat returns the value for envvar "key" as a float. It accepts one optional "fallback" argument. If no envvar is set, returns fallback or 0.0.

Values are parsed with strconv.ParseFloat().

Strings are parsed to floats using strconv.ParseFloat().

Code:

// Set some test variables
os.Setenv("TOTAL_SCORE", "172.3")
os.Setenv("AVERAGE_SCORE", "7.54")

// New Config from environment
cfg := NewConfig()

fmt.Printf("%0.2f\n", cfg.GetFloat("TOTAL_SCORE"))
fmt.Printf("%0.1f\n", cfg.GetFloat("AVERAGE_SCORE"))
fmt.Println(cfg.GetFloat("NON_EXISTENT_SCORE", 120.5))

Output:

172.30
7.5
120.5

func (*Config) GetInt Uses

func (cfg *Config) GetInt(key string, fallback ...int) int

GetInt returns the value for envvar "key" as an int. It accepts one optional "fallback" argument. If no envvar is set, returns fallback or 0.

Values are parsed with strconv.ParseInt(). If strconv.ParseInt() fails, tries to parse the number with strconv.ParseFloat() and truncate it to an int.

Getting int values with and without fallbacks.

Code:

// Set some test variables
os.Setenv("PORT", "3000")
os.Setenv("PING_INTERVAL", "")

// New Config from environment
cfg := NewConfig()

fmt.Println(cfg.GetInt("PORT"))
fmt.Println(cfg.GetInt("PORT", 5000))        // fallback is ignored
fmt.Println(cfg.GetInt("PING_INTERVAL"))     // returns zero value
fmt.Println(cfg.GetInt("PING_INTERVAL", 60)) // returns fallback

Output:

3000
3000
0
60

func (*Config) GetString Uses

func (cfg *Config) GetString(key string, fallback ...string) string

GetString is a synonym for Get.

func (*Config) Set Uses

func (cfg *Config) Set(key, value string, export bool, bundleID ...string) *Config

Set saves a workflow variable to info.plist.

It accepts one optional bundleID argument, which is the bundle ID of the workflow whose configuration should be changed. If not specified, it defaults to the current workflow's.

func (*Config) To Uses

func (cfg *Config) To(v interface{}) error

To populates (tagged) struct v with values from the environment.

Populate a struct from workflow/environment variables. See EnvVarForField for information on how fields are mapped to environment variables if no variable name is specified using an `env:"name"` tag.

Code:

// Set some test values
os.Setenv("USERNAME", "dave")
os.Setenv("API_KEY", "hunter2")
os.Setenv("INTERVAL", "5m")
os.Setenv("FORCE", "1")

// Program settings to load from env
type Settings struct {
    Username       string
    APIKey         string
    UpdateInterval time.Duration `env:"INTERVAL"`
    Force          bool
}

var (
    s   = &Settings{}
    cfg = NewConfig()
)

// Populate Settings from workflow/environment variables
if err := cfg.To(s); err != nil {
    panic(err)
}

fmt.Println(s.Username)
fmt.Println(s.APIKey)
fmt.Println(s.UpdateInterval)
fmt.Println(s.Force)

Output:

dave
hunter2
5m0s
true

func (*Config) Unset Uses

func (cfg *Config) Unset(key string, bundleID ...string) *Config

Unset removes a workflow variable from info.plist.

It accepts one optional bundleID argument, which is the bundle ID of the workflow whose configuration should be changed. If not specified, it defaults to the current workflow's.

type Env Uses

type Env interface {
    // Lookup retrieves the value of the variable named by key.
    //
    // It follows the same semantics as os.LookupEnv(). If a variable
    // is unset, the boolean will be false. If a variable is set, the
    // boolean will be true, but the variable may still be an empty
    // string.
    Lookup(key string) (string, bool)
}

Env is the datasource for configuration lookups.

Pass a custom implementation to NewFromEnv() to provide a custom source for the required workflow configuration settings.

As an absolute minimum, the following variables must be set:

alfred_workflow_bundleid
alfred_workflow_cache
alfred_workflow_data

See EnvVar* consts for all variables set by Alfred.

type ErrJobExists Uses

type ErrJobExists struct {
    Name string // Name of the job
    Pid  int    // PID of the running job
}

ErrJobExists is the error returned by RunInBackground if a job with the given name is already running.

func (ErrJobExists) Error Uses

func (a ErrJobExists) Error() string

Error implements error interface.

type Feedback Uses

type Feedback struct {
    Items  []*Item // The results to be sent to Alfred.
    NoUIDs bool    // If true, suppress Item UIDs.
    // contains filtered or unexported fields
}

Feedback represents the results for an Alfred Script Filter.

Normally, you won't use this struct directly, but via the package-level functions/Workflow methods NewItem(), SendFeedback(), etc. It is important to use the constructor functions for Feedback, Item and Modifier structs so they are properly initialised and bound to their parent.

func NewFeedback Uses

func NewFeedback() *Feedback

NewFeedback creates a new, initialised Feedback struct.

func (*Feedback) Clear Uses

func (fb *Feedback) Clear()

Clear removes any items.

func (*Feedback) Filter Uses

func (fb *Feedback) Filter(query string, opts ...fuzzy.Option) []*fuzzy.Result

Filter fuzzy-sorts Items against query and deletes Items that don't match. It returns a slice of Result structs, which contain the results of the fuzzy sorting.

func (*Feedback) IsEmpty Uses

func (fb *Feedback) IsEmpty() bool

IsEmpty returns true if Feedback contains no items.

func (*Feedback) Keywords Uses

func (fb *Feedback) Keywords(i int) string

Keywords implements fuzzy.Sortable.

Returns the match or title field for Item i.

func (*Feedback) Len Uses

func (fb *Feedback) Len() int

Len implements sort.Interface.

func (*Feedback) Less Uses

func (fb *Feedback) Less(i, j int) bool

Less implements sort.Interface.

func (*Feedback) MarshalJSON Uses

func (fb *Feedback) MarshalJSON() ([]byte, error)

MarshalJSON serializes Feedback to Alfred 3's JSON format. You shouldn't need to call this: use Send() instead.

func (*Feedback) NewFileItem Uses

func (fb *Feedback) NewFileItem(path string) *Item

NewFileItem adds and returns a pointer to a new item pre-populated from path. Title and Autocomplete are the base name of the file; Subtitle is the path to the file (using "~" for $HOME); Valid is true; UID and Arg are set to path; Type is "file"; and Icon is the icon of the file at path.

func (*Feedback) NewItem Uses

func (fb *Feedback) NewItem(title string) *Item

NewItem adds a new Item and returns a pointer to it.

The Item inherits any workflow variables set on the Feedback parent at time of creation.

func (*Feedback) Rerun Uses

func (fb *Feedback) Rerun(secs float64) *Feedback

Rerun tells Alfred to re-run the Script Filter after `secs` seconds.

func (*Feedback) Send Uses

func (fb *Feedback) Send() error

Send generates JSON from this struct and sends it to Alfred (by writing the JSON to STDOUT).

You shouldn't need to call this directly: use SendFeedback() instead.

func (*Feedback) Sort Uses

func (fb *Feedback) Sort(query string, opts ...fuzzy.Option) []*fuzzy.Result

Sort sorts Items against query. Uses a fuzzy.Sorter with the specified options.

func (*Feedback) Swap Uses

func (fb *Feedback) Swap(i, j int)

Swap implements sort.Interface.

func (*Feedback) Var Uses

func (fb *Feedback) Var(k, v string) *Feedback

Var sets an Alfred variable for subsequent workflow elements.

func (*Feedback) Vars Uses

func (fb *Feedback) Vars() map[string]string

Vars returns the Feedback's workflow variables.

type Icon Uses

type Icon struct {
    Value string   `json:"path"`           // Path or UTI
    Type  IconType `json:"type,omitempty"` // "fileicon", "filetype" or ""
}

Icon represents the icon for an Item.

Alfred can show icons based on image files, UTIs (e.g. "public.folder") or can use the icon of a specific file (e.g. "/Applications/Safari.app" to use Safari's icon).

Type = "" (the default) will treat Value as the path to an image file. Alfred supports (at least) PNG, ICNS, JPG, GIF.

Type = IconTypeFileIcon will treat Value as the path to a file or directory and use that file's icon, e.g:

icon := &Icon{"/Applications/Mail.app", IconTypeFileIcon}

will display Mail.app's icon.

Type = IconTypeFileType will treat Value as a UTI, such as "public.movie" or "com.microsoft.word.doc". UTIs are useful when you don't have a local path to point to.

You can find out the UTI of a filetype by dragging one of the files to a File Filter's File Types list in Alfred, or in a shell with:

mdls -name kMDItemContentType -raw /path/to/the/file

This will only work on Spotlight-indexed files.

type IconType Uses

type IconType string

IconType specifies the type of an aw.Icon struct. It can be an image file, the icon of a file, e.g. an application's icon, or the icon for a UTI.

const (
    // Indicates that Icon.Value is the path to an image file that should
    // be used as the Item's icon.
    IconTypeImage IconType = ""
    // Icon.Value points to an object whose icon should be show in Alfred,
    //e.g. combine with "/Applications/Safari.app" to show Safari's icon.
    IconTypeFileIcon IconType = "fileicon"
    // Indicates that Icon.Value is a UTI, e.g. "public.folder",
    // which will give you the icon for a folder.
    IconTypeFileType IconType = "filetype"
)

Valid icon types.

type Item Uses

type Item struct {
    // contains filtered or unexported fields
}

Item is a single Alfred Script Filter result. Together with Feedback & Modifier, Item generates Script Filter feedback for Alfred.

Create Items via NewItem(), so they are bound to their parent Feedback.

func (*Item) Arg Uses

func (it *Item) Arg(s string) *Item

Arg sets Item's arg, the value passed as {query} to the next workflow action.

func (*Item) Autocomplete Uses

func (it *Item) Autocomplete(s string) *Item

Autocomplete sets what Alfred's query expands to when the user TABs result. (or hits RETURN on a result where valid is false)

func (*Item) Copytext Uses

func (it *Item) Copytext(s string) *Item

Copytext is what CMD+C should copy instead of Arg (the default).

func (*Item) Icon Uses

func (it *Item) Icon(icon *Icon) *Item

Icon sets the icon for the Item. Can point to an image file, a filepath of a file whose icon should be used, or a UTI.

See the documentation for Icon for more details.

func (*Item) IsFile Uses

func (it *Item) IsFile(b bool) *Item

IsFile tells Alfred that this Item is a file, i.e. Arg is a path and Alfred's File Actions should be made available.

func (*Item) Largetype Uses

func (it *Item) Largetype(s string) *Item

Largetype is what is shown in Alfred's Large Text window on CMD+L instead of Arg (the default).

func (*Item) MarshalJSON Uses

func (it *Item) MarshalJSON() ([]byte, error)

MarshalJSON serializes Item to Alfred 3's JSON format. You shouldn't need to call this directly: use SendFeedback() instead.

func (*Item) Match Uses

func (it *Item) Match(s string) *Item

Match sets Item's match field for filtering. If present, this field is preferred over the item's title for fuzzy sorting via Feedback, and by Alfred's "Alfred filters results" feature.

func (*Item) NewModifier Uses

func (it *Item) NewModifier(key ModKey) *Modifier

NewModifier returns an initialised Modifier bound to this Item. It also populates the Modifier with any workflow variables set in the Item.

func (*Item) Quicklook Uses

func (it *Item) Quicklook(s string) *Item

Quicklook is a path or URL shown in a macOS Quicklook window on SHIFT or CMD+Y.

func (*Item) SetModifier Uses

func (it *Item) SetModifier(m *Modifier) error

SetModifier sets a Modifier for a modifier key.

func (*Item) Subtitle Uses

func (it *Item) Subtitle(s string) *Item

Subtitle sets the subtitle of the item in Alfred's results.

func (*Item) Title Uses

func (it *Item) Title(s string) *Item

Title sets the title of the item in Alfred's results.

func (*Item) UID Uses

func (it *Item) UID(s string) *Item

UID sets Item's unique ID, which is used by Alfred to remember your choices. Use a blank string to force results to appear in the order you add them.

You can also use the SuppressUIDs() Option to (temporarily) suppress output of UIDs.

func (*Item) Valid Uses

func (it *Item) Valid(b bool) *Item

Valid tells Alfred whether the result is "actionable", i.e. ENTER will pass Arg to subsequent action.

func (*Item) Var Uses

func (it *Item) Var(k, v string) *Item

Var sets an Alfred variable for subsequent workflow elements.

func (*Item) Vars Uses

func (it *Item) Vars() map[string]string

Vars returns the Item's workflow variables.

type MagicAction Uses

type MagicAction interface {
    // Keyword is what the user must enter to run the action after
    // AwGo has recognised the magic prefix. So if the prefix is
    // "workflow:" (the default), a user must enter the query
    // "workflow:<keyword>" to execute this action.
    Keyword() string

    // Description is shown when a user has entered "magic" mode, but
    // the query does not yet match a keyword.
    Description() string

    // RunText is sent to Alfred and written to the log file &
    // debugger when the action is run.
    RunText() string

    // Run is called when the Magic Action is triggered.
    Run() error
}

MagicAction is a command that is called directly by AwGo (i.e. your workflow code is not run) if its keyword is passed in a user query.

To use Magic Actions, it's imperative that your workflow call Workflow.Args().

Calls to Workflow.Args() check the workflow's arguments (os.Args[1:]) for the magic prefix ("workflow:" by default), and hijack control of the workflow if found.

If an exact keyword match is found (e.g. "workflow:log"), the corresponding action is executed, and the workflow exits.

If no exact match is found, AwGo runs a Script Filter for the user to select an action. Hitting TAB or RETURN on an item will run it.

Magic Actions are mainly aimed at making debugging and supporting users easier (via the built-in actions), but they also provide a simple way to integrate your own commands that don't need a "real" UI.

For example, setting an Updater on Workflow adds an "update" command that checks for & installs a new version of the workflow.

Defaults

There are several built-in magic actions, which are registered by default:

<prefix>log         Open workflow's log file in the default app (usually
                    Console).
<prefix>data        Open workflow's data directory in the default app
                    (usually Finder).
<prefix>cache       Open workflow's data directory in the default app
                    (usually Finder).
<prefix>deldata     Delete everything in the workflow's data directory.
<prefix>delcache    Delete everything in the workflow's cache directory.
<prefix>reset       Delete everything in the workflow's data and cache directories.
<prefix>help        Open help URL in default browser.
                    Only registered if you have set a HelpURL.
<prefix>update      Check for updates and install a newer version of the
                    workflow if available.
                    Only registered if you have configured an Updater.

Custom Actions

To add custom MagicActions, you must register them with your Workflow *before* you call Workflow.Args()

To do this, configure Workflow with the AddMagic option.

type MagicActions Uses

type MagicActions struct {
    // contains filtered or unexported fields
}

MagicActions contains the registered magic actions. See the MagicAction interface for full documentation.

func (*MagicActions) Args Uses

func (ma *MagicActions) Args(args []string, prefix string) []string

Args runs a magic action or returns command-line arguments. It parses args for magic actions. If it finds one, it takes control of your workflow and runs the action. Control is not returned to your code.

If no magic actions are found, it returns args.

func (*MagicActions) Register Uses

func (ma *MagicActions) Register(actions ...MagicAction)

Register adds a MagicAction to the mapping. Previous entries are overwritten.

func (*MagicActions) Unregister Uses

func (ma *MagicActions) Unregister(actions ...MagicAction)

Unregister removes a MagicAction from the mapping (based on its keyword).

type MapEnv Uses

type MapEnv map[string]string

MapEnv is a testing helper that makes it simple to convert a map[string]string to an Env.

func (MapEnv) Lookup Uses

func (env MapEnv) Lookup(key string) (string, bool)

Lookup implements Env. It returns values from the map.

type ModKey Uses

type ModKey string

ModKey is a modifier key pressed by the user to run an alternate item action in Alfred (in combination with ↩).

It is passed to Item.NewModifier(). ModKeys cannot be combined: Alfred only permits one modifier at a time.

const (
    ModCmd   ModKey = "cmd"   // Alternate action for ⌘↩
    ModAlt   ModKey = "alt"   // Alternate action for ⌥↩
    ModOpt   ModKey = "alt"   // Synonym for ModAlt
    ModCtrl  ModKey = "ctrl"  // Alternate action for ^↩
    ModShift ModKey = "shift" // Alternate action for ⇧↩
    ModFn    ModKey = "fn"    // Alternate action for fn↩
)

Valid modifier keys used to specify alternate actions in Script Filters.

type Modifier Uses

type Modifier struct {
    // The modifier key. May be any of ValidModifiers.
    Key ModKey
    // contains filtered or unexported fields
}

Modifier encapsulates alterations to Item when a modifier key is held when the user actions the item.

Create new Modifiers via Item.NewModifier(). This binds the Modifier to the Item, initializes Modifier's map and inherits Item's workflow variables. Variables are inherited at creation time, so any Item variables you set after creating the Modifier are not inherited.

func (*Modifier) Arg Uses

func (m *Modifier) Arg(s string) *Modifier

Arg sets the arg for the Modifier.

func (*Modifier) Icon Uses

func (m *Modifier) Icon(i *Icon) *Modifier

Icon sets an icon for the Modifier.

func (*Modifier) MarshalJSON Uses

func (m *Modifier) MarshalJSON() ([]byte, error)

MarshalJSON serializes Item to Alfred 3's JSON format. You shouldn't need to call this directly: use SendFeedback() instead.

func (*Modifier) Subtitle Uses

func (m *Modifier) Subtitle(s string) *Modifier

Subtitle sets the subtitle for the Modifier.

func (*Modifier) Valid Uses

func (m *Modifier) Valid(v bool) *Modifier

Valid sets the valid status for the Modifier.

func (*Modifier) Var Uses

func (m *Modifier) Var(k, v string) *Modifier

Var sets a variable for the Modifier.

func (*Modifier) Vars Uses

func (m *Modifier) Vars() map[string]string

Vars returns all Modifier variables.

type Option Uses

type Option func(wf *Workflow) Option

Option is a configuration option for Workflow. Pass one or more Options to New() or Workflow.Configure().

An Option returns its inverse (i.e. an Option that restores the previous value).

You can apply Options at any time, so you can, e.g. suppress UIDs if you need to for items to be in a particular order.

func AddMagic Uses

func AddMagic(actions ...MagicAction) Option

AddMagic registers Magic Actions with the Workflow. Magic Actions connect special keywords/queries to callback functions. See the MagicAction interface for more information.

func HelpURL Uses

func HelpURL(URL string) Option

HelpURL sets link shown in debugger & log if Run() catches a panic ("Get help at http://…"). Set this to the URL of an issue tracker/forum thread where users can ask for help.

func LogPrefix Uses

func LogPrefix(prefix string) Option

LogPrefix is the printed to debugger at the start of each run. Its purpose is to ensure that the first real log message is shown on its own line. It is only sent to Alfred's debugger, not the log file.

Default: Beer Mug (\U0001F37A)

func MagicPrefix Uses

func MagicPrefix(prefix string) Option

MagicPrefix sets the prefix for "magic" commands. If a user enters this prefix, AwGo takes control of the workflow and shows a list of matching magic commands to the user.

Default: workflow:

func MaxLogSize Uses

func MaxLogSize(bytes int) Option

MaxLogSize sets the size (in bytes) when workflow log is rotated. Default: 1 MiB

func MaxResults Uses

func MaxResults(num int) Option

MaxResults is the maximum number of results to send to Alfred. 0 means send all results. Default: 0

func RemoveMagic Uses

func RemoveMagic(actions ...MagicAction) Option

RemoveMagic unregisters Magic Actions with Workflow. Magic Actions connect special keywords/queries to callback functions. See the MagicAction interface for more information.

func SessionName Uses

func SessionName(name string) Option

SessionName changes the name of the variable used to store the session ID.

This is useful if you have multiple Script Filters chained together that you don't want to use the same cache.

func SortOptions Uses

func SortOptions(opts ...fuzzy.Option) Option

SortOptions sets the fuzzy sorting options for Workflow.Filter(). See fuzzy and fuzzy.Option for info on (configuring) the sorting algorithm.

_examples/fuzzy contains an example workflow using fuzzy sort.

func SuppressUIDs Uses

func SuppressUIDs(on bool) Option

SuppressUIDs prevents UIDs from being set on feedback Items.

This turns off Alfred's knowledge, i.e. prevents Alfred from applying its own sort, so items will be shown in the order you add them.

Useful if you need to force a particular item to the top/bottom.

This setting only applies to Items created *after* it has been set.

func TextErrors Uses

func TextErrors(on bool) Option

TextErrors tells Workflow to print errors as text, not JSON. Messages are still sent to STDOUT. Set to true if error should be captured by Alfred, e.g. if output goes to a Notification.

func Update Uses

func Update(updater Updater) Option

Update sets the updater for the Workflow. Panics if a version number isn't set (in Alfred Preferences).

See Updater interface and subpackage update for more documentation.

type Session Uses

type Session struct {
    SessionID string
    // contains filtered or unexported fields
}

Session is a Cache that is tied to the `sessionID` value passed to NewSession().

All cached data are stored under the sessionID. NewSessionID() creates a pseudo-random string based on the current UNIX time (in nanoseconds). The Workflow struct persists this value as a session ID as long as the user is using the current workflow via the `AW_SESSION_ID` top-level workflow variable.

As soon as Alfred closes or the user calls another workflow, this variable is lost and the data are "hidden". Session.Clear(false) must be called to actually remove the data from the cache directory, which Workflow.Run() does.

In contrast to the Cache API, Session methods lack an explicit `maxAge` parameter. It is always `0`, i.e. cached data are always loaded regardless of age as long as the session is valid.

TODO: Embed Cache rather than wrapping it.

func NewSession Uses

func NewSession(dir, sessionID string) *Session

NewSession creates and initialises a Session.

func (Session) Clear Uses

func (s Session) Clear(current bool) error

Clear removes session-scoped cache data. If current is true, it also removes data cached for the current session.

func (Session) Exists Uses

func (s Session) Exists(name string) bool

Exists returns true if the named cache exists.

func (Session) Load Uses

func (s Session) Load(name string) ([]byte, error)

Load reads data saved under given name.

func (Session) LoadJSON Uses

func (s Session) LoadJSON(name string, v interface{}) error

LoadJSON unmarshals a cache into v.

func (Session) LoadOrStore Uses

func (s Session) LoadOrStore(name string, reload func() ([]byte, error)) ([]byte, error)

LoadOrStore loads data from cache if they exist. If data do not exist, reload is called, and the resulting data are cached & returned.

func (Session) LoadOrStoreJSON Uses

func (s Session) LoadOrStoreJSON(name string, reload func() (interface{}, error), v interface{}) error

LoadOrStoreJSON loads JSON-serialised data from cache if they exist. If the data do not exist, reload is called, and the resulting interface{} is cached and returned.

func (Session) Store Uses

func (s Session) Store(name string, data []byte) error

Store saves data under the given name. If len(data) is 0, the file is deleted.

func (Session) StoreJSON Uses

func (s Session) StoreJSON(name string, v interface{}) error

StoreJSON serialises v to JSON and saves it to the cache. If v is nil, the cache is deleted.

type Updater Uses

type Updater interface {
    UpdateInterval(time.Duration) // Set interval between checks
    UpdateAvailable() bool        // Return true if a newer version is available
    CheckDue() bool               // Return true if a check for a newer version is due
    CheckForUpdate() error        // Retrieve available releases, e.g. from a URL
    Install() error               // Install the latest version
}

Updater can check for and download & install newer versions of the workflow. There is a concrete implementation and documentation in subpackage "update".

type Workflow Uses

type Workflow struct {
    sync.WaitGroup
    // Interface to workflow's settings.
    // Reads workflow variables by type and saves new values to info.plist.
    Config *Config

    // Call Alfred's AppleScript functions.
    Alfred *Alfred

    // Cache is a Cache pointing to the workflow's cache directory.
    Cache *Cache
    // Data is a Cache pointing to the workflow's data directory.
    Data *Cache
    // Session is a cache that stores session-scoped data. These data
    // persist until the user closes Alfred or runs a different workflow.
    Session *Session

    // The response that will be sent to Alfred. Workflow provides
    // convenience wrapper methods, so you don't normally have to
    // interact with this directly.
    Feedback *Feedback

    // Updater fetches updates for the workflow.
    Updater Updater

    // MagicActions contains the magic actions registered for this workflow.
    // It is set to DefaultMagicActions by default.
    MagicActions *MagicActions
    // contains filtered or unexported fields
}

Workflow provides a consolidated API for building Script Filters.

As a rule, you should create a Workflow in init or main and call your main entry-point via Workflow.Run(), which catches panics, and logs & shows the error in Alfred.

Script Filter

To generate feedback for a Script Filter, use Workflow.NewItem() to create new Items and Workflow.SendFeedback() to send the results to Alfred.

Run Script

Use the TextErrors option, so any rescued panics are printed as text, not as JSON.

Use ArgVars to set workflow variables, not Workflow/Feedback.

See the _examples/ subdirectory for some full examples of workflows.

func New Uses

func New(opts ...Option) *Workflow

New creates and initialises a new Workflow, passing any Options to Workflow.Configure().

For available options, see the documentation for the Option type and the following functions.

IMPORTANT: In order to be able to initialise the Workflow correctly, New must be run within a valid Alfred environment; specifically *at least* the following environment variables must be set:

alfred_workflow_bundleid
alfred_workflow_cache
alfred_workflow_data

If you aren't running from Alfred, or would like to specify a custom environment, use NewFromEnv().

New initialises a Workflow with the default settings. Name, bundle ID, version etc. are read from the environment variables set by Alfred.

Code:

wf := New()
// Name is read from environment
fmt.Println(wf.Name())
// BundleID is read from environment
fmt.Println(wf.BundleID())
// Version is from info.plist
fmt.Println(wf.Version())

Output:

AwGo
net.deanishe.awgo
0.14

Pass one or more Options to New() to configure the created Workflow.

Code:

wf := New(HelpURL("http://www.example.com"), MaxResults(200))
fmt.Println(wf.helpURL)
fmt.Println(wf.maxResults)

Output:

http://www.example.com
200

func NewFromEnv Uses

func NewFromEnv(env Env, opts ...Option) *Workflow

NewFromEnv creates a new Workflows from a custom Env, instead of reading its configuration from Alfred's environment variables.

func (*Workflow) Args Uses

func (wf *Workflow) Args() []string

Args returns command-line arguments passed to the program. It intercepts "magic args" and runs the corresponding actions, terminating the workflow. See MagicAction for full documentation.

func (*Workflow) BundleID Uses

func (wf *Workflow) BundleID() string

BundleID returns the workflow's bundle ID. This library will not work without a bundle ID, which is set in the workflow's main setup sheet in Alfred Preferences.

func (*Workflow) CacheDir Uses

func (wf *Workflow) CacheDir() string

CacheDir returns the path to the workflow's cache directory.

func (*Workflow) CheckForUpdate Uses

func (wf *Workflow) CheckForUpdate() error

CheckForUpdate retrieves and caches the list of available releases.

func (*Workflow) ClearCache Uses

func (wf *Workflow) ClearCache() error

ClearCache deletes all files from the workflow's cache directory.

func (*Workflow) ClearData Uses

func (wf *Workflow) ClearData() error

ClearData deletes all files from the workflow's data directory.

func (*Workflow) Configure Uses

func (wf *Workflow) Configure(opts ...Option) (previous Option)

Configure applies one or more Options to Workflow. The returned Option reverts all Options passed to Configure.

Change Workflow's configuration after creation, then revert it.

Code:

wf := New()
// Default settings (false and 0)
fmt.Println(wf.textErrors)
fmt.Println(wf.maxResults)
// Turn text errors on, set max results and save Option to revert
// to previous configuration
previous := wf.Configure(TextErrors(true), MaxResults(200))
fmt.Println(wf.textErrors)
fmt.Println(wf.maxResults)
// Revert to previous configuration
wf.Configure(previous)
fmt.Println(wf.textErrors)
fmt.Println(wf.maxResults)

Output:

false
0
true
200
false
0

func (*Workflow) DataDir Uses

func (wf *Workflow) DataDir() string

DataDir returns the path to the workflow's data directory.

func (*Workflow) Debug Uses

func (wf *Workflow) Debug() bool

Debug returns true if Alfred's debugger is open.

func (*Workflow) Dir Uses

func (wf *Workflow) Dir() string

Dir returns the path to the workflow's root directory.

func (*Workflow) Fatal Uses

func (wf *Workflow) Fatal(msg string)

Fatal displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.

func (*Workflow) FatalError Uses

func (wf *Workflow) FatalError(err error)

FatalError displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.

func (*Workflow) Fatalf Uses

func (wf *Workflow) Fatalf(format string, args ...interface{})

Fatalf displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.

func (*Workflow) Filter Uses

func (wf *Workflow) Filter(query string) []*fuzzy.Result

Filter fuzzy-sorts feedback Items against query and deletes Items that don't match.

func (*Workflow) InstallUpdate Uses

func (wf *Workflow) InstallUpdate() error

InstallUpdate downloads and installs the latest version of the workflow.

func (*Workflow) IsEmpty Uses

func (wf *Workflow) IsEmpty() bool

IsEmpty returns true if Workflow contains no items.

func (*Workflow) IsRunning Uses

func (wf *Workflow) IsRunning(jobName string) bool

IsRunning returns true if a job with name jobName is currently running.

func (*Workflow) Kill Uses

func (wf *Workflow) Kill(jobName string) error

Kill stops a background job.

func (*Workflow) LogFile Uses

func (wf *Workflow) LogFile() string

LogFile returns the path to the workflow's log file.

func (*Workflow) Name Uses

func (wf *Workflow) Name() string

Name returns the workflow's name as specified in the workflow's main setup sheet in Alfred Preferences.

func (*Workflow) NewFileItem Uses

func (wf *Workflow) NewFileItem(path string) *Item

NewFileItem adds and returns a new feedback Item pre-populated from path. See Feedback.NewFileItem() for more information.

func (*Workflow) NewItem Uses

func (wf *Workflow) NewItem(title string) *Item

NewItem adds and returns a new feedback Item. See Feedback.NewItem() for more information.

The normal way to create a new Item, but not the normal way to use it.

Typically, when you're done adding Items, you call SendFeedback() to send the results to Alfred.

Code:

wf := New()
// Create a new item via the Workflow object, which will
// track the Item and send it to Alfred when you call
// Workflow.SendFeedback()
//
// Title is the only required value.
it := wf.NewItem("First Result").
    Subtitle("Some details here")

// Just to see what it looks like...
data, _ := json.Marshal(it)
fmt.Println(string(data))

Output:

{"title":"First Result","subtitle":"Some details here","valid":false}

func (*Workflow) NewWarningItem Uses

func (wf *Workflow) NewWarningItem(title, subtitle string) *Item

NewWarningItem adds and returns a new Feedback Item with the system warning icon (exclamation mark on yellow triangle).

func (*Workflow) OpenCache Uses

func (wf *Workflow) OpenCache() error

OpenCache opens the workflow's cache directory in the default application (usually Finder).

func (*Workflow) OpenData Uses

func (wf *Workflow) OpenData() error

OpenData opens the workflow's data directory in the default application (usually Finder).

func (*Workflow) OpenHelp Uses

func (wf *Workflow) OpenHelp() error

OpenHelp opens the workflow's help URL (if set) in the default browser.

func (*Workflow) OpenLog Uses

func (wf *Workflow) OpenLog() error

OpenLog opens the workflow's logfile in the default application (usually Console.app).

func (*Workflow) Rerun Uses

func (wf *Workflow) Rerun(secs float64) *Workflow

Rerun tells Alfred to re-run the Script Filter after `secs` seconds.

func (*Workflow) Reset Uses

func (wf *Workflow) Reset() error

Reset deletes all workflow data (cache and data directories).

func (*Workflow) Run Uses

func (wf *Workflow) Run(fn func())

Run runs your workflow function, catching any errors. If the workflow panics, Run rescues and displays an error message in Alfred.

func (*Workflow) RunInBackground Uses

func (wf *Workflow) RunInBackground(jobName string, cmd *exec.Cmd) error

RunInBackground executes cmd in the background. It returns an ErrJobExists error if a job of the same name is already running.

func (*Workflow) SendFeedback Uses

func (wf *Workflow) SendFeedback() *Workflow

SendFeedback sends Script Filter results to Alfred.

Results are output as JSON to STDOUT. As you can output results only once, subsequent calls to sending methods are logged and ignored.

The sending methods are:

SendFeedback()
Fatal()
Fatalf()
FatalError()
Warn()
WarnEmpty()  // only sends if there are no items

func (*Workflow) SessionID Uses

func (wf *Workflow) SessionID() string

SessionID returns the session ID for this run of the workflow. This is used internally for session-scoped caching.

The session ID is persisted as a workflow variable. It and the session persist as long as the user is using the workflow in Alfred. That means that the session expires as soon as Alfred closes or the user runs a different workflow.

func (*Workflow) UpdateAvailable Uses

func (wf *Workflow) UpdateAvailable() bool

UpdateAvailable returns true if a newer version is available to install.

func (*Workflow) UpdateCheckDue Uses

func (wf *Workflow) UpdateCheckDue() bool

UpdateCheckDue returns true if an update is available.

func (*Workflow) Var Uses

func (wf *Workflow) Var(k, v string) *Workflow

Var sets the value of workflow variable k on Workflow.Feedback to v. See Feedback.Var() for more information.

func (*Workflow) Vars Uses

func (wf *Workflow) Vars() map[string]string

Vars returns the workflow variables set on Workflow.Feedback. See Feedback.Vars() for more information.

func (*Workflow) Version Uses

func (wf *Workflow) Version() string

Version returns the workflow's version set in the workflow's configuration sheet in Alfred Preferences.

func (*Workflow) Warn Uses

func (wf *Workflow) Warn(title, subtitle string) *Workflow

Warn displays a warning message in Alfred immediately. Unlike FatalError()/Fatal(), this does not terminate the workflow, but you can't send any more results to Alfred.

func (*Workflow) WarnEmpty Uses

func (wf *Workflow) WarnEmpty(title, subtitle string)

WarnEmpty adds a warning item to feedback if there are no other items.

Directories

PathSynopsis
_examplesPackage examples contains trivial, but complete, Alfred workflows demonstrating features of AwGo and/or useful workflow idioms.
_examples/bookmarksWorkflow bookmarks demonstrates implementing fuzzy.Sortable.
_examples/fuzzyWorkflow fuzzy demonstrates AwGo's fuzzy filtering.
_examples/settingsWorkflow settings demonstrates binding a struct to Alfred's settings.
_examples/updateWorkflow update is an example of how to use AwGo's update API.
_examples/workflowsWorkflow workflows retrieves and filters GitHub repos tagged with "alfred-workflow".
fuzzyPackage fuzzy implements fuzzy sorting and filtering.
updatePackage update implements an API for fetching updates to workflows from remote servers.
utilPackage util contains general helper functions for workflow (library) authors.

Package aw imports 20 packages (graph) and is imported by 24 packages. Updated 2018-09-30. Refresh now. Tools for package owners.