Documentation ¶
Overview ¶
Package aw is a "plug-and-play" workflow development library/framework for Alfred 3 & 4 (https://www.alfredapp.com/). It requires Go 1.13 or later.
It provides everything you need to create a polished and blazing-fast Alfred frontend for your project.
Features ¶
As of AwGo 0.26, all applicable features of Alfred 4.1 are supported.
The main features are:
- Full support for Alfred 3 & 4
- Bi-directional interface to workflow's configuration
- Fluent API for generating Script Filter JSON
- Fuzzy filtering
- Simple, powerful API for caching/saving workflow data
- Keychain API to securely store (and sync) sensitive data
- API to call Alfred's AppleScript methods from Go code
- Helpers to easily run scripts and script code
- Workflow update API with built-in support for GitHub & Gitea
- Pre-configured logging for easier debugging, with a rotating 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 ¶
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:
// Absolutely required. No ifs or buts. alfred_workflow_bundleid // Cache & data dirs can be set to anything, but for best // results, point them at the same directories as Alfred uses // Alfred 3: ~/Library/Caches/com.runningwithcrayons.Alfred-3/Workflow Data/<bundle ID>/ // Alfred 4+: ~/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/<bundle ID>/ alfred_workflow_cache // Alfred 3: ~/Library/Application Support/Alfred 3/Workflow Data/<bundle ID>/ // Alfred 4+: ~/Library/Application Support/Alfred/Workflow Data/<bundle ID>/ alfred_workflow_data // If you're using the Updater API, a semantic-ish workflow version // must be set otherwise the Updater will panic alfred_workflow_version // If you're using the Alfred API and running Alfred 3, you need to // set `alfred_version` as AwGo defaults to calling Alfred 4+ alfred_version=3
NOTE: AwGo is currently in development. The API *will* change and should not be considered stable until v1.0. Until then, be sure to pin a version using go modules or similar.
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.
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/ChicK00o/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(aw.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.
See the documentation for Option for more information on configuring a Workflow.
Updates ¶
AwGo can check for and install new versions of your workflow. Subpackage update provides an implementation of the Updater interface and sources to load updates from GitHub or Gitea releases, or from the URL of an Alfred `metadata.json` file.
See subpackage update and _examples/update.
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.
See _examples/fuzzy for a basic demonstration, and _examples/bookmarks for a demonstration of implementing fuzzy.Sortable on your own structs and customising the fuzzy sort settings.
Fuzzy matching is done by package https://godoc.org/go.deanishe.net/fuzzy
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 (see 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/info.plist 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 Options from the corresponding environment variables. if err := cfg.To(opts); err != nil { // handle error } // Save Options back to Alfred/info.plist. 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, to browse/action files & directories, or to run External Triggers.
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 (almost) 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 ¶
- Constants
- Variables
- func IsJobExists(err error) bool
- func Marshal(v interface{}) ([]byte, error)
- func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
- func NewSessionID() string
- type Alfred
- func (a *Alfred) Action(value ...string) error
- func (a *Alfred) ActionAsType(typ string, value ...string) error
- func (a *Alfred) Browse(path string) error
- func (a *Alfred) ReloadWorkflow(bundleID ...string) error
- func (a *Alfred) RunTrigger(name, query string, bundleID ...string) error
- func (a *Alfred) Search(query string) error
- func (a *Alfred) SetTheme(name string) error
- type ArgVars
- type Cache
- func (c Cache) Age(name string) (time.Duration, error)
- func (c Cache) Exists(name string) bool
- func (c Cache) Expired(name string, maxAge time.Duration) bool
- func (c Cache) Load(name string) ([]byte, error)
- func (c Cache) LoadJSON(name string, v interface{}) error
- func (c Cache) LoadOrStore(name string, maxAge time.Duration, reload func() ([]byte, error)) ([]byte, error)
- func (c Cache) LoadOrStoreJSON(name string, maxAge time.Duration, reload func() (interface{}, error), ...) error
- func (c Cache) Store(name string, data []byte) error
- func (c Cache) StoreJSON(name string, v interface{}) error
- type Config
- func (cfg *Config) Do() error
- func (cfg *Config) From(v interface{}, opt ...env.DumpOption) error
- func (cfg *Config) Get(key string, fallback ...string) string
- func (cfg *Config) GetBool(key string, fallback ...bool) bool
- func (cfg *Config) GetDuration(key string, fallback ...time.Duration) time.Duration
- func (cfg *Config) GetFloat(key string, fallback ...float64) float64
- func (cfg *Config) GetInt(key string, fallback ...int) int
- func (cfg *Config) GetString(key string, fallback ...string) string
- func (cfg *Config) Set(key, value string, export bool, bundleID ...string) *Config
- func (cfg *Config) To(v interface{}) error
- func (cfg *Config) Unset(key string, bundleID ...string) *Config
- type Env
- type ErrJobExists
- type Feedback
- func (fb *Feedback) Clear()
- func (fb *Feedback) Filter(query string, opts ...fuzzy.Option) []*fuzzy.Result
- func (fb *Feedback) IsEmpty() bool
- func (fb *Feedback) Keywords(i int) string
- func (fb *Feedback) Len() int
- func (fb *Feedback) Less(i, j int) bool
- func (fb *Feedback) MarshalJSON() ([]byte, error)
- func (fb *Feedback) NewItem(title string) *Item
- func (fb *Feedback) Rerun(secs float64) *Feedback
- func (fb *Feedback) Send() error
- func (fb *Feedback) Sort(query string, opts ...fuzzy.Option) []*fuzzy.Result
- func (fb *Feedback) Swap(i, j int)
- func (fb *Feedback) Var(k, v string) *Feedback
- func (fb *Feedback) Vars() map[string]string
- type Icon
- type IconType
- type Item
- func (it *Item) Action(value ...string) *Item
- func (it *Item) ActionForType(typ string, value ...string) *Item
- func (it *Item) Alt() *Modifier
- func (it *Item) Arg(s ...string) *Item
- func (it *Item) Autocomplete(s string) *Item
- func (it *Item) Cmd() *Modifier
- func (it *Item) Copytext(s string) *Item
- func (it *Item) Ctrl() *Modifier
- func (it *Item) Fn() *Modifier
- func (it *Item) Icon(icon *Icon) *Item
- func (it *Item) IsFile(b bool) *Item
- func (it *Item) Largetype(s string) *Item
- func (it *Item) MarshalJSON() ([]byte, error)
- func (it *Item) Match(s string) *Item
- func (it *Item) NewModifier(key ...string) *Modifier
- func (it *Item) Opt() *Modifier
- func (it *Item) Quicklook(s string) *Item
- func (it *Item) SetModifier(m *Modifier)
- func (it *Item) Shift() *Modifier
- func (it *Item) Subtitle(s string) *Item
- func (it *Item) Title(s string) *Item
- func (it *Item) UID(s string) *Item
- func (it *Item) Valid(b bool) *Item
- func (it *Item) Var(k, v string) *Item
- func (it *Item) Vars() map[string]string
- type MagicAction
- type Modifier
- func (m *Modifier) Arg(s ...string) *Modifier
- func (m *Modifier) Icon(i *Icon) *Modifier
- func (m *Modifier) MarshalJSON() ([]byte, error)
- func (m *Modifier) Subtitle(s string) *Modifier
- func (m *Modifier) Valid(v bool) *Modifier
- func (m *Modifier) Var(k, v string) *Modifier
- func (m *Modifier) Vars() map[string]string
- type Option
- func AddMagic(actions ...MagicAction) Option
- func HelpURL(url string) Option
- func LogPrefix(prefix string) Option
- func MagicPrefix(prefix string) Option
- func MaxLogSize(bytes int) Option
- func MaxResults(num int) Option
- func RemoveMagic(actions ...MagicAction) Option
- func SessionName(name string) Option
- func SortOptions(opts ...fuzzy.Option) Option
- func SuppressUIDs(on bool) Option
- func TextErrors(on bool) Option
- func Update(updater Updater) Option
- type Session
- func (s Session) Clear(current bool) error
- func (s Session) Exists(name string) bool
- func (s Session) Load(name string) ([]byte, error)
- func (s Session) LoadJSON(name string, v interface{}) error
- func (s Session) LoadOrStore(name string, reload func() ([]byte, error)) ([]byte, error)
- func (s Session) LoadOrStoreJSON(name string, reload func() (interface{}, error), v interface{}) error
- func (s Session) Store(name string, data []byte) error
- func (s Session) StoreJSON(name string, v interface{}) error
- type Updater
- type Workflow
- func (wf *Workflow) Args() []string
- func (wf *Workflow) BundleID() string
- func (wf *Workflow) CacheDir() string
- func (wf *Workflow) CheckForUpdate() error
- func (wf *Workflow) ClearCache() error
- func (wf *Workflow) ClearData() error
- func (wf *Workflow) Configure(opts ...Option) (previous Option)
- func (wf *Workflow) DataDir() string
- func (wf *Workflow) Debug() bool
- func (wf *Workflow) Dir() string
- func (wf *Workflow) Fatal(msg string)
- func (wf *Workflow) FatalError(err error)
- func (wf *Workflow) Fatalf(format string, args ...interface{})
- func (wf *Workflow) Filter(query string) []*fuzzy.Result
- func (wf *Workflow) InstallUpdate() error
- func (wf *Workflow) IsEmpty() bool
- func (wf *Workflow) IsRunning(jobName string) bool
- func (wf *Workflow) Kill(jobName string) error
- func (wf *Workflow) LogFile() string
- func (wf *Workflow) Name() string
- func (wf *Workflow) NewFileItem(path string) *Item
- func (wf *Workflow) NewItem(title string) *Item
- func (wf *Workflow) NewWarningItem(title, subtitle string) *Item
- func (wf *Workflow) OpenCache() error
- func (wf *Workflow) OpenData() error
- func (wf *Workflow) OpenHelp() error
- func (wf *Workflow) OpenLog() error
- func (wf *Workflow) Rerun(secs float64) *Workflow
- func (wf *Workflow) Reset() error
- func (wf *Workflow) Run(fn func())
- func (wf *Workflow) RunInBackground(jobName string, cmd *exec.Cmd) error
- func (wf *Workflow) SendFeedback() *Workflow
- func (wf *Workflow) SessionID() string
- func (wf *Workflow) UpdateAvailable() bool
- func (wf *Workflow) UpdateCheckDue() bool
- func (wf *Workflow) Var(k, v string) *Workflow
- func (wf *Workflow) Vars() map[string]string
- func (wf *Workflow) Version() string
- func (wf *Workflow) Warn(title, subtitle string) *Workflow
- func (wf *Workflow) WarnEmpty(title, subtitle string)
Examples ¶
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 Config:
// Returns a string Config.Get(EnvVarName) // Parse string into a bool Config.GetBool(EnvVarDebug)
const ( ModCmd string = "cmd" // Alternate action for ⌘↩ ModAlt string = "alt" // Alternate action for ⌥↩ ModOpt string = "alt" // Synonym for ModAlt ModCtrl string = "ctrl" // Alternate action for ^↩ ModShift string = "shift" // Alternate action for ⇧↩ ModFn string = "fn" // Alternate action for fn↩ )
Valid modifier keys pressed by the user to run an alternate item action in Script Filters (in combination with ↩). Passed to Item.NewModifier().
Alfred 3 only permits one modifier at a time, but in Alfred 4+ you can combine them arbitrarily.
const ( TypeFile = "file" // values are paths TypeURL = "url" // values are URLs TypeText = "text" // values are just text )
Types understood by Alfred's `action` API call and item field. Added in Alfred 4.5.
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.27.1"
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 + "AlertCautionBadgeIcon.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
Functions ¶
func IsJobExists ¶
IsJobExists returns true if error is of type or wraps ErrJobExists.
func MarshalIndent ¶
func NewSessionID ¶
func NewSessionID() string
NewSessionID returns a pseudo-random string based on the current UNIX time in nanoseconds.
Types ¶
type Alfred ¶
type Alfred struct { Env // contains filtered or unexported fields }
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 ¶
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 ¶
Action tells Alfred to show Universal Actions for value(s). This calls Alfred.ActionAsType with an empty type.
func (*Alfred) ActionAsType ¶
ActionAsType tells Alfred to show Universal Actions for value(s). Type typ may be one of "file", "url" or "text", or an empty string to tell Alfred to guess the type.
Added in Alfred 4.5
func (*Alfred) ReloadWorkflow ¶
ReloadWorkflow tells Alfred to reload a workflow from disk.
It accepts one optional bundleID argument, which is the bundle ID of the workflow to reload. If not specified, it defaults to the current workflow's.
func (*Alfred) RunTrigger ¶
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.
type ArgVars ¶
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.
Example ¶
// 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" if err := av.Send(); err != nil { panic(err) }
Output: {"alfredworkflow":{"arg":"baz","variables":{"foo":"bar"}}}
func (*ArgVars) Arg ¶
Arg sets the arg(s)/query to be passed to the next workflow action. Multiple values are allowed in Alfred 4.1 and later.
func (*ArgVars) MarshalJSON ¶
MarshalJSON serialises ArgVars to JSON. You probably don't need to call this: use ArgVars.Send() instead.
func (*ArgVars) String ¶
String returns a string representation.
If any variables are set, JSON is returned. Otherwise, a plain string is returned.
type Cache ¶
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 the on-disk cache, so make sure it's filesystem-safe, and consider adding an appropriate extension to the name, e.g. use "name.txt" (or "name.json" with LoadOrStoreJSON).
Example ¶
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 ¶
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) Expired ¶
Expired returns true if the named cache does not exist or is older than maxAge.
func (Cache) LoadOrStore ¶
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, the reload function is called, and the returned data are saved to the cache and also returned.
If maxAge is 0, any cached data are always returned.
Example ¶
LoadOrStore loads data from cache if they're fresh enough, otherwise it calls the reload function for new data (which it caches).
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.Since(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 ¶
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, the reload function is called, and the data it returns are marshalled to JSON & cached, and also unmarshalled into v.
If maxAge is 0, any cached data are loaded regardless of age.
Example ¶
LoadOrStoreJSON marshals JSON to/from the cache.
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
type Config ¶
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 ¶
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 ¶
Do calls Alfred and runs the accumulated actions.
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 ¶
func (cfg *Config) From(v interface{}, opt ...env.DumpOption) error
From saves the fields of (tagged) struct v to the workflow's settings in Alfred. All supported and unignored fields are saved by default. The behaviour can be customised by passing in options from deanishe/go-env, such as env.IgnoreZeroValues to omit any fields set to zero values.
func (*Config) Get ¶
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.
Example ¶
Basic usage of Config.Get. Returns an empty string if variable is unset.
// 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
Example (Fallback) ¶
The fallback value is returned if the variable is unset.
// 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 ¶
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().
Example ¶
Strings are parsed using strconv.ParseBool().
// 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 ¶
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().
Example ¶
Durations are parsed using time.ParseDuration.
// 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 ¶
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().
Example ¶
Strings are parsed to floats using strconv.ParseFloat().
// 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 ¶
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.
Example ¶
Getting int values with and without fallbacks.
// 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) Set ¶
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 ¶
To populates (tagged) struct v with values from the environment.
Example ¶
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.
// 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
type Env ¶
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 data source 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 ¶
ErrJobExists is the error returned by RunInBackground if a job with the given name is already running.
func (ErrJobExists) Error ¶
func (err ErrJobExists) Error() string
Error implements error interface.
func (ErrJobExists) Is ¶
func (err ErrJobExists) Is(target error) bool
Is returns true if target is of type ErrJobExists.
type Feedback ¶
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 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 ¶
func NewFeedback() *Feedback
NewFeedback creates a new, initialised Feedback struct.
func (*Feedback) Filter ¶
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) Keywords ¶
Keywords implements fuzzy.Sortable.
Returns the match or title field for Item i.
func (*Feedback) MarshalJSON ¶
MarshalJSON serializes Feedback to Alfred's JSON format. You shouldn't need to call this: use Send() instead.
func (*Feedback) NewItem ¶
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) Send ¶
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 ¶
Sort sorts Items against query. Uses a fuzzy.Sorter with the specified options.
type Icon ¶
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 := &aw.Icon{"/Applications/Mail.app", aw.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 ¶
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 = "" // Indicates that 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 ¶
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) Action ¶
Action sets the value(s) to be passed to Alfred's Universal Actions if the user actions this item. Alfred will auto-detect the type of the value(s).
Added in Alfred 4.5.
func (*Item) ActionForType ¶
ActionForType sets the value(s) to be passed to Alfred's Universal Actions if the user actions this item. Type may be one of "file", "url" or "text".
Added in Alfred 4.5.
func (*Item) Arg ¶
Arg sets Item's arg, the value(s) passed as {query} to the next workflow action. Multiple values are allowed in Alfred 4.1 and later.
func (*Item) Autocomplete ¶
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) Icon ¶
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 ¶
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 ¶
Largetype is what is shown in Alfred's Large Text window on CMD+L instead of Arg (the default).
func (*Item) MarshalJSON ¶
MarshalJSON serializes Item to Alfred's JSON format. You shouldn't need to call this directly: use SendFeedback() instead.
func (*Item) Match ¶
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 ¶
NewModifier returns an initialised Modifier bound to this Item. It also populates the Modifier with any workflow variables set in the Item.
You must specify at least one modifier key. Alfred 3 only supports a single modifier, but Alfred 4+ allow them to be arbitrarily combined. Any invalid modifier keys are ignored. If you specify an unusable set of modifiers (i.e. they evaluate to ""), although a Modifier is returned, it is not retained by Item and will not be sent to Alfred. An error message is also logged.
func (*Item) Quicklook ¶
Quicklook is a path or URL shown in a macOS Quicklook window on SHIFT or CMD+Y.
func (*Item) SetModifier ¶
SetModifier sets a Modifier for a modifier key.
func (*Item) Shift ¶
Shift returns an initialised Modifier bound to this Item and the SHIFT (⇧) key.
func (*Item) UID ¶
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 ¶
Valid tells Alfred whether the result is "actionable", i.e. ENTER will pass Arg to subsequent action.
type MagicAction ¶
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 Modifier ¶
type Modifier struct { // The modifier key, e.g. "cmd", "alt". // With Alfred 4+, modifiers can be combined, e.g. "cmd+alt", "ctrl+shift+cmd" Key string // 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 ¶
Arg sets the arg for the Modifier. Multiple values are allowed in Alfred 4.1 and later.
func (*Modifier) MarshalJSON ¶
MarshalJSON serializes Item to Alfred 3's JSON format. You shouldn't need to call this directly: use SendFeedback() instead.
type 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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
MaxLogSize sets the size (in bytes) when workflow log is rotated. Default: 1 MiB
func MaxResults ¶
MaxResults is the maximum number of results to send to Alfred. 0 means send all results. Default: 0
func RemoveMagic ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
type Session ¶
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 ¶
NewSession creates and initialises a Session.
func (Session) Clear ¶
Clear removes session-scoped cache data. If current is true, it also removes data cached for the current session.
func (Session) LoadOrStore ¶
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 ¶
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.
type Updater ¶
type Updater interface { 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 ¶
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 // Access macOS Keychain. Passwords are saved using the workflow's // bundle ID as the service name. Passwords are synced between // devices if you have iCloud Keychain turned on. Keychain *keychain.Keychain // 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 // 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 ¶
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().
Example ¶
New initialises a Workflow with the default settings. Name, bundle ID, version etc. are read from the environment variables set by Alfred.
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 1.2.0
Example (WithOptions) ¶
Pass one or more Options to New() to configure the created Workflow.
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 ¶
NewFromEnv creates a new Workflows from the specified Env. If env is nil, the system environment is used.
func (*Workflow) Args ¶
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 ¶
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) CheckForUpdate ¶
CheckForUpdate retrieves and caches the list of available releases.
func (*Workflow) ClearCache ¶
ClearCache deletes all files from the workflow's cache directory.
func (*Workflow) Configure ¶
Configure applies one or more Options to Workflow. The returned Option reverts all Options passed to Configure.
Example ¶
Change Workflow's configuration after creation, then revert it.
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) Fatal ¶
Fatal displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.
func (*Workflow) FatalError ¶
FatalError displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.
func (*Workflow) Fatalf ¶
Fatalf displays an error message in Alfred, then calls log.Fatal(), terminating the workflow.
func (*Workflow) Filter ¶
Filter fuzzy-sorts feedback Items against query and deletes Items that don't match.
func (*Workflow) InstallUpdate ¶
InstallUpdate downloads and installs the latest version of the workflow.
func (*Workflow) IsRunning ¶
IsRunning returns true if a job with name jobName is currently running.
func (*Workflow) Name ¶
Name returns the workflow's name as specified in the workflow's main setup sheet in Alfred Preferences.
func (*Workflow) NewFileItem ¶
NewFileItem adds and returns 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 (*Workflow) NewItem ¶
NewItem adds and returns a new feedback Item. See Feedback.NewItem() for more information.
Example ¶
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.
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 ¶
NewWarningItem adds and returns a new Feedback Item with the system warning icon (exclamation mark on yellow triangle).
func (*Workflow) OpenCache ¶
OpenCache opens the workflow's cache directory in the default application (usually Finder).
func (*Workflow) OpenData ¶
OpenData opens the workflow's data directory in the default application (usually Finder).
func (*Workflow) OpenLog ¶
OpenLog opens the workflow's logfile in the default application (usually Console.app).
func (*Workflow) Run ¶
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 ¶
RunInBackground executes cmd in the background. It returns an ErrJobExists error if a job of the same name is already running.
func (*Workflow) SendFeedback ¶
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 ¶
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 ¶
UpdateAvailable returns true if a newer version is available to install.
func (*Workflow) UpdateCheckDue ¶
UpdateCheckDue returns true if an update is available.
func (*Workflow) Var ¶
Var sets the value of workflow variable k on Workflow.Feedback to v. See Feedback.Var() for more information.
func (*Workflow) Vars ¶
Vars returns the workflow variables set on Workflow.Feedback. See Feedback.Vars() for more information.
func (*Workflow) Version ¶
Version returns the workflow's version set in the workflow's configuration sheet in Alfred Preferences.
func (*Workflow) Warn ¶
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.
Example ¶
wf := New() // Add some items wf.NewItem("Item One"). Subtitle("Subtitle one") wf.NewItem("Item Two"). Subtitle("Subtitle two") // Delete existing items, add a warning, then // immediately send feedback wf.Warn("Bad Items", "Those items are boring")
Output: { "variables": { "AW_SESSION_ID": "test-session-id" }, "items": [ { "title": "Bad Items", "subtitle": "Those items are boring", "valid": false, "icon": { "path": "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertCautionBadgeIcon.icns" } } ] }
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package examples contains trivial, but complete, Alfred workflows demonstrating features of AwGo and/or useful workflow idioms.
|
Package examples contains trivial, but complete, Alfred workflows demonstrating features of AwGo and/or useful workflow idioms. |
fuzzy
Workflow fuzzy is a basic demonstration of AwGo's fuzzy filtering.
|
Workflow fuzzy is a basic demonstration of AwGo's fuzzy filtering. |
reading-list
Workflow reading-list is a more advanced example of fuzzy filtering.
|
Workflow reading-list is a more advanced example of fuzzy filtering. |
settings
Workflow settings demonstrates binding a struct to Alfred's settings.
|
Workflow settings demonstrates binding a struct to Alfred's settings. |
update
Workflow update is an example of how to use AwGo's update API.
|
Workflow update is an example of how to use AwGo's update API. |
workflows
Workflow workflows retrieves and filters GitHub repos tagged with "alfred-workflow".
|
Workflow workflows retrieves and filters GitHub repos tagged with "alfred-workflow". |
Package keychain implements a simple interface to the macOS Keychain.
|
Package keychain implements a simple interface to the macOS Keychain. |
Package update implements an API for fetching workflow updates from remote servers.
|
Package update implements an API for fetching workflow updates from remote servers. |
Package util contains general helper functions for workflow (library) authors.
|
Package util contains general helper functions for workflow (library) authors. |
build
Package build provides helpers for developing and building workflows.
|
Package build provides helpers for developing and building workflows. |