diff --git a/cli.go b/cli.go
index 8755bb6..ef0091d 100644
--- a/cli.go
+++ b/cli.go
@@ -316,12 +316,10 @@ func runSearch() {
Var("close", "true")
if len(proj.Folders) > 0 {
-
sub := "Open Project Folder"
if len(proj.Folders) > 1 {
sub += "s"
}
-
it.NewModifier("cmd").
Subtitle(sub).
Icon(&aw.Icon{Value: "public.folder", Type: "filetype"}).
diff --git a/go.mod b/go.mod
index 84d119b..e217dcd 100644
--- a/go.mod
+++ b/go.mod
@@ -2,16 +2,15 @@ module github.com/deanishe/alfred-sublime-text
require (
github.com/BurntSushi/toml v0.3.1
- github.com/bmatcuk/doublestar v1.1.5
+ github.com/bmatcuk/doublestar v1.3.0 // indirect
github.com/davecgh/go-spew v1.1.1
- github.com/deanishe/awgo v0.20.4
- github.com/disintegration/imaging v1.6.1
+ github.com/deanishe/awgo v0.22.1
+ github.com/disintegration/imaging v1.6.2
github.com/gobwas/glob v0.2.3
github.com/magefile/mage v1.9.0
github.com/yosuke-furukawa/json5 v0.1.1
- golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect
- golang.org/x/text v0.3.2
- howett.net/plist v0.0.0-20181124034731-591f970eefbb
+ golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect
+ howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 // indirect
)
go 1.13
diff --git a/go.sum b/go.sum
index 2d77cbb..4d4f0df 100644
--- a/go.sum
+++ b/go.sum
@@ -2,13 +2,18 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk=
github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
+github.com/bmatcuk/doublestar v1.3.0 h1:1jLE2y0VpSrOn/QR9G4f2RmrCtkM3AuATcWradjHUvM=
+github.com/bmatcuk/doublestar v1.3.0/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/deanishe/awgo v0.20.4 h1:d6PUWriwtOtJr+wxxNwQ58N50fr9lhsf3Z5XhWfmYnI=
-github.com/deanishe/awgo v0.20.4/go.mod h1:GU6eQZvFKhxX6Qjlb5Qls/Le/3r5XOs3P0L4F283R+w=
-github.com/disintegration/imaging v1.6.1 h1:JnBbK6ECIZb1NsWIikP9pd8gIlTIRx7fuDNpU9fsxOE=
-github.com/disintegration/imaging v1.6.1/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
+github.com/deanishe/awgo v0.22.1 h1:N61eAOqc2u2zMQjY0Srd3mAn1gaj/9nU4YaTe3aaHU0=
+github.com/deanishe/awgo v0.22.1/go.mod h1:FIvY0LMPTrqEqSDy79rcSqL6+oFUhFL9qlXBi+qQKks=
+github.com/deanishe/go-env v0.4.0 h1:tpu14o16gJGTN/w2gxntwxu2l5Eby30jSrnlgOfjzwk=
+github.com/deanishe/go-env v0.4.0/go.mod h1:RgEcGAqdRnt8ybQteAbv1Ys2lWIRE7TlgON/sbdjuaY=
+github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
+github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@@ -19,8 +24,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE=
github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -28,10 +33,10 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yosuke-furukawa/json5 v0.1.1 h1:0F9mNwTvOuDNH243hoPqvf+dxa5QsKnZzU20uNsh3ZI=
github.com/yosuke-furukawa/json5 v0.1.1/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU=
-golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81 h1:00VmoueYNlNz/aHIilyyQz/MHSqGoWJzpFv/HW8xpzI=
-golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
+golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -44,3 +49,5 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
+howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 h1:AQkaJpH+/FmqRjmXZPELom5zIERYZfwTjnHpfoVMQEc=
+howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
diff --git a/info.plist b/info.plist
index 65dc81b..349a3c8 100644
--- a/info.plist
+++ b/info.plist
@@ -29,16 +29,6 @@
modifiersubtext
vitoclose
-
-
-
- destinationuid
- A18FD78E-C1F5-4B49-95D1-9ED40BA1E4D8
- modifiers
- 0
- modifiersubtext
-
- vitoclose
@@ -178,19 +168,6 @@
- A18FD78E-C1F5-4B49-95D1-9ED40BA1E4D8
-
-
- destinationuid
- D26E55A9-2B57-4343-8C9D-9223F1E3AA70
- modifiers
- 0
- modifiersubtext
-
- vitoclose
-
-
-
D545A35F-4FA1-469E-A8AB-A167D29E8D50
@@ -231,47 +208,31 @@
config
- alfredfiltersresults
-
- alfredfiltersresultsmatchmode
+ action
0
- argumenttrimmode
+ argument
0
- argumenttype
- 1
- escaping
- 68
- keyword
- .st
- queuedelaycustom
- 1
- queuedelayimmediatelyinitially
+ focusedappvariable
- queuedelaymode
+ focusedappvariablename
+
+ hotkey
0
- queuemode
- 1
- runningsubtext
- Finding projects…
- script
- ./alfsubl -- "$1"
- scriptargtype
- 1
- scriptfile
+ hotmod
+ 0
+ hotstring
- subtext
- Search and Open Sublime Text Projects
- title
- Sublime Text Projects
- type
+ leftcursor
+
+ modsmode
+ 0
+ relatedAppsMode
0
- withspace
-
type
- alfred.workflow.input.scriptfilter
+ alfred.workflow.trigger.hotkey
uid
- 0D6DB001-6C1A-4973-BD3C-0CD4706096CB
+ DA2EB775-5859-482A-8BF0-499164DCDA0B
version
2
@@ -314,60 +275,51 @@
config
- action
- 0
- argument
- 0
- focusedappvariable
+ alfredfiltersresults
- focusedappvariablename
-
- hotkey
+ alfredfiltersresultsmatchmode
0
- hotmod
+ argumenttreatemptyqueryasnil
+
+ argumenttrimmode
0
- hotstring
-
- leftcursor
+ argumenttype
+ 1
+ escaping
+ 68
+ keyword
+ .st
+ queuedelaycustom
+ 1
+ queuedelayimmediatelyinitially
- modsmode
+ queuedelaymode
0
- relatedAppsMode
+ queuemode
+ 1
+ runningsubtext
+ Finding projects…
+ script
+ ./alfsubl -- "$1"
+ scriptargtype
+ 1
+ scriptfile
+
+ subtext
+ Search and Open Sublime Text Projects
+ title
+ Sublime Text Projects
+ type
0
-
- type
- alfred.workflow.trigger.hotkey
- uid
- DA2EB775-5859-482A-8BF0-499164DCDA0B
- version
- 2
-
-
- type
- alfred.workflow.utility.hidealfred
- uid
- D26E55A9-2B57-4343-8C9D-9223F1E3AA70
- version
- 1
-
-
- config
-
- inputstring
- {var:close}
- matchcasesensitive
+ withspace
- matchmode
- 0
- matchstring
- true
type
- alfred.workflow.utility.filter
+ alfred.workflow.input.scriptfilter
uid
- A18FD78E-C1F5-4B49-95D1-9ED40BA1E4D8
+ 0D6DB001-6C1A-4973-BD3C-0CD4706096CB
version
- 1
+ 3
config
@@ -376,6 +328,8 @@
alfredfiltersresultsmatchmode
0
+ argumenttreatemptyqueryasnil
+
argumenttrimmode
0
argumenttype
@@ -414,7 +368,7 @@
uid
9981F708-6C83-44CD-BC06-B6C10A2B00F6
version
- 2
+ 3
config
@@ -473,6 +427,25 @@
version
1
+
+ config
+
+ inputstring
+ {var:action}
+ matchcasesensitive
+
+ matchmode
+ 1
+ matchstring
+ rescan
+
+ type
+ alfred.workflow.utility.filter
+ uid
+ 2DBA4231-BA57-4BB8-9E1D-DD1F29FA2A8A
+ version
+ 1
+
config
@@ -496,25 +469,6 @@
version
1
-
- config
-
- inputstring
- {var:action}
- matchcasesensitive
-
- matchmode
- 1
- matchstring
- rescan
-
- type
- alfred.workflow.utility.filter
- uid
- 2DBA4231-BA57-4BB8-9E1D-DD1F29FA2A8A
- version
- 1
-
config
@@ -599,126 +553,110 @@ To add additional directories to scan, use `.stconfig > Edit Config File`.0A75A8BC-3856-4729-B16A-62B167B2E91F
xpos
- 40
+ 45
ypos
- 50
+ 165
0D6DB001-6C1A-4973-BD3C-0CD4706096CB
note
Filter Sublime Text projects
xpos
- 230
+ 235
ypos
- 50
+ 165
1958F9DC-5B69-4F0C-B4DC-FCBAE0AB1EF8
xpos
- 670
+ 675
ypos
- 320
+ 340
2DBA4231-BA57-4BB8-9E1D-DD1F29FA2A8A
note
$action != rescan
xpos
- 470
+ 475
ypos
- 350
+ 370
3044F153-18F7-41B3-949A-22D21BA52903
xpos
- 40
+ 45
ypos
- 320
+ 340
506077C9-6BF8-401D-B34D-ACAEAA975F30
note
Open project/folder
xpos
- 470
+ 450
ypos
- 50
+ 165
640C6327-8251-4BC6-B952-603E863B03D2
note
$action == rescan
xpos
- 470
+ 475
ypos
- 500
+ 520
671FF011-6B4E-45E5-B96B-4A6B87738E93
xpos
- 570
+ 575
ypos
- 350
+ 370
6756738D-5D8A-4FEC-9F39-8AF903ED1FD2
xpos
- 670
+ 675
ypos
- 620
+ 640
6F4C4F63-0697-43E5-B54D-317C51DFE8D5
xpos
- 1070
+ 1075
ypos
- 320
+ 340
73C36700-35E0-40C2-A0AB-9D6B310FD946
xpos
- 980
+ 985
ypos
- 350
+ 370
9981F708-6C83-44CD-BC06-B6C10A2B00F6
note
View workflow configuration
xpos
- 230
- ypos
- 320
-
- A18FD78E-C1F5-4B49-95D1-9ED40BA1E4D8
-
- note
- Hide Alfred
- xpos
- 470
- ypos
- 220
-
- D26E55A9-2B57-4343-8C9D-9223F1E3AA70
-
- xpos
- 570
+ 235
ypos
- 220
+ 340
D545A35F-4FA1-469E-A8AB-A167D29E8D50
xpos
- 670
+ 675
ypos
- 470
+ 490
DA2EB775-5859-482A-8BF0-499164DCDA0B
xpos
- 40
+ 45
ypos
- 180
+ 35
variables
@@ -733,8 +671,8 @@ To add additional directories to scan, use `.stconfig > Edit Config File`.false
version
- 3.1.1
+ 3.1.2
webaddress
-
+ https://github.com/deanishe/alfred-sublime-text
diff --git a/magefile.go b/magefile.go
index d1388ff..a386213 100644
--- a/magefile.go
+++ b/magefile.go
@@ -6,32 +6,41 @@
package main
import (
- "archive/zip"
"fmt"
- "io"
- "io/ioutil"
"os"
"path/filepath"
- "regexp"
- "unicode"
- "github.com/bmatcuk/doublestar"
+ "github.com/deanishe/awgo/util/build"
"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
- "golang.org/x/text/transform"
- "golang.org/x/text/unicode/norm"
)
// Default target to run when none is specified
// If not set, running mage will list available targets
// var Default = Build
+const (
+ green = "03ae03"
+ // blue = "5484f3"
+ // red = "b00000"
+ // yellow = "f8ac30"
+)
+
+const (
+ buildDir = "./build"
+ distDir = "./dist"
+)
+
var (
+ info *build.Info
workDir string
)
func init() {
var err error
+ if info, err = build.NewInfo(); err != nil {
+ panic(err)
+ }
if workDir, err = os.Getwd(); err != nil {
panic(err)
}
@@ -39,78 +48,40 @@ func init() {
func mod(args ...string) error {
argv := append([]string{"mod"}, args...)
- return sh.RunWith(alfredEnv(), "go", argv...)
+ return sh.RunWith(info.Env(), "go", argv...)
}
// Aliases are mage command aliases.
var Aliases = map[string]interface{}{
"b": Build,
+ "c": Clean,
"d": Dist,
"l": Link,
}
-// Build builds workflow in ./build
+// make workflow in build directory
func Build() error {
mg.Deps(cleanBuild, Icons)
- // mg.Deps(Deps)
fmt.Println("building ...")
- if err := sh.RunWith(alfredEnv(), "go", "build", "-o", "./build/alfsubl", "."); err != nil {
+ if err := sh.RunWith(info.Env(), "go", "build", "-o", "./build/alfsubl", "."); err != nil {
return err
}
- // link files to ./build
- globs := []struct {
- glob, dest string
- }{
- {"*.png", ""},
- {"info.plist", ""},
- {"*.html", ""},
- {"README.md", ""},
- {"LICENCE.txt", ""},
- {"icons/*.png", ""},
- }
-
- pairs := []struct {
- src, dest string
- }{}
-
- for _, cfg := range globs {
- files, err := doublestar.Glob(cfg.glob)
- if err != nil {
- return err
- }
-
- for _, p := range files {
- dest := filepath.Join("./build", cfg.dest, p)
- pairs = append(pairs, struct{ src, dest string }{p, dest})
- }
- }
-
- for _, p := range pairs {
-
- var (
- relPath string
- dir = filepath.Dir(p.dest)
- err error
- )
-
- if err = os.MkdirAll(dir, 0755); err != nil {
- return err
- }
- if relPath, err = filepath.Rel(filepath.Dir(p.dest), p.src); err != nil {
- return err
- }
- fmt.Printf("%s --> %s\n", p.dest, relPath)
- if err := os.Symlink(relPath, p.dest); err != nil {
- return err
- }
- }
+ // files to include in workflow
+ globs := build.Globs(
+ "*.png",
+ "info.plist",
+ "*.html",
+ "README.md",
+ "LICENCE.txt",
+ "icons/*.png",
+ )
- return nil
+ return build.SymlinkGlobs(buildDir, globs...)
}
-// Run run workflow
+// run workflow
func Run() error {
mg.Deps(Build)
fmt.Println("running ...")
@@ -119,134 +90,27 @@ func Run() error {
}
defer os.Chdir(workDir)
- return sh.RunWith(alfredEnv(), "./alfsubl", "-h")
+ return sh.RunWith(info.Env(), "./alfsubl", "-h")
}
-// Dist build an .alfredworkflow file in ./dist
+// create an .alfredworkflow file in ./dist
func Dist() error {
mg.SerialDeps(Clean, Build)
- if err := os.MkdirAll("./dist", 0700); err != nil {
- return err
- }
-
- var (
- name = slugify(fmt.Sprintf("%s-%s.alfredworkflow", Name, Version))
- path = filepath.Join("./dist", name)
- f *os.File
- w *zip.Writer
- err error
- )
-
- fmt.Println("building .alfredworkflow file ...")
-
- if _, err = os.Stat(path); err == nil {
- if err = os.Remove(path); err != nil {
- return err
- }
- fmt.Println("deleted old .alfredworkflow file")
- }
-
- if f, err = os.Create(path); err != nil {
- return err
- }
- defer f.Close()
-
- w = zip.NewWriter(f)
-
- err = filepath.Walk("./build", func(path string, fi os.FileInfo, err error) error {
-
- if err != nil {
- return err
- }
-
- if fi.IsDir() {
- return nil
- }
-
- var name string
- if name, err = filepath.Rel("./build", path); err != nil {
- return err
- }
-
- fmt.Printf(" %s (%v)\n", name, fi.Mode().Perm())
-
- var (
- f *os.File
- zf io.Writer
- fh *zip.FileHeader
- )
-
- fh = &zip.FileHeader{
- Name: name,
- Method: zip.Deflate,
- }
-
- fh.SetMode(fi.Mode().Perm())
-
- if f, err = os.Open(path); err != nil {
- return err
- }
- defer f.Close()
-
- if zf, err = w.CreateHeader(fh); err != nil {
- return err
- }
- if _, err = io.Copy(zf, f); err != nil {
- return err
- }
-
- return nil
- })
-
+ p, err := build.Export(buildDir, distDir)
if err != nil {
return err
}
- if err = w.Close(); err != nil {
- return err
- }
-
- fmt.Printf("wrote %s\n", path)
-
+ fmt.Printf("built workflow file %s\n", p)
return nil
}
-var (
- rxAlphaNum = regexp.MustCompile(`[^a-zA-Z0-9.-]+`)
- rxMultiDash = regexp.MustCompile(`-+`)
-)
-
-// make s filesystem- and URL-safe.
-func slugify(s string) string {
- s = fold(s)
- s = rxAlphaNum.ReplaceAllString(s, "-")
- s = rxMultiDash.ReplaceAllString(s, "-")
- return s
-}
-
-var stripper = transform.Chain(norm.NFD, transform.RemoveFunc(isMn))
-
-// isMn returns true if rune is a non-spacing mark
-func isMn(r rune) bool {
- return unicode.Is(unicode.Mn, r) // Mn: non-spacing mark
-}
-
-// fold strips diacritics from string.
-func fold(s string) string {
- ascii, _, err := transform.String(stripper, s)
- if err != nil {
- panic(err)
- }
- return ascii
-}
-
-// Link symlinks ./build directory to Alfred's workflow directory.
+// symlink build directory to Alfred's workflow directory
func Link() error {
mg.Deps(Build)
- fmt.Println("linking ./build to workflow directory ...")
- target := filepath.Join(workflowDirectory(), BundleID)
- // fmt.Printf("target: %s\n", target)
+ fmt.Printf("linking %s to workflow directory ...\n", buildDir)
+ target := filepath.Join(info.AlfredWorkflowDir, info.BundleID)
if exists(target) {
fmt.Println("removing existing workflow ...")
@@ -256,34 +120,16 @@ func Link() error {
return err
}
- build, err := filepath.Abs("build")
- if err != nil {
- return err
- }
- src, err := filepath.Rel(filepath.Dir(target), build)
+ src, err := filepath.Abs(buildDir)
if err != nil {
return err
}
-
- if err := os.Symlink(src, target); err != nil {
- return err
- }
-
- fmt.Printf("symlinked workflow to %s\n", target)
-
- return nil
+ return build.Symlink(target, src, true)
}
-// Icons generate icons
+// generate icons
func Icons() error {
- var (
- green = "03ae03"
- // blue = "5484f3"
- // red = "b00000"
- // yellow = "f8ac30"
- )
-
copies := []struct {
src, dest, colour string
}{
@@ -308,66 +154,39 @@ func Icons() error {
return rotateIcon("./icons/loading.png", []int{15, 30})
}
-// Deps ensure dependencies
+// download dependencies
func Deps() error {
mg.Deps(cleanDeps)
fmt.Println("downloading deps ...")
return mod("download")
}
-// Clean remove build files
-func Clean() {
- fmt.Println("cleaning ...")
- mg.Deps(cleanBuild, cleanMage)
-}
-
-func cleanDeps() error {
- return mod("tidy", "-v")
-}
+func cleanDeps() error { return mod("tidy", "-v") }
-func cleanDir(name string, exclude ...string) error {
+// remove build files
+func Clean() { mg.Deps(cleanBuild, cleanMage) }
- if _, err := os.Stat(name); err != nil {
- return nil
- }
-
- infos, err := ioutil.ReadDir(name)
- if err != nil {
+func cleanBuild() error {
+ fmt.Printf("cleaning %s ...\n", buildDir)
+ if err := sh.Rm(buildDir); err != nil {
return err
}
- for _, fi := range infos {
-
- var match bool
- for _, glob := range exclude {
- if match, err = doublestar.Match(glob, fi.Name()); err != nil {
- return err
- } else if match {
- break
- }
- }
-
- if match {
- fmt.Printf("excluded: %s\n", fi.Name())
- continue
- }
-
- p := filepath.Join(name, fi.Name())
- if err := os.RemoveAll(p); err != nil {
- return err
- }
- }
- return nil
-}
-
-func cleanBuild() error {
- return cleanDir("./build")
+ return os.MkdirAll(buildDir, 0755)
}
func cleanMage() error {
+ fmt.Println("cleaning mage ...")
return sh.Run("mage", "-clean")
}
-// CleanIcons delete all generated icons from ./icons
-func CleanIcons() error {
- return cleanDir("./icons")
-}
+// return true if path exists
+func exists(path string) bool {
+ if _, err := os.Stat(path); err != nil {
+ if os.IsNotExist(err) {
+ return false
+ }
+ panic(err)
+ }
+
+ return true
+}
\ No newline at end of file
diff --git a/magefile_alfred.go b/magefile_alfred.go
deleted file mode 100644
index 589abe4..0000000
--- a/magefile_alfred.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2019 Dean Jackson
-// MIT Licence applies http://opensource.org/licenses/MIT
-
-// +build mage
-
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- "howett.net/plist"
-)
-
-var (
- alfredPrefsPath = os.ExpandEnv("${HOME}/Library/Preferences/com.runningwithcrayons.Alfred-Preferences-3.plist")
- defaultSyncFolder = os.ExpandEnv("~/Library/Application Support/Alfred 3")
-
- // Read from info.plist
- BundleID string
- Version string
- Name string
-
- DataDir string
- CacheDir string
- WorkflowDir string
-)
-
-func init() {
- home := os.ExpandEnv("$HOME")
- ip := readInfo()
-
- BundleID = ip.BundleID
- if BundleID == "" {
- panic("Bundle ID is unset")
- }
-
- Version = ip.Version
- Name = ip.Name
-
- CacheDir = filepath.Join(home, "Library/Caches/com.runningwithcrayons.Alfred-3/Workflow Data", ip.BundleID)
- DataDir = filepath.Join(home, "Library/Application Support/Alfred 3/Workflow Data", ip.BundleID)
- WorkflowDir = workflowDirectory()
-}
-
-type infoPlist struct {
- BundleID string `plist:"bundleid"`
- Version string `plist:"version"`
- Name string `plist:"name"`
-}
-
-func syncFolder() string {
-
- data, err := ioutil.ReadFile(alfredPrefsPath)
- if err != nil {
- panic(err)
- }
-
- p := struct {
- SyncFolder string `plist:"syncfolder"`
- }{}
-
- if _, err := plist.Unmarshal(data, &p); err != nil {
- panic(err)
- }
-
- return p.SyncFolder
-}
-
-func workflowDirectory() string {
-
- dirs := []string{}
-
- if p := syncFolder(); p != "" {
- dirs = append(dirs, p)
- }
- dirs = append(dirs, defaultSyncFolder)
-
- for _, p := range dirs {
- p = expandPath(filepath.Join(p, "Alfred.alfredpreferences/workflows"))
- if _, err := os.Stat(p); err != nil {
- fmt.Printf("read %q: %v\n", p, err)
- continue
- }
- return p
- }
- panic("workflow directory not found")
-}
-
-func readInfo() infoPlist {
- data, err := ioutil.ReadFile("info.plist")
- if err != nil {
- panic(err)
- }
-
- ip := infoPlist{}
- if _, err := plist.Unmarshal(data, &ip); err != nil {
- panic(err)
- }
-
- return ip
-}
-
-func alfredEnv() map[string]string {
- return map[string]string{
- "alfred_workflow_bundleid": BundleID,
- "alfred_workflow_version": Version,
- "alfred_workflow_name": Name,
- "alfred_workflow_cache": CacheDir,
- "alfred_workflow_data": DataDir,
- "GO111MODULE": "on", // for building
- }
-}
-
-// expand ~ and variables in path.
-func expandPath(path string) string {
- if strings.HasPrefix(path, "~") {
- path = "${HOME}" + path[1:]
- }
-
- return os.ExpandEnv(path)
-}
-
-func exists(path string) bool {
- if _, err := os.Stat(path); err != nil {
- if os.IsNotExist(err) {
- return false
- }
- panic(err)
- }
-
- return true
-}
diff --git a/scan.go b/scan.go
index 637c70f..b0b42e9 100644
--- a/scan.go
+++ b/scan.go
@@ -9,6 +9,7 @@
package main
import (
+ "sort"
"bufio"
"bytes"
"fmt"
@@ -75,35 +76,18 @@ func NewScanManager(conf *config) *ScanManager {
// ScanDue returns true if one or more scanners needs updating.
func (sm *ScanManager) ScanDue() bool {
-
if !wf.Cache.Exists(cacheKey) {
return true
}
-
- // age, err := wf.Cache.Age(cacheKey)
- // if err != nil {
- // log.Printf("[scan] cache empty")
- // return true
- // }
-
- // if fi, err := os.Stat(configFile); err == nil {
- // if time.Now().Sub(fi.ModTime()) < age {
- // log.Printf("[scan] config file has changed")
- // return true
- // }
- // }
-
if len(sm.dueScanners()) > 0 {
log.Printf("[scan] cache expired")
return true
}
-
return false
}
// Scan updates the cached lists of projects.
func (sm *ScanManager) Scan() error {
-
var (
due = map[string]bool{}
ins []<-chan string
@@ -117,7 +101,6 @@ func (sm *ScanManager) Scan() error {
}
for name := range sm.Scanners {
-
if !sm.IsActive(name) {
// Clear any cached results
if err := wf.Cache.Store(sm.cacheName(name), nil); err != nil {
@@ -179,17 +162,14 @@ func (sm *ScanManager) IsDue(name string) bool {
// load data from cache.
func (sm *ScanManager) scanFromCache(name string) <-chan string {
-
var (
key = sm.cacheName(name)
out = make(chan string)
)
go func() {
-
- defer util.Timed(time.Now(), fmt.Sprintf(`[cache] loaded "%s"`, name))
-
defer close(out)
+ defer util.Timed(time.Now(), fmt.Sprintf(`[cache] loaded "%s"`, name))
if !wf.Cache.Exists(key) {
return
@@ -214,7 +194,6 @@ func (sm *ScanManager) scanFromCache(name string) <-chan string {
}
func (sm *ScanManager) dueScanners() []string {
-
var (
due []string
force bool
@@ -234,7 +213,6 @@ func (sm *ScanManager) dueScanners() []string {
}
for name := range sm.Scanners {
-
if !sm.IsActive(name) {
continue
}
@@ -243,7 +221,6 @@ func (sm *ScanManager) dueScanners() []string {
due = append(due, name)
}
}
-
return due
}
@@ -256,18 +233,11 @@ func (sm *ScanManager) cacheName(name string) string {
}
// Load loads cached Projects.
-func (sm *ScanManager) Load() ([]Project, error) {
-
- var (
- projs []Project
- err error
- )
-
+func (sm *ScanManager) Load() (projects []Project, err error) {
if wf.Cache.Exists(cacheKey) {
- err = wf.Cache.LoadJSON(cacheKey, &projs)
+ err = wf.Cache.LoadJSON(cacheKey, &projects)
}
-
- return projs, err
+ return
}
// Find files with `mdfind`
@@ -275,8 +245,8 @@ type mdfindScanner struct{}
func (s *mdfindScanner) Name() string { return "mdfind" }
func (s *mdfindScanner) Scan(conf *config) (<-chan string, error) {
- cmd := exec.Command("/usr/bin/mdfind", "-name", "*"+fileExtension)
- return lineCommand(cmd, s.Name())
+ cmd := exec.Command("/usr/bin/mdfind", fmt.Sprintf("kMDItemFSName == '*%s'", fileExtension))
+ return lineCommand(cmd, "mdfind")
}
// Find files with `locate`
@@ -285,28 +255,23 @@ type locateScanner struct{}
func (s *locateScanner) Name() string { return "locate" }
func (s *locateScanner) Scan(conf *config) (<-chan string, error) {
cmd := exec.Command("/usr/bin/locate", "*"+fileExtension)
- return lineCommand(cmd, s.Name())
+ return lineCommand(cmd, "locate")
}
+// Find files with `find`
type findScanner struct{}
func (s *findScanner) Name() string { return "find" }
func (s *findScanner) Scan(conf *config) (<-chan string, error) {
var chs []<-chan string
-
for _, sp := range conf.SearchPaths {
-
argv := []string{sp.Path, "-maxdepth", fmt.Sprintf("%d", sp.Depth)}
argv = append(argv, "-type", "f", "-name", "*"+fileExtension)
-
- cmd := exec.Command("/usr/bin/find", argv...)
-
- ch, err := lineCommand(cmd, fmt.Sprintf("[%s] %s", s.Name(), sp.Path))
+ ch, err := lineCommand(exec.Command("/usr/bin/find", argv...), "[find] " + sp.Path)
if err != nil {
return nil, err
}
-
chs = append(chs, ch)
}
@@ -322,7 +287,6 @@ func lineCommand(cmd *exec.Cmd, name string) (chan string, error) {
)
go func() {
-
defer close(out)
defer util.Timed(time.Now(), fmt.Sprintf("%s scan", name))
@@ -331,13 +295,12 @@ func lineCommand(cmd *exec.Cmd, name string) (chan string, error) {
log.Printf("[%s] command failed: %v", name, err)
return
}
-
if err := cmd.Start(); err != nil {
log.Printf("[%s] command failed: %v", name, err)
return
}
- // Read mdfind output and send it to channel
+ // Read output and send it to channel
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
out <- scanner.Text()
@@ -345,7 +308,6 @@ func lineCommand(cmd *exec.Cmd, name string) (chan string, error) {
if err := scanner.Err(); err != nil {
log.Printf("[%s] couldn't parse output: %v", name, err)
}
-
if err != cmd.Wait() {
log.Printf("[%s] command failed: %v", name, err)
}
@@ -395,7 +357,6 @@ func filterNotProject(in <-chan string) <-chan string {
func filterNotExist(in <-chan string) <-chan string {
return filterMatches(in, func(r string) bool {
if _, err := os.Stat(r); err != nil {
- // log.Printf("[filter] doesn't exist: %s", p)
return true
}
return false
@@ -404,16 +365,11 @@ func filterNotExist(in <-chan string) <-chan string {
// Filter files that have already passed through.
func filterDupes(in <-chan string) <-chan string {
-
seen := map[string]bool{}
-
return filterMatches(in, func(r string) bool {
-
if seen[r] {
- // log.Printf("[filter] duplicate: %s", r.String())
return true
}
-
seen[r] = true
return false
})
@@ -421,12 +377,9 @@ func filterDupes(in <-chan string) <-chan string {
// passes through paths from in to out, ignoring those for which ignore(path) returns true.
func filterMatches(in <-chan string, ignore func(r string) bool) <-chan string {
-
var out = make(chan string)
-
go func() {
defer close(out)
-
for p := range in {
if ignore(p) {
continue
@@ -440,19 +393,19 @@ func filterMatches(in <-chan string, ignore func(r string) bool) <-chan string {
func cacheProjects(key string, in <-chan string) <-chan string {
- projs := []string{}
-
- var out = make(chan string)
+ var (
+ projs = []string{}
+ out = make(chan string)
+ )
go func() {
-
defer close(out)
-
for p := range in {
projs = append(projs, p)
out <- p
}
+ sort.Sort(sort.StringSlice(projs))
data := []byte(strings.Join(projs, "\n"))
if err := wf.Cache.Store(key, data); err != nil {
log.Printf("[cache] error storing %s: %v", key, err)
@@ -466,12 +419,10 @@ func cacheProjects(key string, in <-chan string) <-chan string {
// Read Sublime/VSCode project files
func resultToProject(in <-chan string) <-chan Project {
-
var out = make(chan Project)
go func() {
defer close(out)
-
for p := range in {
proj, err := NewProject(p)
if err != nil {
@@ -493,7 +444,6 @@ func merge(ins ...<-chan string) <-chan string {
)
wg.Add(len(ins))
-
for _, in := range ins {
go func(in <-chan string) {
defer wg.Done()