├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── feature_request.md
│ └── question.md
└── PULL_REQUEST_TEMPLATE.md
├── contributing.md
├── go.mod
├── license
├── main.go
├── modd.conf
├── readme.md
├── search.go
├── update.go
└── workflow
├── alfred-awesome-lists
├── icon.png
├── icons
└── update-available.png
└── info.plist
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug 🐞
3 | about: Something isn't working as expected?
4 | labels: bug
5 | ---
6 |
7 | ### Bug 🐞
8 |
9 |
10 |
11 |
12 | ### Steps to Reproduce:
13 |
14 | 1.
15 | 2.
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature ✨
3 | about: Suggest new idea for the project
4 | labels: enhancement
5 | ---
6 |
7 | ### Feature ✨
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question 🤔
3 | about: Usage question or discussion
4 | labels: question
5 | ---
6 |
7 | ### Question 🤔
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Summary
2 |
3 |
4 |
5 |
6 | ### Changes
7 |
8 | -
9 |
10 |
11 | ### Notes
12 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thank you for taking the time to contribute! ♥️ You can:
4 |
5 | - Submit [bug reports or feature requests](../../issues/new/choose). Contribute to discussions. Fix [open issues](../../issues).
6 | - Improve docs, the code and more! Any idea is welcome.
7 |
8 | ## Run project
9 |
10 | The workflow is written in [Go](https://golang.org/) and uses [AwGo](https://github.com/deanishe/awgo) library for all Alfred related things.
11 |
12 | It uses [modd](https://github.com/cortesi/modd) and [Alfred command](https://godoc.org/github.com/jason0x43/go-alfred/alfred) to ease its development.
13 |
14 | 1. Clone repo
15 | 2. Run `alfred link` (makes symbolic link of [`workflow`](workflow) directory)
16 | 3. Run `modd` (starts a process that automatically builds the workflow with `alfred build` on any changes you make to `.go` files, this builds and places a binary inside [`workflow`](workflow) directory.)
17 | 4. Make changes to code or modify Alfred objects to do what you want! Open debugger in Alfred or run the workflow with `workflow:log` passed in as argument to see the logs Alfred produces.
18 |
19 | 
20 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/nikitavoloboev/alfred-awesome-lists
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/deanishe/awgo v0.24.0
7 | github.com/nikitavoloboev/markdown-parser v0.0.0-20200514190103-adb11a66522a
8 | )
9 |
10 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Nikita (nikiv.dev)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | // Command awesome is Alfred 3 workflow for quickly navigating GitHub Awesome lists.
2 | package main
3 |
4 | import (
5 | "log"
6 | "time"
7 |
8 | aw "github.com/deanishe/awgo"
9 | "github.com/deanishe/awgo/update"
10 | )
11 |
12 | var (
13 | // Icons
14 | iconUpdate = &aw.Icon{Value: "icons/update-available.png"}
15 |
16 | query string
17 |
18 | repo = "nikitavoloboev/alfred-awesome-lists"
19 |
20 | // Workflow stuff
21 | wf *aw.Workflow
22 | )
23 |
24 | func init() {
25 | wf = aw.New(update.GitHub(repo), aw.HelpURL(repo+"/issues"))
26 | }
27 |
28 | func run() {
29 | reload := func() (interface{}, error) {
30 | listIndex, err := searchAwesomeLists()
31 |
32 | if err != nil {
33 | log.Fatal(err)
34 | }
35 |
36 | var lists []List
37 | for _, list := range listIndex {
38 | lists = append(lists, list)
39 | }
40 |
41 | return lists, err
42 | }
43 |
44 | // Cache Awesome lists for 6 hours
45 | maxCache := 6 * time.Hour
46 | var lists []List
47 | err := wf.Cache.LoadOrStoreJSON("awesomeLists", maxCache, reload, &lists)
48 |
49 | if err != nil {
50 | wf.Fatal(err.Error())
51 | }
52 |
53 | for _, list := range lists {
54 | wf.NewItem(list.Name).UID(list.UID).Valid(true).Arg(list.URL)
55 | }
56 |
57 | args := wf.Args()
58 | var searchQuery string
59 | if len(args) > 0 {
60 | searchQuery = args[0]
61 | }
62 |
63 | if searchQuery == "" {
64 | wf.WarnEmpty("No matching items", "Try a different query?")
65 | } else {
66 | wf.Filter(searchQuery)
67 | wf.WarnEmpty("No matching items", "Try a different query?")
68 | }
69 |
70 | wf.SendFeedback()
71 | }
72 |
73 | func main() {
74 | wf.Run(run)
75 | }
76 |
--------------------------------------------------------------------------------
/modd.conf:
--------------------------------------------------------------------------------
1 | **/*.go {
2 | prep: alfred build
3 | }
4 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Alfred Awesome Lists
2 |
3 | > [Alfred](https://www.alfredapp.com/) workflow to search [awesome lists](https://github.com/sindresorhus/awesome)
4 |
5 |
6 |
7 | ## Install
8 |
9 | Download workflow from [GitHub releases](../../releases/latest).
10 |
11 | See [here](https://github.com/deanishe/awgo/wiki/Catalina) for instructions on fixing permissions in macOS refusing to run Go binary.
12 |
13 | ## Contribute
14 |
15 | Always open to useful ideas or fixes in form of issues or PRs.
16 |
17 | Can [open new issue](../../issues/new/choose) (search [existing issues](../../issues) first) or [start discussion](../../discussions).
18 |
19 | It's okay to submit draft PR as you can get help along the way to make it merge ready.
20 |
21 | Join [Discord](https://discord.com/invite/TVafwaD23d) for more indepth discussions on this repo and [others](https://github.com/nikitavoloboev#src).
22 |
23 | ### 🖤
24 |
25 | [Support on GitHub](https://github.com/sponsors/nikitavoloboev) or look into [other projects](https://nikiv.dev/projects).
26 |
27 | [](https://discord.com/invite/TVafwaD23d) [](https://twitter.com/nikitavoloboev) [](https://nikiv.dev)
28 |
--------------------------------------------------------------------------------
/search.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | parser "github.com/nikitavoloboev/markdown-parser"
7 | )
8 |
9 | // List holds an awesome list.
10 | type List struct {
11 | UID string
12 | Name string
13 | URL string
14 | }
15 |
16 | func searchAwesomeLists() (map[string]List, error) {
17 | showUpdateStatus()
18 |
19 | log.Printf("query=%s", query)
20 |
21 | // Get the list from GitHub
22 | urls, err := parser.ParseMarkdownURL("https://raw.githubusercontent.com/sindresorhus/awesome/main/readme.md")
23 | if err != nil {
24 | log.Println("Error parsing links")
25 | }
26 |
27 | links := make(map[string]List)
28 |
29 | for name, url := range urls {
30 | links[url] = List{
31 | UID: name,
32 | Name: name,
33 | URL: url,
34 | }
35 | }
36 |
37 | return links, nil
38 | }
39 |
--------------------------------------------------------------------------------
/update.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | "os/exec"
7 |
8 | aw "github.com/deanishe/awgo"
9 | )
10 |
11 | // doUpdate checks for a newer version of the workflow.
12 | func doUpdate() error {
13 | log.Println("Checking for update...")
14 | return wf.CheckForUpdate()
15 | }
16 |
17 | // checkForUpdate runs "./alsf update" in the background if an update check is due.
18 | func checkForUpdate() error {
19 | if !wf.UpdateCheckDue() || wf.IsRunning("update") {
20 | return nil
21 | }
22 | cmd := exec.Command(os.Args[0], "update")
23 | return wf.RunInBackground("update", cmd)
24 | }
25 |
26 | // showUpdateStatus adds an "update available!" message to Script Filters if an update is available
27 | // and query is empty.
28 | func showUpdateStatus() {
29 | if query != "" {
30 | return
31 | }
32 |
33 | if wf.UpdateAvailable() {
34 | wf.Configure(aw.SuppressUIDs(true))
35 | log.Println("Update available!")
36 | wf.NewItem("An update is available!").
37 | Subtitle("⇥ or ↩ to install update").
38 | Valid(false).
39 | Autocomplete("workflow:update").
40 | Icon(&aw.Icon{Value: "icons/update-available.png"})
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/workflow/alfred-awesome-lists:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikitavoloboev/alfred-awesome-lists/7647cab3f1920bc2025d4c8ab5a7717237c8680b/workflow/alfred-awesome-lists
--------------------------------------------------------------------------------
/workflow/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikitavoloboev/alfred-awesome-lists/7647cab3f1920bc2025d4c8ab5a7717237c8680b/workflow/icon.png
--------------------------------------------------------------------------------
/workflow/icons/update-available.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikitavoloboev/alfred-awesome-lists/7647cab3f1920bc2025d4c8ab5a7717237c8680b/workflow/icons/update-available.png
--------------------------------------------------------------------------------
/workflow/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | nikivi.awesome.lists
7 | category
8 | Mine
9 | connections
10 |
11 | 09B97908-9A52-4275-855F-41A8C354E5B8
12 |
13 |
14 | destinationuid
15 | 185DBDA9-7F2E-40C9-A8C6-C84B737806CF
16 | modifiers
17 | 0
18 | modifiersubtext
19 |
20 | vitoclose
21 |
22 |
23 |
24 | destinationuid
25 | 7BED6B3C-632D-4E17-B07C-6411AC259F94
26 | modifiers
27 | 1048576
28 | modifiersubtext
29 | Edit list
30 | vitoclose
31 |
32 |
33 |
34 | destinationuid
35 | 37F1E515-5CF8-4276-8A8A-305D169D7BC9
36 | modifiers
37 | 524288
38 | modifiersubtext
39 | View contribution guidelines
40 | vitoclose
41 |
42 |
43 |
44 | 37F1E515-5CF8-4276-8A8A-305D169D7BC9
45 |
46 |
47 | destinationuid
48 | C4DD0986-C311-4550-9E12-F754F61F30BA
49 | modifiers
50 | 0
51 | modifiersubtext
52 |
53 | vitoclose
54 |
55 |
56 |
57 | 7BED6B3C-632D-4E17-B07C-6411AC259F94
58 |
59 |
60 | destinationuid
61 | C14883EE-9E77-4120-B375-97E42BD808B6
62 | modifiers
63 | 0
64 | modifiersubtext
65 |
66 | vitoclose
67 |
68 |
69 |
70 | B22AABA1-E682-48A2-A417-B8D983A8867F
71 |
72 |
73 | destinationuid
74 | EE1712A5-3B88-4D36-ADDE-E366B0DD8FC4
75 | modifiers
76 | 0
77 | modifiersubtext
78 |
79 | vitoclose
80 |
81 |
82 |
83 | C14883EE-9E77-4120-B375-97E42BD808B6
84 |
85 |
86 | destinationuid
87 | C37D87EC-752A-4D60-A7C8-20E488267314
88 | modifiers
89 | 0
90 | modifiersubtext
91 |
92 | vitoclose
93 |
94 |
95 |
96 | C4DD0986-C311-4550-9E12-F754F61F30BA
97 |
98 |
99 | destinationuid
100 | 633B3C4A-0415-4EA4-A080-FF110E6CA2D9
101 | modifiers
102 | 0
103 | modifiersubtext
104 |
105 | vitoclose
106 |
107 |
108 |
109 | EE1712A5-3B88-4D36-ADDE-E366B0DD8FC4
110 |
111 |
112 | destinationuid
113 | 09B97908-9A52-4275-855F-41A8C354E5B8
114 | modifiers
115 | 0
116 | modifiersubtext
117 |
118 | vitoclose
119 |
120 |
121 |
122 |
123 | createdby
124 | Nikita Voloboev
125 | description
126 | Search awesome lists
127 | disabled
128 |
129 | name
130 | Awesome lists
131 | objects
132 |
133 |
134 | config
135 |
136 | browser
137 |
138 | spaces
139 |
140 | url
141 | {query}
142 | utf8
143 |
144 |
145 | type
146 | alfred.workflow.action.openurl
147 | uid
148 | 185DBDA9-7F2E-40C9-A8C6-C84B737806CF
149 | version
150 | 1
151 |
152 |
153 | config
154 |
155 | browser
156 |
157 | spaces
158 |
159 | url
160 | {var:link}
161 | utf8
162 |
163 |
164 | type
165 | alfred.workflow.action.openurl
166 | uid
167 | C37D87EC-752A-4D60-A7C8-20E488267314
168 | version
169 | 1
170 |
171 |
172 | config
173 |
174 | triggerid
175 | search lists
176 |
177 | type
178 | alfred.workflow.trigger.external
179 | uid
180 | B22AABA1-E682-48A2-A417-B8D983A8867F
181 | version
182 | 1
183 |
184 |
185 | config
186 |
187 | concurrently
188 |
189 | escaping
190 | 102
191 | script
192 | query=$1
193 |
194 | echo -n "${query//}"
195 | scriptargtype
196 | 1
197 | scriptfile
198 |
199 | type
200 | 0
201 |
202 | type
203 | alfred.workflow.action.script
204 | uid
205 | 7BED6B3C-632D-4E17-B07C-6411AC259F94
206 | version
207 | 2
208 |
209 |
210 | config
211 |
212 | alfredfiltersresults
213 |
214 | alfredfiltersresultsmatchmode
215 | 0
216 | argumenttreatemptyqueryasnil
217 |
218 | argumenttrimmode
219 | 0
220 | argumenttype
221 | 1
222 | escaping
223 | 102
224 | keyword
225 | awe
226 | queuedelaycustom
227 | 3
228 | queuedelayimmediatelyinitially
229 |
230 | queuedelaymode
231 | 0
232 | queuemode
233 | 1
234 | runningsubtext
235 | Loading...
236 | script
237 | ./alfred-awesome-lists "$1"
238 | scriptargtype
239 | 1
240 | scriptfile
241 |
242 | subtext
243 |
244 | title
245 | Search Awesome Lists
246 | type
247 | 0
248 | withspace
249 |
250 |
251 | type
252 | alfred.workflow.input.scriptfilter
253 | uid
254 | 09B97908-9A52-4275-855F-41A8C354E5B8
255 | version
256 | 3
257 |
258 |
259 | config
260 |
261 | json
262 | {
263 | "alfredworkflow" : {
264 | "arg" : "{query}",
265 | "config" : {
266 | "title" : "",
267 | "runningsubtext" : "",
268 | "subtext" : ""
269 | },
270 | "variables" : {
271 | }
272 | }
273 | }
274 |
275 | type
276 | alfred.workflow.utility.json
277 | uid
278 | EE1712A5-3B88-4D36-ADDE-E366B0DD8FC4
279 | version
280 | 1
281 |
282 |
283 | config
284 |
285 | argument
286 | {query}
287 | passthroughargument
288 |
289 | variables
290 |
291 | link
292 | {query}/edit/master/README.md
293 |
294 |
295 | type
296 | alfred.workflow.utility.argument
297 | uid
298 | C14883EE-9E77-4120-B375-97E42BD808B6
299 | version
300 | 1
301 |
302 |
303 | config
304 |
305 | concurrently
306 |
307 | escaping
308 | 102
309 | script
310 | query=$1
311 |
312 | echo -n "${query//}"
313 | scriptargtype
314 | 1
315 | scriptfile
316 |
317 | type
318 | 0
319 |
320 | type
321 | alfred.workflow.action.script
322 | uid
323 | 37F1E515-5CF8-4276-8A8A-305D169D7BC9
324 | version
325 | 2
326 |
327 |
328 | config
329 |
330 | browser
331 |
332 | spaces
333 |
334 | url
335 | {var:link}
336 | utf8
337 |
338 |
339 | type
340 | alfred.workflow.action.openurl
341 | uid
342 | 633B3C4A-0415-4EA4-A080-FF110E6CA2D9
343 | version
344 | 1
345 |
346 |
347 | config
348 |
349 | argument
350 | {query}
351 | passthroughargument
352 |
353 | variables
354 |
355 | link
356 | {query}/blob/master/CONTRIBUTING.md
357 |
358 |
359 | type
360 | alfred.workflow.utility.argument
361 | uid
362 | C4DD0986-C311-4550-9E12-F754F61F30BA
363 | version
364 | 1
365 |
366 |
367 | readme
368 | Details on how to use this workflow are found in the GitHub repo attached to the workflow.
369 |
370 | Double click this workflow in sidebar -> Open website.
371 |
372 | Post any issues and feature requests you have there. 💜
373 | uidata
374 |
375 | 09B97908-9A52-4275-855F-41A8C354E5B8
376 |
377 | note
378 | Seach Awesome Lists
379 | xpos
380 | 245
381 | ypos
382 | 160
383 |
384 | 185DBDA9-7F2E-40C9-A8C6-C84B737806CF
385 |
386 | xpos
387 | 465
388 | ypos
389 | 30
390 |
391 | 37F1E515-5CF8-4276-8A8A-305D169D7BC9
392 |
393 | xpos
394 | 465
395 | ypos
396 | 300
397 |
398 | 633B3C4A-0415-4EA4-A080-FF110E6CA2D9
399 |
400 | note
401 | View contribution guidelines
402 | xpos
403 | 725
404 | ypos
405 | 300
406 |
407 | 7BED6B3C-632D-4E17-B07C-6411AC259F94
408 |
409 | xpos
410 | 465
411 | ypos
412 | 160
413 |
414 | B22AABA1-E682-48A2-A417-B8D983A8867F
415 |
416 | xpos
417 | 10
418 | ypos
419 | 160
420 |
421 | C14883EE-9E77-4120-B375-97E42BD808B6
422 |
423 | xpos
424 | 635
425 | ypos
426 | 190
427 |
428 | C37D87EC-752A-4D60-A7C8-20E488267314
429 |
430 | note
431 | Edit Awesome list
432 | xpos
433 | 725
434 | ypos
435 | 160
436 |
437 | C4DD0986-C311-4550-9E12-F754F61F30BA
438 |
439 | xpos
440 | 635
441 | ypos
442 | 330
443 |
444 | EE1712A5-3B88-4D36-ADDE-E366B0DD8FC4
445 |
446 | xpos
447 | 160
448 | ypos
449 | 190
450 |
451 |
452 | version
453 | 1.2
454 | webaddress
455 | https://github.com/nikitavoloboev/alfred-awesome-lists
456 |
457 |
458 |
--------------------------------------------------------------------------------