Skip to content

Commit

Permalink
Move to kingpin
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita Voloboev committed Feb 8, 2018
1 parent 2f578bc commit e34f02a
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 120 deletions.
167 changes: 48 additions & 119 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,154 +1,83 @@
package main

import (
"encoding/csv"
"log"
"os"
"os/exec"
"regexp"
"strings"
"fmt"

"github.com/alecthomas/kingpin"
"github.com/deanishe/awgo"
"github.com/deanishe/awgo/update"
"github.com/docopt/docopt-go"
)

// Name of the background job that checks for updates
const updateJobName = "checkForUpdate"

var usage = `alfred-web-searches [search|check] [<query>]
Search through any website on Earth.
Usage:
alfred-web-searches search [<query>]
alfred-web-searches check
alfred-web-searches -h
Options:
-h, --help Show this message and exit.
`

var (
// Icons
iconAvailable = &aw.Icon{Value: "icons/update.png"}
redditIcon = &aw.Icon{Value: "icons/reddit.png"}
githubIcon = &aw.Icon{Value: "icons/github.png"}
translateIcon = &aw.Icon{Value: "icons/translate.png"}
forumsIcon = &aw.Icon{Value: "icons/forums.png"}
stackIcon = &aw.Icon{Value: "icons/stack.png"}
docIcon = &aw.Icon{Value: "icons/doc.png"}
updateAvailable = &aw.Icon{Value: "icons/update-available.png"}
redditIcon = &aw.Icon{Value: "icons/reddit.png"}
githubIcon = &aw.Icon{Value: "icons/github.png"}
translateIcon = &aw.Icon{Value: "icons/translate.png"}
forumsIcon = &aw.Icon{Value: "icons/forums.png"}
stackIcon = &aw.Icon{Value: "icons/stack.png"}
docIcon = &aw.Icon{Value: "icons/doc.png"}

repo = "nikitavoloboev/alfred-web-searches"
wf *aw.Workflow
)
// Kingpin and script options
app *kingpin.Application

func init() {
wf = aw.New(update.GitHub(repo))
}
// Application commands
searchCmd *kingpin.CmdClause
updateCmd *kingpin.CmdClause

func run() {
query string

// Pass wf.Args() to docopt because our update logic relies on
// AwGo's magic actions.
args, _ := docopt.Parse(usage, wf.Args(), true, wf.Version(), false, true)

// Alternate action: get available releases from remote
if args["check"] != false {
wf.TextErrors = true
log.Println("checking for updates...")
if err := wf.CheckForUpdate(); err != nil {
wf.FatalError(err)
}
return
}
repo = "nikitavoloboev/alfred-web-searches"

var query string
if args["<query>"] != nil {
query = args["<query>"].(string)
}
// Workflow stuff
wf *aw.Workflow
)

log.Printf("query=%s", query)
// Mostly sets up kingpin commands
func init() {
wf = aw.New(update.GitHub(repo), aw.HelpURL(repo+"/issues"))

// Call self with "check" command if an update is due and a
// check job isn't already running.
if wf.UpdateCheckDue() && !aw.IsRunning(updateJobName) {
log.Println("running update check in background...")
cmd := exec.Command("./alfred-web-searches", "check")
if err := aw.RunInBackground(updateJobName, cmd); err != nil {
log.Printf("error starting update check: %s", err)
}
}
app = kingpin.New("ask", "Search websites.")

if query == "" { // Only show update status if query is empty
// Send update status to Alfred
if wf.UpdateAvailable() {
wf.NewItem("Update Available!").
Subtitle("↩ to install").
Autocomplete("workflow:update").
Valid(false).
Icon(iconAvailable)
}
}
// Update command
updateCmd = app.Command("update", "Check for new workflow version.").Alias("u")

links := parseCSV()

var re1 = regexp.MustCompile(`.: `)
var re2 = regexp.MustCompile(`(all)`)

for key, value := range links {
if strings.Contains(key, "r: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(redditIcon).Var("RECENT", re2.ReplaceAllString(value, `week`)).Subtitle("⌃ = Search past week")
} else if strings.Contains(key, "d: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(docIcon)
} else if strings.Contains(key, "g: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(githubIcon)
} else if strings.Contains(key, "s: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(stackIcon)
} else if strings.Contains(key, "f: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(forumsIcon)
} else if strings.Contains(key, "t: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(translateIcon)
} else {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key)
}
}
// Commands using query
searchCmd = app.Command("search", "Search websites.").Alias("s")

if query != "" {
wf.Filter(query)
// Common options
for _, cmd := range []*kingpin.CmdClause{
searchCmd,
} {
cmd.Flag("query", "Search query.").Short('q').StringVar(&query)
}

wf.WarnEmpty("No matching items", "Try a different query?")
wf.SendFeedback()
}

// Parses CSV of links and arguments
func parseCSV() map[string]string {
func run() {
var err error

// load values from file to a hash map
f, err := os.Open("websites.csv")
cmd, err := app.Parse(wf.Args())
if err != nil {
panic(err)
wf.FatalError(err)
}
defer f.Close()

r := csv.NewReader(f)

records, err := r.ReadAll()
if err != nil {
log.Fatal(err)
switch cmd {
case searchCmd.FullCommand():
err = doSearch()
case updateCmd.FullCommand():
err = doUpdate()
default:
err = fmt.Errorf("Uknown command: %s", cmd)
}

// holds user's search arguments and an appropriate search URL
links := make(map[string]string)

for _, record := range records {
links[record[0]] = record[1]
// Check for update
if err == nil && cmd != updateCmd.FullCommand() {
err = checkForUpdate()
}

return links

if err != nil {
wf.FatalError(err)
}
}

func main() {
Expand Down
76 changes: 76 additions & 0 deletions search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"encoding/csv"
"log"
"os"
"regexp"
"strings"
)

// doSearch makes a search for websites and returns results to Alfred.
func doSearch() error {
showUpdateStatus()

log.Printf("query=%s", query)

links := parseCSV()

var re1 = regexp.MustCompile(`.: `)
var re2 = regexp.MustCompile(`(all)`)

for key, value := range links {
if strings.Contains(key, "r: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(redditIcon).Var("RECENT", re2.ReplaceAllString(value, `week`)).Subtitle("⌃ = Search past week")
} else if strings.Contains(key, "d: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(docIcon)
} else if strings.Contains(key, "g: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(githubIcon)
} else if strings.Contains(key, "s: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(stackIcon)
} else if strings.Contains(key, "f: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(forumsIcon)
} else if strings.Contains(key, "t: ") {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key).Icon(translateIcon)
} else {
wf.NewItem(key).Valid(true).Var("URL", value).Var("ARG", re1.ReplaceAllString(key, ``)).UID(key)
}
}

if query != "" {
wf.Filter(query)
}

wf.WarnEmpty("No matching items", "Try a different query?")
wf.SendFeedback()
return nil
}

// parseCSV parses CSV for links and arguments.
func parseCSV() map[string]string {
var err error

// Load values from file to a hash map
f, err := os.Open("websites.csv")
if err != nil {
panic(err)
}
defer f.Close()

r := csv.NewReader(f)

records, err := r.ReadAll()
if err != nil {
log.Fatal(err)
}

// Holds user's search arguments and an appropriate search URL
links := make(map[string]string)

for _, record := range records {
links[record[0]] = record[1]
}

return links

}
42 changes: 42 additions & 0 deletions update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"log"
"os"
"os/exec"

aw "github.com/deanishe/awgo"
)

// doUpdate checks for a newer version of the workflow.
func doUpdate() error {
log.Println("Checking for update...")
return wf.CheckForUpdate()
}

// checkForUpdate runs "./alsf update" in the background if an update check is due.
func checkForUpdate() error {
if !wf.UpdateCheckDue() || aw.IsRunning("update") {
return nil
}
cmd := exec.Command(os.Args[0], "update")
return aw.RunInBackground("update", cmd)
}

// showUpdateStatus adds an "update available!" message to Script Filters if an update is available
// and query is empty.
func showUpdateStatus() {
if query != "" {
return
}

if wf.UpdateAvailable() {
wf.Configure(aw.SuppressUIDs(true))
log.Println("Update available!")
wf.NewItem("An update is available!").
Subtitle("⇥ or ↩ to install update").
Valid(false).
Autocomplete("workflow:update").
Icon(updateAvailable)
}
}
Binary file modified workflow/alfred-web-searches
Binary file not shown.
2 changes: 1 addition & 1 deletion workflow/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@
<key>runningsubtext</key>
<string></string>
<key>script</key>
<string>./alfred-web-searches search "$1"</string>
<string>./alfred-web-searches search -q "$1"</string>
<key>scriptargtype</key>
<integer>1</integer>
<key>scriptfile</key>
Expand Down

0 comments on commit e34f02a

Please sign in to comment.