diff --git a/feedback.go b/feedback.go index 21c9743..fbc5616 100644 --- a/feedback.go +++ b/feedback.go @@ -64,6 +64,7 @@ type Item struct { vars map[string]string mods map[string]*Modifier icon *Icon + noUID bool // Suppress UID in JSON } // Title sets the title of the item in Alfred's results @@ -95,6 +96,9 @@ func (it *Item) Arg(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. func (it *Item) UID(s string) *Item { + if it.noUID { + s = "" + } it.uid = &s return it } @@ -331,19 +335,16 @@ func (m *Modifier) MarshalJSON() ([]byte, error) { // It is important to use the constructor functions for Feedback, Item // and Modifier structs. type Feedback struct { - // Items are the results to be sent to Alfred. - Items []*Item - rerun float64 // Tell Alfred to re-run Script Filter. - sent bool // Set to true when feedback has been sent. - vars map[string]string // Top-level feedback variables. + Items []*Item // The results to be sent to Alfred. + NoUIDs bool // If true, suppress Item UIDs. + rerun float64 // Tell Alfred to re-run Script Filter. + sent bool // Set to true when feedback has been sent. + vars map[string]string // Top-level feedback variables. } // NewFeedback creates a new, initialised Feedback struct. func NewFeedback() *Feedback { - fb := &Feedback{} - fb.Items = []*Item{} - fb.vars = map[string]string{} - return fb + return &Feedback{Items: []*Item{}, vars: map[string]string{}} } // Var sets an Alfred variable for subsequent workflow elements. @@ -381,7 +382,7 @@ func (fb *Feedback) IsEmpty() bool { return len(fb.Items) == 0 } // The Item inherits any workflow variables set on the Feedback parent at // time of creation. func (fb *Feedback) NewItem(title string) *Item { - it := &Item{title: title, vars: map[string]string{}} + it := &Item{title: title, vars: map[string]string{}, noUID: fb.NoUIDs} fb.Items = append(fb.Items, it) return it } diff --git a/magic.go b/magic.go index 5db6c72..0b49e43 100644 --- a/magic.go +++ b/magic.go @@ -12,6 +12,7 @@ import ( "fmt" "log" "os" + "os/exec" "strings" ) @@ -35,13 +36,20 @@ var ( // interface for full documentation. type MagicActions map[string]MagicAction -// Register adds a MagicArgument to the mapping. Previous entries are overwritten. +// Register adds a MagicAction to the mapping. Previous entries are overwritten. func (ma MagicActions) Register(actions ...MagicAction) { for _, action := range actions { ma[action.Keyword()] = action } } +// Unregister removes a MagicAction from the mapping (based on its keyword). +func (ma MagicActions) Unregister(actions ...MagicAction) { + for _, action := range actions { + delete(ma, action.Keyword()) + } +} + // 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. @@ -116,10 +124,11 @@ func (ma MagicActions) Args(args []string, prefix string) []string { // deldata | Delete everything in the workflow's data directory. // delcache | Delete everything in the workflow's cache directory. // reset | Delete everything in the workflow's data and cache directories. +// help | Open help URL in default browser. +// | Only registered if you have set a HelpURL. // update | Check for updates and install a newer version of the workflow // | if available. -// | Only registered if you have set an Updater via SetUpdater() -// | or the GitHub value in Options. +// | Only registered if you have set an Updater. // type MagicAction interface { // Keyword is what the user must enter to run the action after @@ -183,6 +192,19 @@ func (a resetMagic) Description() string { return "Delete all saved and cached w func (a resetMagic) RunText() string { return "Deleted workflow saved and cached data" } func (a resetMagic) Run() error { return Reset() } +// Opens URL in default browser. +type helpMagic struct { + URL string +} + +func (a helpMagic) Keyword() string { return "help" } +func (a helpMagic) Description() string { return "Open workflow help URL in default browser" } +func (a helpMagic) RunText() string { return "Opening help in your browser…" } +func (a helpMagic) Run() error { + cmd := exec.Command("open", a.URL) + return cmd.Run() +} + // Updates the workflow if a newer release is available. type updateMagic struct { updater Updater diff --git a/update/update.go b/update/update.go index f05896c..0e1b4aa 100644 --- a/update/update.go +++ b/update/update.go @@ -215,7 +215,7 @@ func (u *Updater) Install() error { // cachePath returns a filepath within AwGo's update cache directory. func (u *Updater) cachePath(filename string) string { - dp := util.MustExist(filepath.Join(u.cacheDir, "update")) + dp := util.MustExist(filepath.Join(u.cacheDir, "_aw/update")) return filepath.Join(dp, filename) } diff --git a/workflow.go b/workflow.go index fb2c617..f10262b 100644 --- a/workflow.go +++ b/workflow.go @@ -24,7 +24,7 @@ import ( ) // AwGoVersion is the semantic version number of this library. -const AwGoVersion = "0.10.1" +const AwGoVersion = "0.11" var ( startTime time.Time // Time execution started @@ -81,6 +81,12 @@ func (opts options) apply(wf *Workflow) Option { func HelpURL(URL string) Option { return func(wf *Workflow) Option { prev := wf.HelpURL + ma := &helpMagic{URL} + if URL != "" { + wf.MagicActions.Register(ma) + } else { + wf.MagicActions.Unregister(ma) + } wf.HelpURL = URL return HelpURL(prev) } @@ -152,6 +158,20 @@ func SortOptions(opts ...fuzzy.Option) Option { } } +// SuppressUIDs prevents UIDs from being set on feedback Items. +// This turns off Alfred's knowledge, so items will be shown in the order +// you add them. Useful if you need a particular item to be the top result, +// e.g. a notification of an update. +// +// This setting only applies to Items created *after* it has been set. +func SuppressUIDs(on bool) Option { + return func(wf *Workflow) Option { + prev := wf.Feedback.NoUIDs + wf.Feedback.NoUIDs = on + return SuppressUIDs(prev) + } +} + // Update sets the updater for the Workflow. func Update(updater Updater) Option { return func(wf *Workflow) Option { @@ -506,6 +526,15 @@ func (wf *Workflow) OpenLog() error { return cmd.Run() } +func OpenHelp() error { return wf.OpenHelp() } +func (wf *Workflow) OpenHelp() error { + if wf.HelpURL == "" { + return errors.New("Help URL is not set") + } + cmd := exec.Command("open", wf.HelpURL) + return cmd.Run() +} + // -------------------------------------------------------------------- // Feedback