paradeiser 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/README.md +96 -35
- data/TODO.md +14 -15
- data/VISION.md +92 -84
- data/bin/{pom → par} +32 -2
- data/doc/Paradeiser::Break_status.svg +50 -0
- data/doc/Paradeiser::Pomodoro_status.svg +40 -22
- data/lib/paradeiser.rb +3 -3
- data/lib/paradeiser/controllers/breaks_controller.rb +19 -0
- data/lib/paradeiser/controllers/controller.rb +3 -3
- data/lib/paradeiser/controllers/paradeiser_controller.rb +13 -2
- data/lib/paradeiser/controllers/pomodori_controller.rb +36 -17
- data/lib/paradeiser/errors.rb +12 -6
- data/lib/paradeiser/executor.rb +2 -0
- data/lib/paradeiser/initializers/inflections.rb +4 -0
- data/lib/paradeiser/models/break.rb +40 -0
- data/lib/paradeiser/models/hook.rb +4 -4
- data/lib/paradeiser/models/interrupt.rb +18 -0
- data/lib/paradeiser/models/job.rb +1 -1
- data/lib/paradeiser/models/pomodoro.rb +30 -22
- data/lib/paradeiser/models/repository.rb +26 -13
- data/lib/paradeiser/models/scheduled.rb +25 -0
- data/lib/paradeiser/models/scheduler.rb +1 -1
- data/lib/paradeiser/models/status.rb +21 -0
- data/lib/paradeiser/{refinements.rb → refinements/numeric.rb} +4 -0
- data/lib/paradeiser/router.rb +12 -7
- data/lib/paradeiser/version.rb +1 -1
- data/lib/paradeiser/views/paradeiser/init.erb +1 -1
- data/lib/paradeiser/views/paradeiser/report.erb +5 -0
- data/lib/paradeiser/views/paradeiser/status.erb +13 -0
- data/paradeiser.gemspec +2 -0
- data/templates/linux/hooks/after-finish-break +10 -0
- data/templates/linux/hooks/after-finish-pomodoro +10 -0
- data/templates/linux/hooks/after-start-break +7 -0
- data/templates/linux/hooks/after-start-pomodoro +7 -0
- data/templates/mac/hooks/after-finish-break +10 -0
- data/templates/mac/hooks/after-finish-pomodoro +10 -0
- data/templates/mac/hooks/after-start-break +7 -0
- data/templates/mac/hooks/after-start-pomodoro +7 -0
- data/test/helper.rb +37 -4
- data/test/integration/{test_pom.rb → test_par.rb} +4 -4
- data/test/lib/{pomodoro_mock.rb → schedulable_mock.rb} +9 -1
- data/test/unit/test_break.rb +99 -0
- data/test/unit/test_break_controller.rb +56 -0
- data/test/unit/test_interrupt.rb +36 -0
- data/test/unit/test_paradeiser_controller_init.rb +92 -0
- data/test/unit/test_paradeiser_controller_report.rb +44 -0
- data/test/unit/test_paradeiser_controller_status.rb +70 -0
- data/test/unit/test_paradeiser_view.rb +66 -0
- data/test/unit/test_pomodori_controller.rb +87 -31
- data/test/unit/test_pomodori_view.rb +0 -50
- data/test/unit/test_pomodoro.rb +131 -9
- data/test/unit/test_pomodoro_hooks.rb +165 -17
- data/test/unit/test_repository.rb +38 -15
- data/test/unit/test_router.rb +4 -4
- data/test/unit/test_status.rb +26 -0
- metadata +70 -17
- data/lib/paradeiser/views/pomodori/report.erb +0 -5
- data/lib/paradeiser/views/pomodori/status.erb +0 -9
- data/templates/linux/hooks/after-finish +0 -10
- data/templates/linux/hooks/after-start +0 -7
- data/templates/mac/hooks/after-finish +0 -10
- data/templates/mac/hooks/after-start +0 -7
- data/test/unit/test_paradeiser_controller.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bee8d6c4f066abbede76f32b8bd4bb6eaffadce7
|
4
|
+
data.tar.gz: 220abdcc0e1bcdf6ef2d2819c5c903508f42da8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82e436e805e7159115ef9b814140f7e62ba1363d9e4af9fc6b18b9cf0bdbbb1efb355fe74f3febe19a61780989ff70df917b8dfbbf7f1229d7f1c79684bc9854
|
7
|
+
data.tar.gz: 40435ad4870ec1e3479bd9f82ef6168cd515cd89f6b0f437646092e1ab8d6d5e34301f93b5a8460f8286847365f7554c43bfeb3a1ba654b119568a8d50a03016
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/paradeiser.png)](http://badge.fury.io/rb/paradeiser)
|
4
4
|
[![Build Status](https://secure.travis-ci.org/nerab/paradeiser.png?branch=master)](http://travis-ci.org/nerab/paradeiser)
|
5
5
|
|
6
|
-
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file describes the functionality that is actually implemented, whereas the [VISION](VISION.md)
|
6
|
+
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file describes the functionality that is actually implemented, whereas the [VISION](VISION.md) reflects the vision where the tool should go._
|
7
7
|
|
8
8
|
Paradeiser is a command-line 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:
|
9
9
|
|
10
|
-
* Records finished pomodori
|
10
|
+
* Records finished and cancelled pomodori as well as internal and external interruptions and other events
|
11
11
|
* Keeps track of the timer for the active pomodoro and the break
|
12
|
-
* Provides out-of-the-box reports
|
12
|
+
* Provides out-of-the-box reports that show details about finished and cancelled pomodori
|
13
|
+
* Shows information about breaks and interruptions
|
13
14
|
|
14
15
|
Paradeiser itself is not concerned with the actual management of tasks. There are plenty of tools for that; e.g. [TaskWarrior](http://taskwarrior.org/).
|
15
16
|
|
@@ -19,7 +20,7 @@ Paradeiser itself is not concerned with the actual management of tasks. There ar
|
|
19
20
|
|
20
21
|
There must never be more than one pomodoro [xor](http://en.wikipedia.org/wiki/Xor) break at any given time.
|
21
22
|
|
22
|
-
This is scoped to a single user account (not just the `$
|
23
|
+
This is scoped to a single user account (not just the `$PAR_DIR` directory, but also the `at` queue).
|
23
24
|
|
24
25
|
## Installation
|
25
26
|
|
@@ -29,31 +30,54 @@ This is scoped to a single user account (not just the `$POM_DIR` directory, but
|
|
29
30
|
|
30
31
|
### Start a new pomodoro
|
31
32
|
|
32
|
-
$
|
33
|
+
$ par pomodoro start
|
33
34
|
|
34
|
-
Because of Rule #1, calling start while a pomodoro is active will print an error message.
|
35
|
+
If a break is still active, it will be stopped before the new pomodoro is started. Because of Rule #1, calling start while a pomodoro is active will print an error message.
|
35
36
|
|
36
37
|
### Finish the pomodoro
|
37
38
|
|
38
|
-
$
|
39
|
+
$ par pomodoro finish
|
39
40
|
|
40
|
-
If a pomodoro is active, it will be marked as successful after stopping it, regardless of whether the 25 minutes are over or not.
|
41
|
+
If a pomodoro is active, it will be marked as successful after stopping it, regardless of whether the 25 minutes are over or not. Remaining arguments, if present, will be added to the pomodoro as annotation.
|
41
42
|
|
42
43
|
If there is no active pomodoro, an error message will be printed.
|
43
44
|
|
45
|
+
### Record an interruption of the current pomodoro
|
46
|
+
|
47
|
+
$ par interrupt
|
48
|
+
$ par interrupt --external
|
49
|
+
|
50
|
+
Remaining arguments, if present, will be added to the interrupt as annotation. If no pomodoro is active, the command will throw an error.
|
51
|
+
|
52
|
+
### Start a break
|
53
|
+
|
54
|
+
$ par break [start]
|
55
|
+
|
56
|
+
If there is an active pomodoro, an error message will be printed. The `start` command is optional and may be omitted (it's only there for symmetry with `par break finish`, see the section about `at`).
|
57
|
+
|
58
|
+
By default the break will be five minutes long.
|
59
|
+
|
60
|
+
While there is a command to stop a break (see the section about `at`), it isn't really necessary to call it from a user's perspective. Either a new pomodoro is started, which will implicitely stop the break, or the break ends naturally because it is over. We do not track break time.
|
61
|
+
|
62
|
+
### Cancel the pomodoro
|
63
|
+
|
64
|
+
$ par pomodoro cancel Just couldn't concentrate anymore.
|
65
|
+
|
66
|
+
It will be marked as unsuccessful (remember, a pomodoro is indivisible). If no pomodoro is active, 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.
|
67
|
+
|
44
68
|
### Initialize Paradeiser
|
45
69
|
|
46
70
|
* Initialize the default directory that is used to store the Paradeiser configuration and data:
|
47
71
|
|
48
|
-
$
|
72
|
+
$ par init
|
49
73
|
|
50
|
-
Creates the `$
|
74
|
+
Creates the `$PAR_DIR` directory and the sample hooks in `$PAR_DIR/hooks`. The data store will not be created on `par init`, but when the first write operation happens (e.g. `par pomodoro start`, but not `par report`).
|
51
75
|
|
52
76
|
* Initialize an abritrary directory
|
53
77
|
|
54
|
-
$
|
78
|
+
$ par init /tmp
|
55
79
|
|
56
|
-
This command initializes `/tmp` as `$
|
80
|
+
This command initializes `/tmp` as `$PAR_DIR`.
|
57
81
|
|
58
82
|
## Timer with `at`
|
59
83
|
|
@@ -64,13 +88,17 @@ A central aspect of the Pomodoro Technique is the timer function:
|
|
64
88
|
|
65
89
|
The `at` command is used for this. We just tell it to call
|
66
90
|
|
67
|
-
|
91
|
+
par pomodoro finish
|
92
|
+
|
93
|
+
when the pomodoro is over. A similar command exists as
|
68
94
|
|
69
|
-
|
95
|
+
par break finish
|
96
|
+
|
97
|
+
which is called by `at` when the break is over.
|
70
98
|
|
71
99
|
When a pomodoro is started, Paradeiser enqueues itself to `at` like this:
|
72
100
|
|
73
|
-
echo
|
101
|
+
echo par pomodoro finish | at now + 25 minutes
|
74
102
|
|
75
103
|
When `at` calls Paradeiser with this command, the pomodoro / break will be over and Paradeiser can do all the internal processing related to stopping the pomodoro / break (incl. calling the appropriate hooks, see below).
|
76
104
|
|
@@ -78,60 +106,91 @@ Paradeiser uses a dedicated at queue named 'p' to organize its jobs and to preve
|
|
78
106
|
|
79
107
|
## Status
|
80
108
|
|
81
|
-
Paradeiser can print the current status to STDOUT with the `
|
109
|
+
Paradeiser can print the current status to STDOUT with the `par status` command. The current state is provided as process exit status (which is also useful when the output is suppressed).
|
82
110
|
|
83
111
|
* Given an active pomodoro:
|
84
112
|
|
85
|
-
$
|
113
|
+
$ par status
|
86
114
|
Pomodoro #2 is active (started 11:03, 14 minutes remaining).
|
87
115
|
|
88
|
-
$
|
116
|
+
$ par status > /dev/null
|
89
117
|
$ echo $?
|
90
118
|
0
|
91
119
|
|
92
120
|
* Given no active pomodoro and the last one (not earlier as today) was finished:
|
93
121
|
|
94
|
-
$
|
122
|
+
$ par status
|
95
123
|
No active pomodoro. Last one was finished at 16:58.
|
96
124
|
|
97
|
-
$
|
125
|
+
$ par status > /dev/null
|
98
126
|
$ echo $?
|
99
127
|
1
|
100
128
|
|
129
|
+
* Given no active pomodoro and the last one (not earlier as today) was cancelled:
|
130
|
+
|
131
|
+
$ par status
|
132
|
+
No pomodoro active. Last pomodoro was cancelled at 17:07.
|
133
|
+
|
134
|
+
$ par status > /dev/null
|
135
|
+
$ echo $?
|
136
|
+
2
|
137
|
+
|
138
|
+
* Given a break (implies no active pomodoro):
|
139
|
+
|
140
|
+
$ par status
|
141
|
+
Taking a 5 minute break until 2013-07-16 17.07 (4 minutes remaining).
|
142
|
+
|
143
|
+
$ par status > /dev/null
|
144
|
+
$ echo $?
|
145
|
+
3
|
146
|
+
|
101
147
|
## Reports
|
102
148
|
|
103
|
-
$
|
104
|
-
|
149
|
+
$ par report
|
150
|
+
|
151
|
+
## Output Policy
|
152
|
+
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` unless `--verbose` is given. `status`, `report` and `timesheet` are exempted from this rule, as their primary purpose is to print to STDOUT.
|
105
153
|
|
106
154
|
## Hooks
|
107
|
-
Instead of handling tasks itself, Paradeiser integrates with external tools via hooks. Every event will attempt to find and execute an appropriate script in `$
|
155
|
+
Instead of handling tasks itself, Paradeiser integrates with external tools via hooks. Every event will attempt to find and execute an appropriate script in `$PAR_DIR/hooks/`. Sufficient information will be made available via environment variables.
|
108
156
|
|
109
|
-
`before-` hooks will be called before the action is executed internally. If a `before-`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.
|
157
|
+
`before-` hooks will be called before the action is executed internally. If a `before-`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. In this case it will not process `after-` hooks.
|
110
158
|
|
111
159
|
`after-` 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.
|
112
160
|
|
113
161
|
### Available Hooks
|
114
162
|
|
115
|
-
* `before-start` is called
|
116
|
-
* `after-start` is called after
|
117
|
-
* `before-finish` is called after the timer of the current pomodoro fired (the pomodoro is over), but before
|
118
|
-
* `after-finish` is called after
|
163
|
+
* `before-start-pomodoro` is called before the processing of the start action begins.
|
164
|
+
* `after-start-pomodoro` is called after the processing of the start action ended.
|
165
|
+
* `before-finish-pomodoro` is called after the timer of the current pomodoro fired (the pomodoro is over), but before the processing of the `finish` action begins.
|
166
|
+
* `after-finish-pomodoro` is called after the processing of the `finish` action ended.
|
167
|
+
|
168
|
+
* `before-start-break` is called before the processing of the break start action begins.
|
169
|
+
* `after-start-break` is called after the processing of the break start action ended.
|
170
|
+
* `before-finish-break` is called after the timer of the current break fired (the break is over), but before the processing of the break finish action begins.
|
171
|
+
* `after-finish-break` is called after the processing of the break finish action ended.
|
172
|
+
* `before-interrupt-pomodoro` is called when the `interrupt` command was received, but before the action processing begins.
|
173
|
+
* `after-interrupt-pomodoro` is called after the processing of the `interrupt` action ended.
|
174
|
+
* `before-cancel-pomodoro` is called when the `cancel` command was received, but before the processing of the cancel action begins.
|
175
|
+
* `after-cancel-pomodoro` is called after the processing of the `cancel` action ended.
|
119
176
|
|
120
177
|
Examples for the use of hooks are:
|
121
178
|
|
122
|
-
* Displaying a desktop notification on `after-finish`
|
179
|
+
* Displaying a desktop notification on `after-finish-pomodoro`
|
123
180
|
* tmux status bar integration like [pomo](https://github.com/visionmedia/pomo) by writing the status to `~/.pomo_stat` from the `after-` hooks.
|
124
181
|
* Displaying a desktop notification
|
125
182
|
|
126
|
-
`$
|
183
|
+
`$PAR_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.
|
127
184
|
|
128
185
|
## Environment Variables
|
129
186
|
|
130
187
|
Variable | Used in | Description
|
131
188
|
--- | --- | ---
|
132
|
-
`$
|
133
|
-
`$
|
134
|
-
`$
|
189
|
+
`$PAR_DIR` | Everywhere | Directory where the data store and the hooks are stored. Defaults to `~/.paradeiser/`.
|
190
|
+
`$PAR_POMODORO_ID` | Hooks | Identifier of the pomodoro
|
191
|
+
`$PAR_POMODORO_STARTED_AT` | Hooks | Timestamp of when the pomodoro was started
|
192
|
+
`$PAR_BREAK_ID` | Hooks | Identifier of the break
|
193
|
+
`$PAR_BREAK_STARTED_AT` | Hooks | Timestamp of when the break was started
|
135
194
|
|
136
195
|
## Similar Projects
|
137
196
|
|
@@ -147,14 +206,16 @@ They have a lot of what I wanted, but pomo focuses very much on the tasks themse
|
|
147
206
|
### State Machine
|
148
207
|
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.
|
149
208
|
|
150
|
-
![State Transition Diagram](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Pomodoro_status.svg)
|
209
|
+
![State Transition Diagram for Pomodoro](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Pomodoro_status.svg)
|
210
|
+
![State Transition Diagram for Break](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Break_status.svg)
|
151
211
|
|
152
212
|
The graph was created using the rake task that comes with `state_machine`:
|
153
213
|
|
154
214
|
rake state_machine:draw CLASS=Paradeiser::Pomodoro TARGET=doc FORMAT=svg HUMAN_NAMES=true ORIENTATION=landscape
|
215
|
+
rake state_machine:draw CLASS=Paradeiser::Break TARGET=doc FORMAT=svg HUMAN_NAMES=true ORIENTATION=landscape
|
155
216
|
|
156
217
|
## API
|
157
|
-
The actual storage backend is *not a public API* and may change at any given time.
|
218
|
+
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 / import.
|
158
219
|
|
159
220
|
## Sync
|
160
221
|
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.
|
data/TODO.md
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
# Paradeiser Backlog
|
2
2
|
|
3
|
-
*
|
3
|
+
* Add `par report` with a single (global) view that implements the report format described in the vision document (but isn't scoped yet)
|
4
4
|
|
5
|
-
|
5
|
+
* Implement `par pomodoro annotate` and annotations for most commands. Alias it it `par annotate`.
|
6
6
|
|
7
|
-
|
7
|
+
* Improve status messages with relative times and dates (`distance_of_time_in_words_to_now`)
|
8
|
+
=> action_view/helpers/date_helper
|
8
9
|
|
9
|
-
*
|
10
|
+
* Simplify the status view. Separate views by class (break vs. pomodoro).
|
10
11
|
|
11
|
-
*
|
12
|
+
* Refactor the hooks tests: extract the common code
|
12
13
|
|
13
|
-
*
|
14
|
+
* Whenever par runs, it should garbage-collect pomodori or breaks (finish them and adjust their finish time) that weren't finished after they were over (e.g. because at isn't there or the hooks did not fire)
|
14
15
|
|
15
|
-
*
|
16
|
+
* Extend commander to allow abbreviated commands with Ruby's `Abbrev` module
|
16
17
|
|
17
18
|
* A text-based repo format would be much more UNIX-like. Think about a JSON repo. Loading it could share a lot of code with import (which we will need anyway). And we cannot trust a JSON repo any more than an import file.
|
18
19
|
|
19
|
-
* Make `start` the default subcommand for `pom break`, so that `pom break` is the same as `pom break start`.
|
20
|
-
|
21
20
|
* Have the router catch warnings (those errors that extend Warning) and print the message to STDERR, but do not exit. The actual exit code is still determined by the controller.
|
22
21
|
|
23
22
|
* Add more tests for the scheduler (error cases like no access, or job not added due to other issues)
|
@@ -28,9 +27,9 @@
|
|
28
27
|
- The view only shows the id for any given day in most reports. That means that a day (current by default, others in queries or import) is the scope of a pomodoro id.
|
29
28
|
- We don't have to globally identify pomodori with uuids because of rule #1
|
30
29
|
|
31
|
-
This also makes `
|
30
|
+
This also makes `par import` simple - only if there is nothing on record for the time between the start and end times of the imported thing, it is accepted into our system.
|
32
31
|
|
33
|
-
Deleting or overwriting existing pomodori is not supported. Manual editing, if ever needed, can be done with exporting, deleting the db file, fixing up the exported file, and importing it into a fresh $
|
32
|
+
Deleting or overwriting existing pomodori is not supported. Manual editing, if ever needed, can be done with exporting, deleting the db file, fixing up the exported file, and importing it into a fresh $PAR_DIR.
|
34
33
|
|
35
34
|
Active pomodori or breaks are not exported or imported.
|
36
35
|
|
@@ -39,19 +38,19 @@
|
|
39
38
|
- Errors red, warnings yellow, otherwise white
|
40
39
|
- Turn off when running w/o tty and when --no-color is given
|
41
40
|
|
42
|
-
* Print only the id of the
|
41
|
+
* Print only the id of the par that was just created / modified / queried when not running in a tty
|
43
42
|
- test with `if $stdin.tty?`
|
44
43
|
- If that approach works well, suggest it for TaskWarrior too (for bulk actions, e.g. in scripts)
|
45
44
|
|
46
45
|
* Implement documentation Approach
|
47
|
-
- `
|
48
|
-
- Not sure how to allow the user to look at features that are not related to a command. Either extend `
|
46
|
+
- `par help` is what the user will use to get information.
|
47
|
+
- Not sure how to allow the user to look at features that are not related to a command. Either extend `par help` to accept arbitrary keywords, or look into 'gem man`.
|
49
48
|
|
50
49
|
Development Tasks
|
51
50
|
|
52
51
|
- Describe each feature / command in one md file (alternatively, store at GitHub issues as feature, would allow discussion).
|
53
52
|
- When a feature is done, move it to a doc file (not the readme; it's getting too big) or a wiki page.
|
54
|
-
- `
|
53
|
+
- `par help <command>` consumes the feature files.
|
55
54
|
- Feature files could be exported onto a the github wiki or static pages about Paradeiser.
|
56
55
|
- As part of finishing a feature, the feature file is moved from the backlog file to in individual doc file, and the README is updated to mention that feature.
|
57
56
|
|
data/VISION.md
CHANGED
@@ -20,7 +20,7 @@ Paradeiser itself is not concerned with the actual management of tasks. There ar
|
|
20
20
|
|
21
21
|
There must never be more than one pomodoro [xor](http://en.wikipedia.org/wiki/Xor) break at any given time.
|
22
22
|
|
23
|
-
This is scoped to a single user account (not just the `$
|
23
|
+
This is scoped to a single user account (not just the `$PAR_DIR` directory, but also the `at` queue).
|
24
24
|
|
25
25
|
## Installation
|
26
26
|
|
@@ -30,14 +30,14 @@ This is scoped to a single user account (not just the `$POM_DIR` directory, but
|
|
30
30
|
|
31
31
|
### Start a new pomodoro
|
32
32
|
|
33
|
-
$
|
33
|
+
$ par pomodoro start
|
34
34
|
|
35
35
|
If a break is still active, it will be stopped before the new pomodoro is started. Because of Rule #1, calling start while a pomodoro is active will print an error message.
|
36
36
|
|
37
37
|
### Finish the pomodoro
|
38
38
|
|
39
|
-
$
|
40
|
-
$
|
39
|
+
$ par pomodoro finish
|
40
|
+
$ par pomodoro finish This one went very well.
|
41
41
|
|
42
42
|
If a pomodoro is active, it will be marked as successful after stopping it, regardless of whether the 25 minutes are over or not. Remaining arguments, if present, will be added to the pomodoro as annotation.
|
43
43
|
|
@@ -45,24 +45,24 @@ If there is no active pomodoro, an error message will be printed.
|
|
45
45
|
|
46
46
|
### Record an interruption of the current pomodoro
|
47
47
|
|
48
|
-
$
|
49
|
-
$
|
48
|
+
$ par interrupt
|
49
|
+
$ par interrupt --external
|
50
50
|
|
51
51
|
Remaining arguments, if present, will be added to the interrupt as annotation. If no pomodoro is active, the command will throw an error.
|
52
52
|
|
53
53
|
### Start a break
|
54
54
|
|
55
|
-
$
|
55
|
+
$ par break [start] [--short | --long]
|
56
56
|
|
57
|
-
If there is an active pomodoro, an error message will be printed. The `start` command is optional and may be omitted (it's only there for symmetry with `
|
57
|
+
If there is an active pomodoro, an error message will be printed. The `start` command is optional and may be omitted (it's only there for symmetry with `par break finish`, see the section about `at`).
|
58
58
|
|
59
|
-
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. `
|
59
|
+
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. `par break --short=10`).
|
60
60
|
|
61
61
|
While there is a command to stop a break (see the section about `at`), it isn't really necessary to call it from a user's perspective. Either a new pomodoro is started, which will implicitely stop the break, or the break ends naturally because it is over. We do not track break time.
|
62
62
|
|
63
63
|
### Annotate a pomodoro
|
64
64
|
|
65
|
-
$
|
65
|
+
$ par pomodoro annotate This was intense, but I am happy about the work I finished.
|
66
66
|
|
67
67
|
The annotation will be added to the active or, if none is active, to the most recently finished or cancelled pomodoro. If no text is given, the annotation text is read from STDIN.
|
68
68
|
|
@@ -70,15 +70,15 @@ Breaks cannot have annotations.
|
|
70
70
|
|
71
71
|
### Cancel the pomodoro
|
72
72
|
|
73
|
-
$
|
73
|
+
$ par pomodoro cancel Just couldn't concentrate anymore.
|
74
74
|
|
75
75
|
It will be marked as unsuccessful (remember, a pomodoro is indivisible). If no pomodoro is active, 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.
|
76
76
|
|
77
77
|
### Log a pomodoro
|
78
78
|
|
79
|
-
$
|
79
|
+
$ par pomodoro log
|
80
80
|
|
81
|
-
Add a successfully finished pomodoro that was never recorded as being started (maybe the user forgot to call `
|
81
|
+
Add a successfully finished pomodoro that was never recorded as being started (maybe the user forgot to call `par pomodoro start`). It will appear in the reports and will count towards efficiency calculations.
|
82
82
|
|
83
83
|
The current time will be used for the finish timestamp, and the start time will be calculated from the finish time backwards.
|
84
84
|
|
@@ -86,72 +86,72 @@ The current time will be used for the finish timestamp, and the start time will
|
|
86
86
|
|
87
87
|
* Initialize the default directory that is used to store the Paradeiser configuration and data:
|
88
88
|
|
89
|
-
$
|
89
|
+
$ par init
|
90
90
|
|
91
|
-
Creates the `$
|
91
|
+
Creates the `$PAR_DIR` directory and the sample hooks in `$PAR_DIR/hooks`. The data store will not be created on `par init`, but when the first write operation happens (e.g. `par pomodoro start`, but not `par report`).
|
92
92
|
|
93
93
|
* Initialize an abritrary directory
|
94
94
|
|
95
|
-
$
|
95
|
+
$ par init /tmp
|
96
96
|
|
97
|
-
This command initializes `/tmp` as `$
|
97
|
+
This command initializes `/tmp` as `$PAR_DIR`. It also sets the config variable `dir` in `~/.pomrc`:
|
98
98
|
|
99
|
-
$
|
99
|
+
$ par config
|
100
100
|
|
101
|
-
If the `at` command is not available or not enabled, `
|
101
|
+
If the `at` command is not available or not enabled, `par init` will issue a warning. The program will continue because it is still useful for recording, although it will not be able to enqueue itself in order to execute the (time-based) `before-finish-pomodoro` and `before-finish-break` hooks.
|
102
102
|
|
103
103
|
### Troubleshooting
|
104
104
|
|
105
|
-
`
|
105
|
+
`par doctor` performs a number of checks that ensure that Paradeiser can run with best results.
|
106
106
|
|
107
107
|
It checks if
|
108
108
|
|
109
109
|
* `at` is there and enabled
|
110
110
|
* ...
|
111
111
|
|
112
|
-
`
|
112
|
+
`par doctor` also provides a hint on how to correct that situation.
|
113
113
|
|
114
114
|
### Location
|
115
115
|
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.
|
116
116
|
|
117
117
|
* Show the current location
|
118
118
|
|
119
|
-
$
|
119
|
+
$ par location
|
120
120
|
Home Office
|
121
121
|
|
122
|
-
$
|
122
|
+
$ par location --verbose
|
123
123
|
Home Office (macbook@01:23:45:67:89:0A)
|
124
124
|
|
125
125
|
* List all locations
|
126
126
|
|
127
|
-
$
|
127
|
+
$ par locations
|
128
128
|
Home Office
|
129
129
|
Starbucks
|
130
130
|
|
131
|
-
$
|
131
|
+
$ par locations --verbose
|
132
132
|
Home Office (macbook@01:23:45:67:89:0A)
|
133
133
|
Starbucks (macbook@45:01:89:0A:67:23)
|
134
134
|
|
135
135
|
* Show the label of a location identifier
|
136
136
|
|
137
|
-
$
|
137
|
+
$ par location macbook@01:23:45:67:89:0A
|
138
138
|
Home Office
|
139
139
|
|
140
140
|
* Show the identifier of a location
|
141
141
|
|
142
|
-
$
|
142
|
+
$ par location "Home Office"
|
143
143
|
macbook@01:23:45:67:89:0A
|
144
144
|
|
145
145
|
* Label a location
|
146
146
|
|
147
|
-
$
|
147
|
+
$ par location macbook@01:23:45:67:89:0A "Your Label"
|
148
148
|
|
149
|
-
Paradeiser will automatically figure out the current location from the hostname and the MAC address of the default gateway (see below for details). This can be overridden by setting `$
|
149
|
+
Paradeiser will automatically figure out the current location from the hostname and the MAC address of the default gateway (see below for details). This can be overridden by setting `$PAR_LOCATION` or with a command line option:
|
150
150
|
|
151
|
-
$
|
151
|
+
$ par location --location="On the road"
|
152
152
|
On the road
|
153
153
|
|
154
|
-
$
|
154
|
+
$ PAR_LOCATION="On the road" par location
|
155
155
|
On the road
|
156
156
|
|
157
157
|
Both the `--location` option and the environment variable can be passed to almost all commands.
|
@@ -165,17 +165,17 @@ A central aspect of the Pomodoro Technique is the timer function:
|
|
165
165
|
|
166
166
|
The `at` command is used for this. We just tell it to call
|
167
167
|
|
168
|
-
|
168
|
+
par pomodoro finish
|
169
169
|
|
170
170
|
when the pomodoro is over. A similar command exists as
|
171
171
|
|
172
|
-
|
172
|
+
par break finish
|
173
173
|
|
174
174
|
which is called by `at` when the break is over.
|
175
175
|
|
176
176
|
When a pomodoro is started, Paradeiser enqueues itself to `at` like this:
|
177
177
|
|
178
|
-
echo
|
178
|
+
echo par pomodoro finish | at now + 25 minutes
|
179
179
|
|
180
180
|
When `at` calls Paradeiser with this command, the pomodoro / break will be over and Paradeiser can do all the internal processing related to stopping the pomodoro / break (incl. calling the appropriate hooks, see below).
|
181
181
|
|
@@ -183,57 +183,57 @@ Paradeiser uses a dedicated at queue named 'p' to organize its jobs and to preve
|
|
183
183
|
|
184
184
|
## Status
|
185
185
|
|
186
|
-
Paradeiser can print the current status to STDOUT with the `
|
186
|
+
Paradeiser can print the current status to STDOUT with the `par status` command. The current state is provided as process exit status (which is also useful when the output is suppressed).
|
187
187
|
|
188
188
|
* Given an active pomodoro:
|
189
189
|
|
190
|
-
$
|
190
|
+
$ par status
|
191
191
|
Pomodoro #2 is active (started 11:03, 14 minutes remaining).
|
192
192
|
|
193
|
-
$
|
193
|
+
$ par status > /dev/null
|
194
194
|
$ echo $?
|
195
195
|
0
|
196
196
|
|
197
197
|
* Given no active pomodoro and the last one (not earlier as today) was finished:
|
198
198
|
|
199
|
-
$
|
199
|
+
$ par status
|
200
200
|
No active pomodoro. Last one was finished at 16:58.
|
201
201
|
|
202
|
-
$
|
202
|
+
$ par status > /dev/null
|
203
203
|
$ echo $?
|
204
204
|
1
|
205
205
|
|
206
206
|
* Given no active pomodoro and the last one (not earlier as today) was cancelled:
|
207
207
|
|
208
|
-
$
|
208
|
+
$ par status
|
209
209
|
No pomodoro active. Last pomodoro was cancelled at 17:07.
|
210
210
|
|
211
|
-
$
|
211
|
+
$ par status > /dev/null
|
212
212
|
$ echo $?
|
213
213
|
2
|
214
214
|
|
215
215
|
* Given a break (implies no active pomodoro):
|
216
216
|
|
217
|
-
$
|
217
|
+
$ par status
|
218
218
|
Taking a 5 minute break until 2013-07-16 17.07 (4 minutes remaining).
|
219
219
|
|
220
|
-
$
|
220
|
+
$ par status > /dev/null
|
221
221
|
$ echo $?
|
222
222
|
3
|
223
223
|
|
224
224
|
* Short status (03:39 remaining in the active pomodoro or break):
|
225
225
|
|
226
|
-
$
|
226
|
+
$ par status --short
|
227
227
|
03:39
|
228
228
|
|
229
229
|
* Given a break and a custom status format (resembles the format switch analog to `date +%Y-%m-%dT%H:%M:%S`):
|
230
230
|
|
231
|
-
$
|
231
|
+
$ par status --format %C-%M:%S
|
232
232
|
B03:39
|
233
233
|
|
234
234
|
* Output in JSON format
|
235
235
|
|
236
|
-
$
|
236
|
+
$ par status --format JSON
|
237
237
|
{
|
238
238
|
"status": {
|
239
239
|
"state": "break",
|
@@ -246,7 +246,7 @@ Paradeiser can print the current status to STDOUT with the `pom status` command.
|
|
246
246
|
|
247
247
|
## Reports
|
248
248
|
|
249
|
-
$
|
249
|
+
$ par report
|
250
250
|
Daily Pomodoro Report for 2013-07-16
|
251
251
|
|
252
252
|
3 pomodori finished
|
@@ -258,11 +258,11 @@ Paradeiser can print the current status to STDOUT with the `pom status` command.
|
|
258
258
|
Most efficient location: Home Office
|
259
259
|
Least efficient location: Coffeshop
|
260
260
|
|
261
|
-
By default, the command groups by `--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. `
|
261
|
+
By default, the command groups by `--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. `par report --day=2013-07-18`. The period is parsed with [Chronic](http://chronic.rubyforge.org/), which also enables symbolic values like `par report --month="last month"`.
|
262
262
|
|
263
263
|
The report can also be grouped by location:
|
264
264
|
|
265
|
-
$
|
265
|
+
$ par report location
|
266
266
|
Pomodoro Location Report
|
267
267
|
|
268
268
|
Home Office: 38 finished, 12 cancelled, 21 interrupts
|
@@ -271,11 +271,11 @@ The report can also be grouped by location:
|
|
271
271
|
|
272
272
|
The following locations do not have a label. Assign it with
|
273
273
|
|
274
|
-
$
|
274
|
+
$ par location macbook@01:23:45:67:89:0A "Your Label"
|
275
275
|
|
276
276
|
Detailed report for a single location:
|
277
277
|
|
278
|
-
$
|
278
|
+
$ par report location "Home Office"
|
279
279
|
Pomodoro Location Report for Home Office
|
280
280
|
|
281
281
|
58 pomodori finished
|
@@ -288,7 +288,7 @@ Detailed report for a single location:
|
|
288
288
|
|
289
289
|
Further grouping is also possible, e.g. by year:
|
290
290
|
|
291
|
-
$
|
291
|
+
$ par report location --year=2012
|
292
292
|
Pomodoro Location Report for 2012
|
293
293
|
|
294
294
|
233 pomodori finished
|
@@ -305,7 +305,7 @@ The efficiency is calculated from the number of successful vs. cancelled pomodor
|
|
305
305
|
|
306
306
|
Efficiency can be reported by day, week, month, year, or location:
|
307
307
|
|
308
|
-
$
|
308
|
+
$ par report efficiency
|
309
309
|
Efficiency Report for 2013-07-16
|
310
310
|
|
311
311
|
TODO
|
@@ -318,14 +318,14 @@ Efficiency can be reported by day, week, month, year, or location:
|
|
318
318
|
|
319
319
|
### Timesheet
|
320
320
|
|
321
|
-
$
|
321
|
+
$ par timesheet
|
322
322
|
TODO Ordered list of pomodori and breaks, each with annotations (like a time sheet)
|
323
323
|
|
324
324
|
The same options as for regular reports apply. The timesheet report also details the efficiency of each location.
|
325
325
|
|
326
326
|
### Exporting a Report
|
327
327
|
|
328
|
-
$
|
328
|
+
$ par report --weekly --format JSON # weekly report in JSON format
|
329
329
|
{
|
330
330
|
"TODO": "Specify"
|
331
331
|
}
|
@@ -334,36 +334,41 @@ The same options as for regular reports apply. The timesheet report also details
|
|
334
334
|
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` unless `--verbose` is given. `status`, `report` and `timesheet` are exempted from this rule, as their primary purpose is to print to STDOUT.
|
335
335
|
|
336
336
|
## Hooks
|
337
|
-
Instead of handling tasks itself, Paradeiser integrates with external tools via hooks. Every event will attempt to find and execute an appropriate script in `$
|
337
|
+
Instead of handling tasks itself, Paradeiser integrates with external tools via hooks. Every event will attempt to find and execute an appropriate script in `$PAR_DIR/hooks/`. Sufficient information will be made available via environment variables.
|
338
338
|
|
339
|
-
`before-` hooks will be called before the action is executed internally. If a `before-`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.
|
339
|
+
`before-` hooks will be called before the action is executed internally. If a `before-`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. In this case it will not process `after-` hooks.
|
340
340
|
|
341
341
|
`after-` 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.
|
342
342
|
|
343
343
|
### Available Hooks
|
344
344
|
|
345
|
-
* `before-start` is called
|
346
|
-
* `after-start` is called after
|
347
|
-
* `before-finish` is called after the timer of the current pomodoro fired (the pomodoro is over), but before
|
348
|
-
* `after-finish` is called after
|
349
|
-
|
350
|
-
* `
|
351
|
-
* `
|
352
|
-
* `
|
353
|
-
* `
|
354
|
-
|
345
|
+
* `before-start-pomodoro` is called before the processing of the start action begins.
|
346
|
+
* `after-start-pomodoro` is called after the processing of the start action ended.
|
347
|
+
* `before-finish-pomodoro` is called after the timer of the current pomodoro fired (the pomodoro is over), but before the processing of the `finish` action begins.
|
348
|
+
* `after-finish-pomodoro` is called after the processing of the `finish` action ended.
|
349
|
+
|
350
|
+
* `before-start-break` is called before the processing of the break start action begins.
|
351
|
+
* `after-start-break` is called after the processing of the break start action ended.
|
352
|
+
* `before-finish-break` is called after the timer of the current break fired (the break is over), but before the processing of the break finish action begins.
|
353
|
+
* `after-finish-break` is called after the processing of the break finish action ended.
|
354
|
+
|
355
|
+
* `before-interrupt-pomodoro` is called when the `interrupt` command was received, but before the action processing begins.
|
356
|
+
* `after-interrupt-pomodoro` is called after the processing of the `interrupt` action ended.
|
357
|
+
|
358
|
+
* `before-cancel-pomodoro` is called when the `cancel` command was received, but before the processing of the cancel action begins.
|
359
|
+
* `after-cancel-pomodoro` is called after the processing of the `cancel` action ended.
|
355
360
|
|
356
361
|
Examples for the use of hooks are:
|
357
362
|
|
358
|
-
* Displaying a desktop notification on `after-finish`
|
363
|
+
* Displaying a desktop notification on `after-finish-pomodoro`
|
359
364
|
* tmux status bar integration like [pomo](https://github.com/visionmedia/pomo) by writing the status to `~/.pomo_stat` from the `after-` hooks.
|
360
365
|
* Displaying a desktop notification
|
361
366
|
|
362
|
-
`$
|
367
|
+
`$PAR_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.
|
363
368
|
|
364
369
|
### Edit a hook
|
365
370
|
|
366
|
-
$
|
371
|
+
$ par edit after-stop
|
367
372
|
|
368
373
|
Launches `$VISUAL` (or, if empty, `$EDITOR`) with the given hook.
|
369
374
|
|
@@ -371,34 +376,35 @@ Launches `$VISUAL` (or, if empty, `$EDITOR`) with the given hook.
|
|
371
376
|
|
372
377
|
Variable | Used in | Description
|
373
378
|
--- | --- | ---
|
374
|
-
`$
|
375
|
-
`$
|
376
|
-
`$
|
377
|
-
`$
|
378
|
-
`$
|
379
|
+
`$PAR_DIR` | Everywhere | Directory where the data store and the hooks are stored. Defaults to `~/.paradeiser/`.
|
380
|
+
`$PAR_POMODORO_ID` | Hooks | Identifier of the pomodoro
|
381
|
+
`$PAR_POMODORO_STARTED_AT` | Hooks | Timestamp of when the pomodoro was started
|
382
|
+
`$PAR_BREAK_ID` | Hooks | Identifier of the break
|
383
|
+
`$PAR_BREAK_STARTED_AT` | Hooks | Timestamp of when the break was started
|
384
|
+
`$PAR_LOCATION` | Location Commands | Location of the pomodoro
|
379
385
|
|
380
386
|
## Configuration File
|
381
387
|
|
382
|
-
The configuration is stored in a config file. It is user-editable file, but editing the configuration is also exposed with `
|
388
|
+
The configuration is stored in a config file. It is user-editable file, but editing the configuration is also exposed with `par config`.
|
383
389
|
|
384
|
-
$
|
390
|
+
$ par config dir
|
385
391
|
/home/nerab/.paradeiser
|
386
392
|
|
387
|
-
# Note how setting $
|
388
|
-
$
|
393
|
+
# Note how setting $PAR_DIR affects par config
|
394
|
+
$ PAR_DIR=/tmp par config dir
|
389
395
|
/tmp
|
390
396
|
|
391
|
-
$
|
392
|
-
$
|
397
|
+
$ par config dir /var/tmp
|
398
|
+
$ par config dir
|
393
399
|
/var/tmp
|
394
400
|
|
395
|
-
`
|
401
|
+
`par config` shows the _active_ config when called, i.e. it takes `$PAR_DIR` into account.
|
396
402
|
|
397
403
|
Available config variables:
|
398
404
|
|
399
405
|
Variable | Description
|
400
406
|
--- | ---
|
401
|
-
`
|
407
|
+
`PAR_DIR` | Directory where the data store and the hooks are stored. Defaults to `~/.paradeiser/`. Overridden by `$PAR_DIR`.
|
402
408
|
`AT_QUEUE` | Name of the `at` queue to use. Defaults to `p`.
|
403
409
|
|
404
410
|
## Taskwarrior Integration
|
@@ -429,11 +435,13 @@ They have a lot of what I wanted, but pomo focuses very much on the tasks themse
|
|
429
435
|
### State Machine
|
430
436
|
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.
|
431
437
|
|
432
|
-
![State Transition Diagram](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Pomodoro_status.svg)
|
438
|
+
![State Transition Diagram for Pomodoro](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Pomodoro_status.svg)
|
439
|
+
![State Transition Diagram for Break](https://rawgithub.com/nerab/paradeiser/master/doc/Paradeiser::Break_status.svg)
|
433
440
|
|
434
441
|
The graph was created using the rake task that comes with `state_machine`:
|
435
442
|
|
436
443
|
rake state_machine:draw CLASS=Paradeiser::Pomodoro TARGET=doc FORMAT=svg HUMAN_NAMES=true ORIENTATION=landscape
|
444
|
+
rake state_machine:draw CLASS=Paradeiser::Break TARGET=doc FORMAT=svg HUMAN_NAMES=true ORIENTATION=landscape
|
437
445
|
|
438
446
|
### I18N
|
439
447
|
Paradeiser uses [I18N](https://github.com/svenfuchs/i18n) to translate messages and localize time and date formats.
|