paradeiser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 514aada5139d88a73f29e87af2fa9e05a83abcf5
4
+ data.tar.gz: bba7a583a6f59e396bf2b97b303a1298ed0d0558
5
+ SHA512:
6
+ metadata.gz: 3df87f14df263ac7abaa64e3a3919766e55b57d2859097d097cdf90d3b630ecf8126d03169ad897a46beb3fbd3b2555a76ee6c5d68c2bc5f5dffeb5781bb549c
7
+ data.tar.gz: 3c52d742719e3efae7ec2ccbf532a5503a40e071277ce8a51a52a056713362007bd68c0d2dfd7fdaa0b3844b4675bf9a93211410cf355d9240b178021793eea2
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,7 @@
1
+ # How to contribute
2
+
3
+ 1. Fork it
4
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
5
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
6
+ 4. Push to the branch (`git push origin my-new-feature`)
7
+ 5. Create new Pull Request
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in paradeiser.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Nicholas E. Rabenau
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,287 @@
1
+ # Paradeiser
2
+
3
+ _Please note that this project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. As such, Paradeiser actually provides much less functionality than it is described here. Once a major milestone is reached, this README will be updated to reflect the actual status._
4
+
5
+ Paradeiser is a tool for the [Pomodoro Technique](http://www.pomodorotechnique.com/). It keeps track of the current pomodoro and assists the user in managing active and past pomodori:
6
+
7
+ * Records finished and cancelled pomodori as well as internal and external interruptions and other events
8
+ * Keeps track of the timer for the active pomodoro and the break
9
+ * Provides out-of-the-box reports that show details about finished and cancelled pomodori
10
+ * Shows information about breaks and interruptions
11
+
12
+ Paradeiser itself is not concerned with the actual management of tasks. There are plenty of tools for that; the author prefers [TaskWarrior](http://taskwarrior.org/).
13
+
14
+ ## Installation
15
+
16
+ $ gem install paradeiser
17
+
18
+ ## Usage
19
+
20
+ ### Start a new pomodoro
21
+
22
+ $ pom start
23
+
24
+ There can only be one active pomodoro or break at a time per user. Therefore, repeatedly calling start will have no effect (other than a warning message).
25
+
26
+ If a break is still active, it will be stopped before the new pomodoro is started.
27
+
28
+ Note that for a single user account (technically, for a `~/.paradeiser` directory), not more than one pomodoro [xor](http://en.wikipedia.org/wiki/Xor) one break can be active at any given time.
29
+
30
+ ### Finish the pomodoro
31
+
32
+ $ pom finish
33
+ $ pom stop # alias
34
+
35
+ If a pomodoro is active, it will be marked as successful after stopping it, regardless of whether the 25 minutes are over or not. If a break is active, it will be stopped. If neither a pomodoro nor or break are active, a warning message will be printed.
36
+
37
+ ### Record an interruption of the current pomodoro
38
+
39
+ $ pom interrupt --external Phone call from boss
40
+ $ pom interrupt --internal "Couldn't stay away from Twitter"
41
+
42
+ Remaining arguments, if present, will be added to the interrupt as annotation. If no pomodoro is active or interrupted (status is idle or paused), the command will throw an error.
43
+
44
+ ### Resume the pomodoro after an interruption
45
+
46
+ $ pom resume
47
+
48
+ If there is no interrupted pomodoro, the command will throw an error.
49
+
50
+ ### Start a break
51
+
52
+ $ pom break [--short | --long]
53
+
54
+ If a pomodoro is active, it will be stopped. By default the break will be five minutes long. After four pomodori within a day, the break will be 30 minutes long. This can be overridden with `--short` or `--long`, with an optional argument value that determines the lenght of the break in minutes (e.g. `pom break --short=10`).
55
+
56
+ There is no public command to stop a break. Either a new pomodoro is started, which will implicitely stop the break, of the break ends naturally because it is over.
57
+
58
+ ### Annotate a pomodoro
59
+
60
+ $ pom annotate This was intense, but I am happy about the work I finished.
61
+
62
+ The annotation will be added to the active or, if none is active, to the most recently finished or cancelled pomodoro. Breaks cannot have annotations. If no text is given, the command throws an error.
63
+
64
+ ### Cancel the pomodoro
65
+
66
+ $ pom cancel Just couldn't concentrate anymore.
67
+ $ pom abandon # alias
68
+
69
+ It will be marked as unsuccessful (remember, a pomodoro is indivisible). If no pomodoro is active or interrupted (status is idle or paused), the command will throw an error. If a break is active, the command will do nothing except printing a warning. Remaining arguments, if present, will be added to the pomodoro as annotation.
70
+
71
+ ### Init Paradeiser
72
+
73
+ $ pom init
74
+
75
+ Creates the `~/.paradeiser` directory, an empty data store and the sample hooks in `~/.paradeiser/hooks`. If `~/.paradeiser` already exists, the command will fail with an error message.
76
+
77
+ ### Location
78
+
79
+ * List all locations
80
+
81
+ $ pom location
82
+ macbook@01:23:45:67:89:0A "Home Office"
83
+ macbook@45:01:89:0A:67:23 "Starbucks"
84
+
85
+ * Show the label of a location
86
+
87
+ $ pom location macbook@01:23:45:67:89:0A
88
+ Home Office
89
+
90
+ * Show the identifier of a location
91
+
92
+ $ pom location "Home Office"
93
+ macbook@01:23:45:67:89:0A
94
+
95
+ * Label a location
96
+
97
+ $ pom location macbook@01:23:45:67:89:0A "Your Label"
98
+
99
+ ## Low-level commands
100
+
101
+ We don't want another daemon, and `at` exists. We just tell `at` to call
102
+
103
+ pom _stop-break
104
+
105
+ when the break is over. The underscore convention marks this command as a protected one that is not to be called from outside.
106
+
107
+ So when `at` calls Paradeiser with this line, the pomodoro or break are over and Paradeiser does all the internal processing related to stopping the break (incl. calling the appropriate hooks, see below).
108
+
109
+ ## Status
110
+
111
+ $ pom status # with an active pomodoro
112
+ Pomodoro #2 started at 11:03. 14 minutes remaining.
113
+
114
+ $ pom status # with no active pomodoro and a previously finished one
115
+ No pomodoro active. Last pomodoro was finished successfully at 2013-07-16 17.07.
116
+
117
+ $ pom status # with no active pomodoro and a previously cancelled one
118
+ No pomodoro active. Last pomodoro was cancelled at 2013-07-16 17.07.
119
+
120
+ $ pom status # with no active pomodoro and an active break
121
+ Taking a 5 minute break until 2013-07-16 17.07 (4 minutes remaining).
122
+
123
+ $ pom status --short # short status (03:39 remaining in the active pomodoro or break)
124
+ 03:39
125
+
126
+ $ pom status --format %C-%M:%S # custom status format, similar to date +%Y-%m-%dT%H:%M:%S
127
+ B03:39
128
+
129
+ $ pom status --format JSON # output in JSON format
130
+ {
131
+ "status": {
132
+ "type": "break",
133
+ "length": 600,
134
+ "remaining": 363,
135
+ "start": 1373988295,
136
+ "end": 1373988595
137
+ }
138
+ }
139
+
140
+ ## Reports
141
+
142
+ $ pom report
143
+ Daily Pomodoro Report for 2013-07-16
144
+
145
+ 3 pomodori finished
146
+ 1 pomodoro cancelled
147
+ 1 internal interruptions (27 minutes in total)
148
+ 2 external interruptions (2 hours and 28 minutes in total)
149
+ 4 breaks (3 short, 1 long; 45 minutes in total)
150
+
151
+ Most efficient location: Home Office (2/0/1/0)
152
+ Least efficient location: Coffeshop (1/1/0/2)
153
+
154
+ The following locations do not have a label. Assign it with
155
+
156
+ $ pom location macbook@01:23:45:67:89:0A "Your Label"
157
+
158
+ The command defaults to `--day`. Alternative options are `--week`, `--month` or `--year`. Without a value, the argument assumes the current day / week / month / year. The first day of the period can be specified as argument, e.g. `pom report --day=2013-07-18`. The period is parsed with [Chronic](http://chronic.rubyforge.org/), which also enables symbolic values like `pom report --month="last month"`.
159
+
160
+ The efficiency is calculated (per location) from the number of successful vs. cancelled pomodori, together with the number and length of interruptions. Breaks are not counted towards efficiency.
161
+
162
+ ### Verbose Reports (timesheet)
163
+
164
+ $ pom report --verbose
165
+ TODO Ordered list of pomodori and breaks, each with annotations (like a time sheet)
166
+
167
+ The same options as for regular reports apply.
168
+
169
+ ### Exporting a Report
170
+
171
+ $ pom report --weekly --format JSON # weekly report in JSON format
172
+ {
173
+ "TODO": "Specify"
174
+ }
175
+
176
+ ## Output Policy
177
+ Paradeiser follows the [Rule of Silence](http://www.faqs.org/docs/artu/ch01s06.html#id2878450). If all goes well, a command will not print any output to `STDOUT`. Reports are exempted from this rule.
178
+
179
+ Error and warning messages always go to `STDERR`.
180
+
181
+ ## Hooks
182
+ Instead of handling tasks itself, Paradeiser integrates with external tools via hooks. Every event will attempt to find and execute an appropriate script in `~/.paradeiser/hooks/`. Sufficient information will be made available via environment variables.
183
+
184
+ `pre-` hooks will be called before the action is executed internally. If a `pre-`hook exits non-zero, paradeiser will abort the action and exit non-zero itself; indicating in a message to STDERR which hook caused the abort.
185
+
186
+ `post-` hooks will be called after the action was executed internally. The exit status of a `post`-hook will be passed through paradeiser, but it will not affect the execution of the action anymore.
187
+
188
+ ### Available Hooks
189
+
190
+ * `pre-start` is called after the `start` command was received, but before internal processing for the `start` action begins
191
+ * `post-start` is called after all interal processing for the `start` action ended
192
+ * `pre-finish` is called after the timer of the current pomodoro fired (the pomodoro is over), but before internal processing for the `finish` action begins
193
+ * `post-finish` is called after all interal processing for the `finish` action ended
194
+ * `pre-interrupt` is called after the `interrupt` command was received, but before internal action processing begins
195
+ * `post-interrupt` is called after all interal processing for the `interrupt` action ended
196
+ * `pre-cancel` is called after the `cancel` command was received, but before internal action processing begins
197
+ * `post-cancel` is called after all interal processing for the `cancel` action ended
198
+ * `pre-break` is called after the `break` command was received, but before internal processing for the `break` action begins
199
+ * `post-break` is called after the timer of the current break fired (the break is over), but after internal processing for the `break` action ended
200
+
201
+ Commands are invoked by the user (e.g. `pom start`). Actions are what Paradeiser does internally.
202
+
203
+ Examples for the use of hooks are:
204
+
205
+ * Displaying a desktop notification on `pre-finish`
206
+ * tmux status bar integration like [pomo](https://github.com/visionmedia/pomo) by writing the status to `~/.pomo_stat` from the `post-` hooks.
207
+ * Displaying a desktop notification on Linux:
208
+
209
+ # ~/.paradeiser/hooks/post-stop
210
+ notify-send "Break" "$POMODORO_TITLE is over." -u critical
211
+
212
+ * Displaying a desktop notification on MacOS:
213
+
214
+ # ~/.paradeiser/hooks/post-stop
215
+ terminal-notifier-success -message "$POMODORO_TITLE is over."
216
+
217
+ `$POMODORO_TITLE` is one of the environment variables set by Paradeiser that provides the context for hooks. See below for the full list of available environment variables.
218
+
219
+ ### Edit a hook
220
+
221
+ $ pom edit post-stop
222
+
223
+ Launches `$VISUAL` (or, if empty, `$EDITOR`) with the given hook.
224
+
225
+ ## Taskwarrior Integration
226
+
227
+ This is deployed to `~/.paradeiser/hooks/post-finish` by default.
228
+
229
+ # exit unless $(task)
230
+
231
+ # find all active
232
+ active = $(task active) # doesn't work yet; find the right column with 'task columns' and the info in http://taskwarrior.org/projects/taskwarrior/wiki/Feature_custom_reports
233
+
234
+ # TODO tag all active tasks so that we can re-start them
235
+
236
+ # stop all active
237
+ task $(task active) stop
238
+
239
+ ## Similar Projects
240
+
241
+ These and many more exist, why another tool?
242
+
243
+ * https://github.com/visionmedia/pomo
244
+ * https://github.com/stefanoverna/redpomo
245
+
246
+ They have a lot of what I wanted, but pomo focuses very much on the tasks themselves and less on the pomodori.
247
+
248
+ ## Implementation Notes
249
+
250
+ ### State Machine
251
+ Paradeiser uses a [state machine](https://github.com/pluginaweek/state_machine) to model a pomodoro. Internal event handlers do the actual work; among them is the task of calling the external hooks.
252
+
253
+ ### I18N
254
+ Paradeiser uses [I18N](https://github.com/svenfuchs/i18n) to translate messages and localize time and date formats.
255
+
256
+ ## API
257
+ The actual storage backend is *not a public API* and may change at any given time. External tools should use the Ruby API instead, or rely on the JSON export.
258
+
259
+ ## Sync
260
+ In todays world of distributed devices, synching data is a problem almost every app needs to solve. Paradeiser is no exception - it is very easy to come up with use cases that involve many computers. Maybe the user has different devices (mobile and desktop), maybe the user works in different environments, and wants to record all pomodori into a single system.
261
+
262
+ There are many potential solutions to this problem:
263
+
264
+ 1. A centralized server could host a data store (relational database, NoSQL store, etc.)
265
+ 1. A shared directory could host a single file and access could be coordinated using lock files
266
+ 1. Commercial solutions like the [Dropbox Sync API](https://www.dropbox.com/developers/sync)
267
+ 1. Custom solutions like [toystore](https://github.com/jnunemaker/toystore) with a [git adapter](https://github.com/bkeepers/adapter-git)
268
+
269
+ All of these are too much overhead right now, so the decision was made to keep Paradeiser simple and not implement any sync features. This may me revisited in a later version of the app.
270
+
271
+ ## Location
272
+ Recording the location of a pomodoro allows Paradeiser to compare the average count of successful and cancelled pomodori and the number of interruptions by location, so that a report can tell in which environment we get the most work done.
273
+
274
+ In order to record the current location at the start of the pomodoro, Paradeiser will record the hostname and the MAC address of the default gateway:
275
+
276
+ * OSX
277
+
278
+ arp 0.0.0.0 | head -1 | awk {'print $4'}
279
+
280
+ * Linux:
281
+
282
+ GATEWAY=$(netstat -rn | grep "^0.0.0.0" | cut -c17-31); ping -c1 $GATEWAY >/dev/null; arp -n $GATEWAY | tail -n1 | cut -c34-50
283
+
284
+ The location is then used to assign a label to one or more hostname@MAC strings, which will be used in a report.
285
+
286
+ ## What about the app's name?
287
+ In Austrian German, "Paradeiser" means tomato, of which the Italian translation is pomodoro.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ require "paradeiser/version"
2
+
3
+ module Paradeiser
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ module Paradeiser
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'paradeiser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "paradeiser"
8
+ spec.version = Paradeiser::VERSION
9
+ spec.authors = ["Nicholas E. Rabenau"]
10
+ spec.email = ["nerab@gmx.net"]
11
+ spec.description = %q{Paradeiser is a tool for the [Pomodoro Technique](http://www.pomodorotechnique.com/). It keeps track of the current pomodoro and assists the user in managing active and past pomodori.}
12
+ spec.summary = %q{Paradeiser is a tool for the Pomodoro Technique}
13
+ spec.homepage = "https://github.com/nerab/paradeiser"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paradeiser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas E. Rabenau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Paradeiser is a tool for the [Pomodoro Technique](http://www.pomodorotechnique.com/).
42
+ It keeps track of the current pomodoro and assists the user in managing active and
43
+ past pomodori.
44
+ email:
45
+ - nerab@gmx.net
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - .gitignore
51
+ - CONTRIBUTING.md
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - lib/paradeiser.rb
57
+ - lib/paradeiser/version.rb
58
+ - paradeiser.gemspec
59
+ homepage: https://github.com/nerab/paradeiser
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.0.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Paradeiser is a tool for the Pomodoro Technique
83
+ test_files: []