now-task-manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +66 -0
  3. data/bin/git-commit-pomodoro +4 -0
  4. data/bin/pomodoro +246 -0
  5. data/doc/benefits.md +91 -0
  6. data/doc/bitbar.md +2 -0
  7. data/doc/curses.md +5 -0
  8. data/doc/example/rules.rb +7 -0
  9. data/doc/formats/scheduled.md +32 -0
  10. data/doc/formats/today.md +115 -0
  11. data/doc/getting-started.md +41 -0
  12. data/doc/integrations.md +68 -0
  13. data/doc/rules.md +0 -0
  14. data/doc/schedules.md +0 -0
  15. data/doc/terms.md +32 -0
  16. data/doc/workflow.md +60 -0
  17. data/lib/pomodoro.rb +6 -0
  18. data/lib/pomodoro/commands/bitbar.rb +87 -0
  19. data/lib/pomodoro/config.rb +30 -0
  20. data/lib/pomodoro/exts/hour.rb +63 -0
  21. data/lib/pomodoro/formats/scheduled.rb +37 -0
  22. data/lib/pomodoro/formats/scheduled/parser/parser.rb +26 -0
  23. data/lib/pomodoro/formats/scheduled/parser/transformer.rb +21 -0
  24. data/lib/pomodoro/formats/scheduled/task_group.rb +40 -0
  25. data/lib/pomodoro/formats/scheduled/task_list.rb +90 -0
  26. data/lib/pomodoro/formats/today.rb +12 -0
  27. data/lib/pomodoro/formats/today/formatter.rb +26 -0
  28. data/lib/pomodoro/formats/today/parser/parser.rb +73 -0
  29. data/lib/pomodoro/formats/today/parser/transformer.rb +65 -0
  30. data/lib/pomodoro/formats/today/task.rb +92 -0
  31. data/lib/pomodoro/formats/today/task/dynamic_additions.rb +5 -0
  32. data/lib/pomodoro/formats/today/task/metadata.rb +37 -0
  33. data/lib/pomodoro/formats/today/task/statuses.rb +63 -0
  34. data/lib/pomodoro/formats/today/task_list.rb +50 -0
  35. data/lib/pomodoro/formats/today/time_frame.rb +113 -0
  36. data/lib/pomodoro/schedule/dsl.rb +68 -0
  37. data/lib/pomodoro/scheduler.rb +46 -0
  38. metadata +124 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 70c0874cdf93fd43ed8551927de6df1108063489
4
+ data.tar.gz: 44a53cdf68384fac811045ff7f014bf17cfb5b22
5
+ SHA512:
6
+ metadata.gz: 0c1a7b2f7d86729e72459bde2c0de679e742af5a96e7f861c7a86d799cde99ab0cb417ed34f3e95867b2ff92ec06736bc91f2e43fefd8369f3b73ad1c1044be1
7
+ data.tar.gz: d4d178e9a047999f5ec680eda76f43959e1a67ace46e57a2f6bb46005443feaf1b953007c5ceacd1d5be66f92f3ad1923a4e9ab9a6480eb4183ef4d14ef5c60a
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # About
2
+
3
+ [![Gem version][GV img]][Gem version]
4
+ [![Build status][BS img]][Build status]
5
+ [![Coverage status][CS img]][Coverage status]
6
+ [![YARD documentation][YD img]][YARD documentation]
7
+
8
+ **Now Task Manager** is a daily planner & focus app *for programmers*. It helps
9
+ you plan your day, stay focused and track your time.
10
+
11
+ It doesn't replace either GTD or the pomodoro technique, it complements them.
12
+ (In fact there will be a [Pomodoro plugin #18](https://github.com/botanicus/now-task-manager/issues/18) at some point.)
13
+
14
+ At some point I must have tried every bloody time management app there is (and let
15
+ me tell you, there's a lot of them) and I was still disorganised and eventually
16
+ went back to tracking my tasks in a plain text file.
17
+
18
+ And that's what <abbrev title="Now Task Manager">NTM</abbrev> is using: just plain
19
+ text files. But plain text files by themselves didn't help me: after all, that was
20
+ what I begun with.
21
+
22
+ The problem I was always facing was what to do when. As a freelancer, I can do
23
+ generally do anything anytime. That's great on one hand, on the other hand it
24
+ takes much more discipline. Typical problems:
25
+
26
+ - Work too much time on one project and too little time on another one.
27
+ - Starting a day with a great idea, coding half a day and then working on clients
28
+ projects late at night.
29
+ - Missing incremental steps to my long-term goals, like doing every morning Spanish
30
+ revision.
31
+
32
+ Everything started to turn around when I started to adapt what I call **time framing**:
33
+ time framing is about splitting your day into several blocks with clear start time
34
+ and end time and within the block doing only tasks that are related to that block.
35
+
36
+ So <abbrev title="Now Task Manager">NTM</abbrev> is an automation based on my plain
37
+ text task files where you define your schedule and then forces you to stick to it.
38
+
39
+ ![Workflow diagram](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/diagram.png)
40
+
41
+ Read about the [benefits](https://github.com/botanicus/now-task-manager/blob/master/doc/benefits.md).
42
+
43
+ ## What it's not
44
+
45
+ Firstly, this is **not a project management** or **GTD system**: there is no
46
+ concept of a project. Here it's all about chunks of time (days and time frames)
47
+ and populating them with tasks from do-it-later lists as well as automatically.
48
+
49
+ You might very well need such system and that's fine: I use GH issues just for that,
50
+ in addition to using Pomodoro. But Pomodoro is the corner stone of my day organisation,
51
+ GH issues are place to dump to tasks, then link them from Pomodoro.
52
+
53
+ For the same reason it doesn't deal with **priorities**. If it's not a priority,
54
+ why would you put it on today's todo list?
55
+
56
+ _**Read next**: the [workflow](https://github.com/botanicus/now-task-manager/blob/master/doc/workflow.md)_
57
+
58
+ [Gem version]: https://rubygems.org/gems/now-task-manager
59
+ [Build status]: https://travis-ci.org/botanicus/now-task-manager
60
+ [Coverage status]: https://coveralls.io/github/botanicus/now-task-manager
61
+ [YARD documentation]: http://www.rubydoc.info/github/botanicus/now-task-manager/master
62
+
63
+ [GV img]: https://badge.fury.io/rb/pomodoro.svg
64
+ [BS img]: https://travis-ci.org/botanicus/now-task-manager.svg?branch=master
65
+ [CS img]: https://img.shields.io/coveralls/botanicus/now-task-manager.svg
66
+ [YD img]: http://img.shields.io/badge/yard-docs-blue.svg
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+ message=$(pomodoro active git)
4
+ git commit -m "$message"
data/bin/pomodoro ADDED
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pomodoro'
4
+ require 'refined-refinements/colours'
5
+
6
+ using RR::ColourExts
7
+
8
+ def parse(parser_class, transformer_class, result_class, file_path)
9
+ input = File.read(file_path, encoding: 'utf-8')
10
+ tree = parser_class.new.parse(input)
11
+ # .parse(input, reporter: Parslet::ErrorReporter::Deepest.new)
12
+ nodes = transformer_class.new.apply(tree)
13
+ result_class.new(nodes) unless nodes.empty?
14
+ rescue Errno::ENOENT
15
+ abort "<red>File #{file_path} doesn't exist.</red>".colourise
16
+ end
17
+
18
+ def parse_today_list(config)
19
+ parse(Pomodoro::TodayParser, Pomodoro::TodayTransformer, Pomodoro::TaskList, config.today_path)
20
+ end
21
+
22
+ def parse_task_list(config)
23
+ parse(Pomodoro::TaskListParser, Pomodoro::SimpleFormat::TaskListTransformer, Pomodoro::SimpleFormat::TaskList, config.task_list_path)
24
+ end
25
+
26
+ def time_frame(config, &block)
27
+ today_list = parse_today_list(config)
28
+
29
+ unless current_time_frame = today_list.get_current_time_frame
30
+ abort "<red>There is no active time frame.</red>".colourise
31
+ end
32
+
33
+ block.call(today_list, current_time_frame)
34
+ end
35
+
36
+ # TODO: change this to find the first active task, ignoring the time frame.
37
+ # Only then complain about the time frame.
38
+ def with_active_task(config, &block)
39
+ time_frame(config) do |today_list, current_time_frame|
40
+ if active_task = current_time_frame.active_task
41
+ block.call(active_task)
42
+ today_list.save(config.today_path)
43
+ else
44
+ abort "<red>No more tasks in #{current_time_frame.desc}</red>".colourise
45
+ end
46
+ end
47
+ end
48
+
49
+ def edit_next_task_when_no_task_active(config, &block)
50
+ time_frame(config) do |today_list, current_time_frame|
51
+ if active_task = current_time_frame.active_task
52
+ abort "<red>There is an active task already:</red>\n#{active_task}".colourise
53
+ end
54
+
55
+ if next_task = current_time_frame.first_unstarted_task
56
+ block.call(next_task)
57
+ today_list.save(config.today_path)
58
+ else
59
+ abort "<red>No more tasks in #{current_time_frame.desc}</red>".colourise
60
+ end
61
+ end
62
+ end
63
+
64
+ def generate_todays_tasks(date, config)
65
+ require 'pomodoro/scheduler'
66
+
67
+ date_path = config.today_path(date)
68
+
69
+ return date_path if File.exist?(config.today_path)
70
+
71
+ scheduler = Pomodoro::Scheduler.load([config.schedule_path, config.routine_path], date)
72
+
73
+ schedule = scheduler.schedule_for_date(date)
74
+ task_list = schedule.call
75
+ scheduler.populate_from_rules(task_list)
76
+
77
+ main_task_list = parse_task_list(config)
78
+ labels = ['Tomorrow', date.strftime('%A'), date.strftime('%-d/%m'), date.strftime('%-d/%m/%Y')]
79
+
80
+ labels.each do |label|
81
+ if main_task_list[label]
82
+ main_task_list[label].tasks.each do |task|
83
+ puts "~ #{task}"
84
+ task_list.morning_ritual.create_task(task)
85
+ main_task_list.delete(main_task_list[label])
86
+ end
87
+ end
88
+ end
89
+
90
+ File.open(date_path, 'w') do |file|
91
+ file.puts(task_list.to_s)
92
+ end
93
+
94
+ main_task_list.save(config.task_list_path)
95
+
96
+ return date_path
97
+ end
98
+
99
+ # Main.
100
+ config = Pomodoro::Config.new
101
+
102
+ case ARGV.shift
103
+ when 'edit', 'e'
104
+ if ARGV.empty?
105
+ date_path = generate_todays_tasks(Date.today, config)
106
+ exec("vim #{date_path}")
107
+ elsif ARGV.first.to_i == 2
108
+ date_path = generate_todays_tasks(Date.today, config)
109
+ exec("vim -O2 #{date_path} #{config.task_list_path}")
110
+ elsif ARGV.first == 'tomorrow'
111
+ date_path = generate_todays_tasks(Date.today + 1, config)
112
+ exec("vim -O2 #{date_path} #{config.task_list_path}")
113
+ elsif ['tasks', 't'].include?(ARGV.first)
114
+ exec("vim #{config.task_list_path}")
115
+ else
116
+ abort(DATA.read.colourise)
117
+ end
118
+ when 'next'
119
+ time_frame(config) do |today_list, current_time_frame|
120
+ if active_task = current_time_frame.active_task
121
+ abort "<red>There is an active task already:</red>\n#{active_task}".colourise
122
+ end
123
+
124
+ if task = current_time_frame.first_unstarted_task
125
+ task.start
126
+ today_list.save(config.today_path)
127
+ else
128
+ abort "<red>No more tasks in #{current_time_frame.desc}</red>".colourise
129
+ end
130
+ end
131
+ when 'next?'
132
+ time_frame(config) do |today_list, current_time_frame|
133
+ if active_task = current_time_frame.active_task
134
+ abort "<red>There is an active task already:</red>\n#{active_task}".colourise
135
+ end
136
+
137
+ if task = current_time_frame.first_unstarted_task
138
+ puts task
139
+ else
140
+ abort "<red>No more tasks in #{current_time_frame.desc}</red>".colourise
141
+ end
142
+ end
143
+ when 'complete'
144
+ with_active_task(config) do |active_task|
145
+ require 'pry'; binding.pry ###
146
+ active_task.complete
147
+ puts active_task
148
+ end
149
+ when 'postpone'
150
+ # Ask for metadata and comments.
151
+ with_active_task(config) do |active_task|
152
+ active_task.postpone
153
+ puts active_task
154
+ end
155
+ when 'move_on'
156
+ # Ask for metadata and comments.
157
+ with_active_task(config) do |active_task|
158
+ active_task.move_on
159
+ puts active_task
160
+ end
161
+ when 'active'
162
+ with_active_task(config) do |active_task|
163
+ case ARGV.shift
164
+ # git-commit-pomodoro
165
+ # TODO: Subtasks as well.
166
+ when 'git' then puts active_task.text
167
+ when 'prompt' then puts active_task.text
168
+ when nil then puts active_task
169
+ else
170
+ # TODO: Format with %d etc.
171
+ end
172
+ end
173
+ when 'tick-off-next'
174
+ edit_next_task_when_no_task_active(config) do |next_task|
175
+ next_task.complete
176
+ end
177
+ when 'fail-next'
178
+ print "<bold>Why?</bold> ".colourise
179
+ reason = STDIN.readline.chomp
180
+ edit_next_task_when_no_task_active(config) do |next_task|
181
+ next_task.fail(reason)
182
+ end
183
+ when 'postpone-next'
184
+ print "<bold>Why?</bold> ".colourise
185
+ reason = STDIN.readline.chomp
186
+ print "<bold>When do you want to review?</bold> Defaults to tomorrow. ".colourise
187
+ review_at = STDIN.readline.chomp
188
+ edit_next_task_when_no_task_active(config) do |next_task|
189
+ next_task.postpone(reason, review_at.empty? ? 'Tomorrow' : review_at)
190
+ end
191
+ when '+'
192
+ task_list = parse_task_list(config)
193
+ task_list['Later'] ||= Array.new
194
+ task_list['Later'] << ARGV.join(' ')
195
+ task_list.save(config.task_list_path)
196
+ when 'console', 'c'
197
+ today = parse_today_list(config)
198
+ tasks = parse_task_list(config)
199
+ require 'pry'; binding.pry
200
+ when 'tools'
201
+ if ARGV.shift == 'workdays'
202
+ start_date = Date.new(2018, 12, 1)
203
+ end_date = Date.new(2018, 12, 31)
204
+ work_days = (start_date..end_date).reduce(0) do |sum, date|
205
+ sum += 1 unless date.saturday? || date.sunday?; sum
206
+ end
207
+ puts "~ There are #{work_days} (without any bank holidays) in 2018."
208
+ # TODO: Per-month breakdown.
209
+ end
210
+ when 'bitbar'
211
+ require 'pomodoro/commands/bitbar'
212
+ today_list = parse_today_list(config)
213
+ task_list = parse_task_list(config)
214
+ Pomodoro::Commands::BitBar.main(today_list, task_list)
215
+ when 'help', '-h', '--help'
216
+ puts(DATA.read.colourise)
217
+ else
218
+ abort(DATA.read.colourise)
219
+ end
220
+
221
+ __END__
222
+
223
+ <red.bold>:: Pomodoro ::</red.bold>
224
+
225
+ pomodoro <green>edit</green>, pomodoro <green>e</green>
226
+ <bright_black>pomodoro e</bright_black> Edit the today task file, creating it if it doesn't exist.
227
+ <bright_black>pomodoro e <yellow>2</yellow></bright_black> Edit both the today task file and tasks (in a split screen).
228
+ <bright_black>pomodoro e <yellow>tasks</yellow></bright_black> (or just <yellow>t</yellow>) Open the task file.
229
+ <bright_black>pomodoro e <yellow>tomorrow</yellow></bright_black> Plan tomorrow.
230
+
231
+ pomodoro <magenta>next</magenta> <bright_black># Start a new task.</bright_black>
232
+ pomodoro <magenta>complete</magenta> <bright_black># Complete the active task.</bright_black>
233
+ pomodoro <magenta>postpone</magenta> <bright_black># Postpone the active task.</bright_black>
234
+ pomodoro <magenta>move_on</magenta> <bright_black># Move on from the active task. Mark its end time, but don't set it as completed.</bright_black>
235
+
236
+ pomodoro <green>next?</green> <bright_black># Print the next task.</bright_black>
237
+ pomodoro <green>active</green> <bright_black># Print the active task.</bright_black>
238
+
239
+ pomodoro <magenta>tick-off-next</magenta> <bright_black># ...</bright_black>
240
+ pomodoro <magenta>fail-next</magenta> <bright_black># ...</bright_black>
241
+ pomodoro <magenta>postpone-next</magenta> <bright_black># ...</bright_black>
242
+
243
+ pomodoro <red>+</red> [strings]<bright_black> # Add a task for later.</bright_black>
244
+
245
+ pomodoro <yellow>console</yellow>, pomodoro <yellow>c</yellow> <bright_black># Load the tasks and launch IRB.</bright_black>
246
+ pomodoro <yellow>bitbar</yellow> <bright_black># Print output for BitBar.</bright_black>
data/doc/benefits.md ADDED
@@ -0,0 +1,91 @@
1
+ _This document is WIP._
2
+
3
+ - Separating planning from execution.
4
+ - Predictable schedules.
5
+ - Task statuses. Where did you ended, why was it postponed and how long for?
6
+
7
+ don't let your work and errands kill your personal objectives. Learning Spanish etc.
8
+
9
+ plan, review
10
+ scrum uses time framing as well (sprints)
11
+ time framing here is different: it's not about deliverables (you can work on a project ad infinitum), it's about the routines and project scheduling (it's all bottom-up).
12
+
13
+ USE POMODORO WITHIN for durations? This can be available via plugins.
14
+ Example: pomodoros are not useful for everything. Like going to a bank,
15
+ you never know how long it's going to take (esp. if you live in Poland).
16
+ The only thing that is certain is that you have to fit it within a time frame,
17
+ because you have to get your client's work done.
18
+
19
+ I'm not a time management expert, but this is the practical solution that made my life infinitely more organised.
20
+
21
+ - Schedules, task archive.
22
+ - Increase awareness.
23
+ - No skipping.
24
+ - End-of-the day/week reports for clients (incl. how much to charge).
25
+ - Offlining.
26
+ - Make your work easier with `git commit-pomodoro`.
27
+
28
+
29
+ _Time management technique based on time framing and a command-line task management tool._
30
+
31
+ This is something between GTD and the pomodoro technique: it has part of the depth of GTD and part of the immediate action management approach of pomodoro. It is a full-circle task management method.
32
+
33
+ It does also time tracking which can be used to count actual time worked for clients.
34
+
35
+ ## Benefits
36
+
37
+ ### Holistic
38
+
39
+ I tried pomodoro and it's great, but it doesn't see the big picture.
40
+
41
+ The pomodoro technique is great to force you to do the work and not procrastinating.
42
+
43
+ It doesn't help you to keep several client projects in the air while you have your
44
+ personal goals and responsibilities.
45
+
46
+ - Holistic. It's not just for the work or just for home.
47
+ - Defaults. Don't think.
48
+ - Automatically tracking time for clients.
49
+
50
+ ## It doesn't make you think
51
+
52
+ Tasks are sequential. You cannot choose which task to work on next. The next task down the list is the one that's coming next.
53
+
54
+ Schedules are automatic.
55
+
56
+ Will power limited.
57
+
58
+ ## Rich data
59
+
60
+ **Time tracking** (optional): Time tracking is useful if you are paid for your time or if you want to run any useful stats.
61
+
62
+ Task **status** and **metadata**
63
+
64
+ **Journaling**
65
+
66
+ ## Data is yours
67
+
68
+ The data are in simple plain text and you get a Ruby library to parse them and do whatever you want.
69
+
70
+ For instance let's see how much time have I spent on admin in the first quarter of 2017:
71
+
72
+ ```ruby
73
+ require 'pomodoro'
74
+
75
+ Pomodoro.load('2017/{1,2,3}').each do |task_list|
76
+ task_list.reduce(0) do |sum, time_frame|
77
+ if time_frame.tags.include?(:admin)
78
+ sum + time_frame.duration
79
+ else
80
+ sum
81
+ end
82
+ end
83
+ end
84
+ ```
85
+
86
+ Or you can want to know how good your estimates are. You've been adding a custom
87
+ metadata such as `Estimate: 4h` to your tasks. Now you can go and compare the estimate
88
+ with the actual duration of the task.
89
+
90
+ Read the [workflow](https://github.com/botanicus/now-task-manager/blob/master/doc/workflow.md)
91
+ to understand how it works.
data/doc/bitbar.md ADDED
@@ -0,0 +1,2 @@
1
+ - BitBar: show each project TODO.
2
+ - colour of a time frame based on how much time left.
data/doc/curses.md ADDED
@@ -0,0 +1,5 @@
1
+ https://github.com/thibaudgg/rb-fsevent
2
+
3
+ - Keep an eye on time frames changing.
4
+ - Keep an eye on tasks scheduled for specific time.
5
+ - Run the timer for tasks with given duration.
@@ -0,0 +1,7 @@
1
+ time_frame(/morning routine/i) do |time_frame|
2
+ time_frame.create_task('Headspace.')
3
+ end
4
+
5
+ time_frame(/admin/i) do |time_frame|
6
+ time_frame.create_task('Inbox 0.')
7
+ end
@@ -0,0 +1,32 @@
1
+ This format is used to store **scheduled tasks**: tasks that will be done later
2
+ or in a certain context.
3
+
4
+ ```
5
+ Tomorrow
6
+ - Buy milk. #errands
7
+ - [9:20] Call with Mike.
8
+
9
+ Prague
10
+ - Pick up my shoes. #errands
11
+ ```
12
+
13
+ # Currently unsupported
14
+
15
+ - **Labels**. Labels allow us to match tasks with _named_ time frames.
16
+ See [#8](https://github.com/botanicus/now-task-manager/issues/8).
17
+
18
+ ```
19
+ - ADM: Catch up with Eva.
20
+ ```
21
+
22
+ # Intentionally unsupported
23
+
24
+ - **Comments**. I want to keep the format simple and the task file small.
25
+ Every time there was something like comments, the file bloated uncontrollably.
26
+ - **Task formatting**. Task is a string, it doesn't recognise any structures within.
27
+ Therefore, anything you can fit in to a line will be the task body. So you can
28
+ put anything that {Pomodoro::Formats::Today} supports such as scheduled times
29
+ and tags.
30
+
31
+ _For more details about the format see
32
+ {https://github.com/botanicus/now-task-manager/blob/master/spec/pomodoro/formats/scheduled/parser/parser_spec.rb parser_spec.rb}._