diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index d35b65b..47705b0 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -11,7 +11,7 @@ jobs: name: Lint and test strategy: matrix: - go-version: [1.13.x, 1.14.x, 1.15.x] + go-version: [1.13.x, 1.14.x, 1.15.x, 1.16.x] platform: [macos-latest] runs-on: ${{ matrix.platform }} steps: @@ -30,7 +30,10 @@ jobs: - name: Install linters run: | go get golang.org/x/lint/golint - go get github.com/golangci/golangci-lint/cmd/golangci-lint + go install golang.org/x/lint/golint + # later versions only run on Go 1.15.x and above + go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.39.0 + go install github.com/golangci/golangci-lint/cmd/golangci-lint - name: Lint Go source code run: zsh run-tests.sh -vl @@ -46,18 +49,10 @@ jobs: with: file: coverage.out - - name: Codacy - run: | - go install github.com/schrej/godacov - godacov -r coverage.out -t ${{ secrets.CODACY_TOKEN }} -c ${{ github.sha }} - - # Currently broken # - name: Codacy - # uses: brpaz/godacov-action@v1 - # with: - # reportPath: coverage.out - # codacyToken: ${{ secrets.CODACY_TOKEN }} - # commitId: ${{ github.sha }} + # run: | + # go install github.com/schrej/godacov + # godacov -r coverage.out -t "${{ secrets.CODACY_TOKEN }}" -c "${{ github.sha }}" - name: Coveralls uses: shogo82148/actions-goveralls@v1 diff --git a/alfred.go b/alfred.go index 229ae29..afdcda7 100644 --- a/alfred.go +++ b/alfred.go @@ -14,14 +14,16 @@ import ( // JXA scripts to call Alfred. const ( - scriptSearch = "Application(%s).search(%s);" - scriptAction = "Application(%s).action(%s);" - scriptBrowse = "Application(%s).browse(%s);" - scriptSetTheme = "Application(%s).setTheme(%s);" - scriptTrigger = "Application(%s).runTrigger(%s, %s);" - scriptSetConfig = "Application(%s).setConfiguration(%s, %s);" - scriptRmConfig = "Application(%s).removeConfiguration(%s, %s);" - scriptReload = "Application(%s).reloadWorkflow(%s);" + scriptSearch = "Application(%s).search(%s);" + scriptAction = "Application(%s).action(%s);" + // support "asType" option added in Alfred 4.5 + scriptActionType = "Application(%s).action(%s, %s);" + scriptBrowse = "Application(%s).browse(%s);" + scriptSetTheme = "Application(%s).setTheme(%s);" + scriptTrigger = "Application(%s).runTrigger(%s, %s);" + scriptSetConfig = "Application(%s).setConfiguration(%s, %s);" + scriptRmConfig = "Application(%s).removeConfiguration(%s, %s);" + scriptReload = "Application(%s).reloadWorkflow(%s);" ) /* @@ -82,24 +84,48 @@ func (a *Alfred) SetTheme(name string) error { return a.runScript(scriptSetTheme, name) } -// Action tells Alfred to show File Actions for path(s). -func (a *Alfred) Action(path ...string) error { - if len(path) == 0 { +// Action tells Alfred to show Universal Actions for value(s). This calls Alfred.ActionAsType +// with an empty type. +func (a *Alfred) Action(value ...string) error { return a.ActionAsType("", value...) } + +// Types understood by Alfred's `action` API call and item field. +const ( + TypeFile = "file" + TypeURL = "url" + TypeText = "text" +) + +// 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 (a *Alfred) ActionAsType(typ string, value ...string) error { + if len(value) == 0 { return nil } - var paths []string - - for _, p := range path { - p, err := filepath.Abs(p) - if err != nil { - return fmt.Errorf("make absolute path %q: %w", p, err) + if typ == TypeFile { + for i, s := range value { + p, err := filepath.Abs(s) + if err != nil { + return fmt.Errorf("make absolute path %q: %w", s, err) + } + value[i] = p } - - paths = append(paths, p) } - return a.runScript(scriptAction, paths) + switch typ { + case "": + return a.runScript(scriptAction, value) + case "file", "url", "text": + opts := map[string]interface{}{ + "asType": typ, + } + return a.runScript(scriptActionType, value, opts) + default: + return fmt.Errorf("unknown type: %s", typ) + } } // RunTrigger runs an External Trigger in the given workflow. Query may be empty. diff --git a/alfred_test.go b/alfred_test.go index 052f6f6..b29433a 100644 --- a/alfred_test.go +++ b/alfred_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" ) +// TestAlfred verifies scripts generated for Alfred's JXA API. func TestAlfred(t *testing.T) { a := NewAlfred() defer func() { @@ -49,6 +50,18 @@ func TestAlfred(t *testing.T) { assert.Equal(t, x, a.lastScript, "action failed") }) + t.Run("action as file", func(t *testing.T) { + x := `Application("com.runningwithcrayons.Alfred").action(["/","/Volumes"], {"asType":"file"});` + assert.Nil(t, a.ActionAsType(TypeFile, "/", "/Volumes"), "call action on files failed") + assert.Equal(t, x, a.lastScript, "action failed") + }) + + t.Run("action as URL", func(t *testing.T) { + x := `Application("com.runningwithcrayons.Alfred").action(["https://example.com/","https://alfredapp.com/"], {"asType":"url"});` + assert.Nil(t, a.ActionAsType(TypeURL, "https://example.com/", "https://alfredapp.com/"), "call action on URLs failed") + assert.Equal(t, x, a.lastScript, "action failed") + }) + t.Run("browse", func(t *testing.T) { x := `Application("com.runningwithcrayons.Alfred").browse("/Users");` assert.Nil(t, a.Browse("/Users"), "call browse failed") @@ -92,6 +105,7 @@ func TestAlfred(t *testing.T) { }) } +// TestAlfred3 verifies scripts generated for Alfred 3's JXA API. func TestAlfred3(t *testing.T) { a := NewAlfred()