├── .gitignore
├── LICENSE.txt
├── README.md
├── Timer.alfredworkflow
├── Timer
├── LICENSE.txt
├── alarm.m4a
├── icon.png
├── info.plist
├── kudos.plist
└── timer.py
└── screenshot.png
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 |
3 | # C extensions
4 | *.so
5 |
6 | # Packages
7 | *.egg
8 | *.egg-info
9 | dist
10 | build
11 | eggs
12 | parts
13 | bin
14 | var
15 | sdist
16 | develop-eggs
17 | .installed.cfg
18 | lib
19 | lib64
20 |
21 | # Installer logs
22 | pip-log.txt
23 |
24 | # Unit test / coverage reports
25 | .coverage
26 | .tox
27 | nosetests.xml
28 |
29 | # Translations
30 | *.mo
31 |
32 | # Mr Developer
33 | .mr.developer.cfg
34 | .project
35 | .pydevproject
36 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Daniel Bader
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [A countdown timer extension for Alfred.app](http://dbader.org/blog/alfred-timer-extension)
2 | A simple countdown timer command for [Alfred.app](http://www.alfredapp.com/) that uses Mountain Lion User Notifications.
3 |
4 | 
5 |
6 | The extension is described in closer detail on my [blog](http://dbader.org/blog/alfred-timer-extension).
7 |
8 | ## Benefits
9 | - Helps you make great tea.
10 | - Solves your [Pomodoro](http://en.wikipedia.org/wiki/Pomodoro_Technique) needs.
11 | - Uses Mountain Lion's User Notifications to tell you when time's up.
12 | - Plays a non-intrusive alarm sound.
13 | - Allows you to run multiple timers at the same time.
14 | - Allows you to add an optional label to the timer, e.g. "Laundry is done!". Thanks to [Alexander Lehmann](http://rudairandamacha.blogspot.de) for the suggestion.
15 | - Shows you how to write Alfred extensions in Python.
16 |
17 | ## Installation
18 | - Download [Timer.alfredworkflow](https://github.com/dbader/alfred-countdown-timer/blob/master/Timer.alfredworkflow?raw=true)
19 | - Double-click `Timer.alfredworkflow` to install the extension.
20 |
21 | To use this extension you need [Alfred.app](http://www.alfredapp.com/) for macOS and the [Alfred PowerPack](http://www.alfredapp.com/powerpack/).
22 |
23 | ## Usage
24 | - The general syntax is `timer [minutes] [optional:title]`
25 | - `timer 5` sets a countdown timer that goes off after 5 minutes.
26 | - `timer 0:30` or `timer 0.5` sets a timer that goes off after 30 seconds.
27 | - `timer 40 Laundry is done!` adds an optional title to the timer.
28 | - `timer` displays usage information.
29 |
30 | ## Meta
31 |
32 | Daniel Bader – [@dbader_org](https://twitter.com/dbader_org) – mail@dbader.org
33 |
34 | Distributed under the MIT license. See ``LICENSE.txt`` for more information.
35 |
36 | https://github.com/dbader/alfred-countdown-timer
37 |
--------------------------------------------------------------------------------
/Timer.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbader/alfred-countdown-timer/3f08bab53c5cbbb99dc7a707eefbdf23bd733db7/Timer.alfredworkflow
--------------------------------------------------------------------------------
/Timer/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The icon is from ~MazeNL77's "nx10" icon set.
2 |
3 | The sound is "Ice" from Nitram+Nunca's awesome "Minutes" dashboard widget.
4 | Sadly, the company seems to have vanished. I love this sound and use
5 | it on all my devices as an alarm sound. So Nitram+Nunca, I hope it is okay
6 | for you that I include your sound file. If not please contact me and I will
7 | take it offline.
8 |
9 | The rest of the project is released under the MIT license.
10 |
11 |
12 | Copyright (c) 2013 Daniel Bader (http://dbader.org)
13 |
14 | Permission is hereby granted, free of charge, to any person obtaining a copy
15 | of this software and associated documentation files (the "Software"), to deal
16 | in the Software without restriction, including without limitation the rights
17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 | copies of the Software, and to permit persons to whom the Software is
19 | furnished to do so, subject to the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be included in
22 | all copies or substantial portions of the Software.
23 |
24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 | THE SOFTWARE.
31 |
--------------------------------------------------------------------------------
/Timer/alarm.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbader/alfred-countdown-timer/3f08bab53c5cbbb99dc7a707eefbdf23bd733db7/Timer/alarm.m4a
--------------------------------------------------------------------------------
/Timer/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbader/alfred-countdown-timer/3f08bab53c5cbbb99dc7a707eefbdf23bd733db7/Timer/icon.png
--------------------------------------------------------------------------------
/Timer/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | action
6 |
7 | category
8 | SCRIPTS
9 | command
10 | python timer.py {query}
11 | disabled
12 |
13 | escapedollar
14 |
15 | escapequery
16 |
17 | escapequerybackquotes
18 |
19 | escapequerybrackets
20 |
21 | escapequeryquotes
22 |
23 | escapequerysemicolons
24 |
25 | growloutput
26 |
27 | growloutputsticky
28 |
29 | keyword
30 | timer
31 | logging
32 |
33 | multifileargs
34 |
35 | parameter
36 | 0
37 | silent
38 |
39 | subtitle
40 | Example: timer 5:30
41 | title
42 | Start a countdown timer
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Timer/kudos.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | Daniel Bader
7 | website
8 | http://dbader.org/blog/alfred-timer-extension
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Timer/timer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """
4 | A simple countdown timer command for Alfred.app that
5 | uses Mountain Lion User Notifications.
6 |
7 | Copyright (c) 2013 Daniel Bader (http://dbader.org)
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in
17 | all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | THE SOFTWARE.
26 | """
27 |
28 | import json
29 | import os
30 | import subprocess
31 | import sys
32 | import time
33 |
34 |
35 | def main(argv):
36 | interval = parse_time(argv)
37 | minutes = interval / 60
38 | seconds = interval % 60
39 |
40 | label = ' '.join(argv[1:])
41 | title = 'Timer started' + (': %s' % label.capitalize() if label else '.')
42 |
43 | if minutes and seconds:
44 | notify(title, "I'll notify you in %i:%.2i." % (minutes, seconds))
45 | passed_time = '%i:%.2i have passed.' % (minutes, seconds)
46 | elif minutes:
47 | notify(title, "I'll notify you in %i %s." % (minutes,
48 | 'minute' if minutes == 1 else 'minutes'))
49 | passed_time = '%i %s passed.' % (minutes,
50 | 'minute has' if minutes == 1 else 'minutes have')
51 | else:
52 | notify(title, "I'll notify you in %i seconds." % seconds)
53 | passed_time = '%i seconds have passed.' % seconds
54 |
55 | time.sleep(interval)
56 | notify("Time's up" + (': %s' % label.capitalize() if label else '.'),
57 | passed_time)
58 | play_sound('alarm.m4a')
59 |
60 |
61 | def parse_time(argv):
62 | """Parse and return the desired countdown duration in seconds from
63 | the commandline.
64 | """
65 | try:
66 | duration = argv[0]
67 | if ':' in duration:
68 | # Minutes and seconds, e.g. "5:30"
69 | minutes, seconds = duration.split(':')
70 | return int(minutes) * 60 + int(seconds)
71 | else:
72 | # Just minutes, e.g. "1.5"
73 | return int(float(duration) * 60)
74 | except:
75 | show_usage()
76 | sys.exit(1)
77 |
78 |
79 | def show_usage():
80 | notify('Timer usage', 'timer [minutes] [optional: title]')
81 |
82 |
83 | def notify(title, text=None):
84 | subprocess.Popen([
85 | 'osascript',
86 | '-e',
87 | f'''tell application id "com.runningwithcrayons.Alfred" to run trigger "notification" in workflow "org.dbader.alfred.timer" with argument "{title}|||{text}"'''
88 | ])
89 |
90 |
91 | def play_sound(filename):
92 | """Play the given sound file using the `afplay` command line utility."""
93 | subprocess.Popen(['afplay', filename])
94 |
95 |
96 | if __name__ == '__main__':
97 | if len(sys.argv) > 1:
98 | argv = sys.argv[1].split()
99 | else:
100 | argv = []
101 | main(argv)
102 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbader/alfred-countdown-timer/3f08bab53c5cbbb99dc7a707eefbdf23bd733db7/screenshot.png
--------------------------------------------------------------------------------