github.com/clysto/awgo@v0.15.0/alfred.go (about)

     1  //
     2  // Copyright (c) 2018 Dean Jackson <deanishe@deanishe.net>
     3  //
     4  // MIT Licence. See http://opensource.org/licenses/MIT
     5  //
     6  // Created on 2018-02-11
     7  //
     8  
     9  package aw
    10  
    11  import (
    12  	"fmt"
    13  	"path/filepath"
    14  
    15  	"github.com/deanishe/awgo/util"
    16  )
    17  
    18  /*
    19  Alfred wraps Alfred's AppleScript API, allowing you to open Alfred in
    20  various modes or call External Triggers.
    21  
    22  	a := NewAlfred()
    23  
    24  	// Open Alfred
    25  	if err := a.Search(""); err != nil {
    26  		// handle error
    27  	}
    28  
    29  	// Browse /Applications
    30  	if err := a.Browse("/Applications"); err != nil {
    31  		// handle error
    32  	}
    33  */
    34  type Alfred struct {
    35  	Env
    36  }
    37  
    38  // NewAlfred creates a new Alfred from the environment.
    39  //
    40  // It accepts one optional Env argument. If an Env is passed, Alfred
    41  // is initialised from that instead of the system environment.
    42  func NewAlfred(env ...Env) *Alfred {
    43  
    44  	var e Env
    45  
    46  	if len(env) > 0 {
    47  		e = env[0]
    48  	} else {
    49  		e = sysEnv{}
    50  	}
    51  
    52  	return &Alfred{e}
    53  }
    54  
    55  // Search runs Alfred with the given query. Use an empty query to just open Alfred.
    56  func (a *Alfred) Search(query string) error {
    57  	_, err := util.RunJS(fmt.Sprintf(scriptSearch, util.QuoteJS(query)))
    58  	return err
    59  }
    60  
    61  // Browse tells Alfred to open path in navigation mode.
    62  func (a *Alfred) Browse(path string) error {
    63  
    64  	var err error
    65  
    66  	if path, err = filepath.Abs(path); err != nil {
    67  		return err
    68  	}
    69  
    70  	_, err = util.RunJS(fmt.Sprintf(scriptBrowse, util.QuoteJS(path)))
    71  	return err
    72  }
    73  
    74  // SetTheme tells Alfred to use the specified theme.
    75  func (a *Alfred) SetTheme(name string) error {
    76  	_, err := util.RunJS(fmt.Sprintf(scriptSetTheme, util.QuoteJS(name)))
    77  	return err
    78  }
    79  
    80  // Action tells Alfred to show File Actions for path(s).
    81  func (a *Alfred) Action(path ...string) error {
    82  
    83  	if len(path) == 0 {
    84  		return nil
    85  	}
    86  
    87  	var paths []string
    88  
    89  	for _, p := range path {
    90  
    91  		p, err := filepath.Abs(p)
    92  		if err != nil {
    93  			return fmt.Errorf("[action] couldn't make path absolute (%s): %v", p, err)
    94  		}
    95  
    96  		paths = append(paths, p)
    97  	}
    98  
    99  	_, err := util.RunJS(fmt.Sprintf(scriptAction, util.QuoteJS(paths)))
   100  	return err
   101  }
   102  
   103  // RunTrigger runs an External Trigger in the given workflow. Query may be empty.
   104  //
   105  // It accepts one optional bundleID argument, which is the bundle ID of the
   106  // workflow whose trigger should be run.
   107  // If not specified, it defaults to the current workflow's.
   108  func (a *Alfred) RunTrigger(name, query string, bundleID ...string) error {
   109  
   110  	var bid string
   111  	if len(bundleID) > 0 {
   112  		bid = bundleID[0]
   113  	} else {
   114  		bid, _ = a.Lookup(EnvVarBundleID)
   115  	}
   116  
   117  	opts := map[string]interface{}{
   118  		"inWorkflow": bid,
   119  	}
   120  
   121  	if query != "" {
   122  		opts["withArgument"] = query
   123  	}
   124  
   125  	_, err := util.RunJS(fmt.Sprintf(scriptTrigger, util.QuoteJS(name), util.QuoteJS(opts)))
   126  	return err
   127  }
   128  
   129  // JXA scripts to call Alfred
   130  var (
   131  	// Simple scripts require one or no string
   132  	scriptSearch   = "Application('Alfred 3').search(%s)"
   133  	scriptAction   = "Application('Alfred 3').action(%s)"
   134  	scriptBrowse   = "Application('Alfred 3').browse(%s)"
   135  	scriptSetTheme = "Application('Alfred 3').setTheme(%s)"
   136  	// These scripts require a string and an object of options
   137  	scriptTrigger   = "Application('Alfred 3').runTrigger(%s, %s)"
   138  	scriptSetConfig = "Application('Alfred 3').setConfiguration(%s, %s)"
   139  	scriptRmConfig  = "Application('Alfred 3').removeConfiguration(%s, %s)"
   140  )