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
@@ -0,0 +1,115 @@
1
+ # `Today` format
2
+
3
+ This format is used for tasks that are being worked on today.
4
+
5
+ ```
6
+ Morning routine (7:50 – 9:20)
7
+ ✔ Headspace. #meditation
8
+ ✘ Go swimming. #exercise
9
+ Reason: Some clever excuse.
10
+ ✔ Eat breakfast.
11
+ ✔ [20] Spanish flashcards. #learning
12
+
13
+ Admin (9:20 – 12)
14
+ ✔ [9:20-10:00] Inbox 0.
15
+ I should allocate more time to it from now on.
16
+
17
+ Some more comment line 1
18
+ Some more comment line 2
19
+ - [started at 10:00] Print out invoices.
20
+ - Review GitHub issues.
21
+ - [11:40] Call with Sonia.
22
+
23
+ Lunch break (12 – 13)
24
+
25
+ Work for client 1 (13 – 17)
26
+ - Issue#87.
27
+
28
+ Evening (after 17)
29
+ - Free style meditation. #meditation
30
+ ```
31
+
32
+ ## Metadata
33
+
34
+ Metadata are indented lines following a task.
35
+
36
+ There can be either lines, subtasks or key value pairs or a combination of either.
37
+
38
+ ### Lines
39
+
40
+ ```
41
+ I should allocate more time to it from now on.
42
+
43
+ Some more comment line 1.
44
+ Some more comment line 2.
45
+ ```
46
+
47
+ This will turn into:
48
+
49
+ ```ruby
50
+ [
51
+ "I should allocate more time to it from now on.",
52
+ "Some more comment line 1. Some more comment line 2."
53
+ ]
54
+ ```
55
+
56
+ ### Key-value pairs
57
+
58
+ ```
59
+ - [8:25-8:41] Research EU residency permit:
60
+ Link: http://www.migrant.info.pl/temporary-residence-permit.html, http://www.migrant.info.pl/residence-card.html
61
+ Outcome: This is what I need.
62
+ Next: Apply for http://www.migrant.info.pl/temporary-residence-permit.html # -> This makes the task.
63
+ Review: Upon my return from CZ/ES. # -> This makes a headline.
64
+
65
+ - [10:09-10:20] Push the code from Cloud9 to GH and clone it from my mac.
66
+ Skipped: SSH keys issues, I requested it to be researched.
67
+
68
+ - [11:42-12:20] Clean up the flat, find my MasterCard.
69
+ Comment: It took me a good while to find the card. # VNORENY.
70
+ I have to clean up the mess and keep it clean!
71
+
72
+ - Headspace.
73
+ Skipped: Instead of meditating, I wrote a command to play the next HS episode and, to remember them. I tend to forget which episode I'm on.
74
+
75
+ - Millennium: pick up EUR.
76
+ Postponed: Queue too long.
77
+
78
+ - [11:31-11:41] Review my moleskine to see whether I need to take it with me.
79
+ Outcome: I don't need to take it.
80
+
81
+ ✔ Inquire about why the payment failed.
82
+ Waiting for: Response.
83
+ Review: Tomorrow.
84
+
85
+ - [9:51-9:59] Inquire about why the payment failed.
86
+ Review: tomorrow.
87
+ ```
88
+
89
+ ### Subtasks
90
+
91
+ ```
92
+ - [9:37-9:51] Plan the CZ/ES trip and make the reservations for PRG.
93
+ ✔ Book accommodation in PRG.
94
+ - Ping Macarena.
95
+ ```
96
+
97
+ ## Considered features
98
+
99
+ #### Nested time frames
100
+
101
+ Very often an action is interrupted by an other. If it takes 5 minutes, it's irrelevant to log it, but what if it took half of the afternoon?
102
+
103
+ NOTE: http://kschiess.github.io/parslet/parser.html last to chapters explain how to create the recursion.
104
+
105
+ ```
106
+ Work for client 1 (13 – 17)
107
+ - Issue#87.
108
+
109
+ Emergency (2 – 3:30)
110
+ ✔ Extinguish fire in the living room.
111
+
112
+ - Task
113
+ ```
114
+
115
+ _There are detailed [unit specs](spec/pomodoro/parser) for the format._
@@ -0,0 +1,41 @@
1
+ _This document is WIP._
2
+
3
+ # Getting started
4
+
5
+ _If you don't understand any term, read [terms](https://github.com/botanicus/now-task-manager/blob/master/doc/terms.md)_
6
+
7
+ 1. Define your schedules.
8
+
9
+ There are two types of tasks: tasks to be done **today** and **scheduled tasks**.
10
+
11
+
12
+ ## Schedules
13
+
14
+ The real fun starts with using schedules.
15
+
16
+ ```ruby
17
+ # ~/.config/pomodoro/schedules/base.rb
18
+ rule(:weekday, -> { today.weekday? }) do |tasks|
19
+ tasks.push(*morning_ritual_tasks)
20
+ tasks << Pomodoro::Task.new('TopTal.', 20, [:online, :work])
21
+ tasks << work_tasks[rand(work_tasks.length)]
22
+ tasks.push(*lunch_break_tasks)
23
+ tasks << Pomodoro::Task.new(project_of_the_week, 90, [:project_of_the_week, :online])
24
+ tasks << cleanup_tasks[rand(cleanup_tasks.length)]
25
+ tasks.push(*evening_tasks)
26
+ end
27
+ ```
28
+
29
+ # Configuration
30
+
31
+ ```yaml
32
+ # ~/.config/pomodoro.yml
33
+ ---
34
+ schedule: ~/Dropbox/Data/Data/Pomodoro/Schedules/schedules.rb
35
+ routine: ~/Dropbox/Data/Data/Pomodoro/Schedules/base.rb
36
+ today: ~/Dropbox/Data/Data/Pomodoro/Tasks/%Y-%m-%d.today
37
+ task_list: ~/Dropbox/Data/WIP/tasks.todo
38
+ ```
39
+
40
+ - [today format](https://github.com/botanicus/now-task-manager/blob/master/doc/formats/today.md)
41
+ - [schedule task list format](https://github.com/botanicus/now-task-manager/blob/master/doc/formats/scheduled.md)
@@ -0,0 +1,68 @@
1
+ _This document is WIP._
2
+
3
+ https://github.com/blog/2231-building-your-first-atom-plugin
4
+
5
+ - Writing Vim plugins http://stevelosh.com/blog/2011/09/writing-vim-plugins/
6
+ - Vim plugin documentation http://learnvimscriptthehardway.stevelosh.com/chapters/54.html
7
+
8
+ ## BitBar plugin
9
+
10
+ [BitBar](https://getbitbar.com/)
11
+
12
+ ```shell
13
+ tee ~/.bitbar/pomodoro.1s.sh <<EOF
14
+ #!/bin/sh
15
+
16
+ log-time --bitbar
17
+ EOF
18
+ ```
19
+
20
+ ![](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/more-than-5m.png)
21
+ ![](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/less-than-5m.png)
22
+
23
+ ## ZSH prompt.
24
+
25
+ ![](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/prompt.png)
26
+
27
+ ## Limiting online access
28
+
29
+ _TODO_
30
+ This is why I wrote it in the first place.
31
+
32
+ ## OS X notifications
33
+
34
+ `~/Library/LaunchAgents/botanicus.pomodoro_notification.plist`
35
+
36
+ ```xml
37
+ <?xml version="1.0" encoding="UTF-8"?>
38
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
39
+ <plist version="1.0">
40
+ <dict>
41
+ <key>Label</key>
42
+ <string>botanicus.pomodoro_notification</string>
43
+
44
+ <key>ProgramArguments</key>
45
+ <array>
46
+ <string>zsh</string>
47
+ <string>-c</string>
48
+ <string>pomodoro-loop</string>
49
+ </array>
50
+
51
+ <key>RunAtLoad</key>
52
+ <true />
53
+
54
+ <key>KeepAlive</key>
55
+ <true />
56
+
57
+ <!-- I don't have permissions to write into /var/log. -->
58
+ <key>StandardOutPath</key>
59
+ <string>/tmp/botanicus.pomodoro_notification.stdout</string>
60
+ <key>StandardErrorPath</key>
61
+ <string>/tmp/botanicus.pomodoro_notification.stderr</string>
62
+ </dict>
63
+ </plist>
64
+ ```
65
+
66
+ ```shell
67
+ launchctl load -w ~/Library/LaunchAgents/botanicus.pomodoro_notification.plist
68
+ ```
data/doc/rules.md ADDED
File without changes
data/doc/schedules.md ADDED
File without changes
data/doc/terms.md ADDED
@@ -0,0 +1,32 @@
1
+ ### Time frames (not the same as time boxes for tasks)
2
+
3
+ I always had some kind of semi-functional task list in place, but my work organisation
4
+ was still hardly existent at all. It wasn't until I started to use time framing that this changed.
5
+
6
+ Time frame is a block of time you give to a project. Your schedule is then time frames of a day
7
+
8
+ ```
9
+ Morning routine (from 7:50)
10
+ Admin (from 9:20)
11
+ Work for client 1 (10:00 – 12:00)
12
+ Lunch break (12:00 – 13)
13
+ Work for client 2 (13 – 18)
14
+ ```
15
+
16
+ ### Schedules
17
+
18
+ You are likely to have more schedules than one. I have one for Tuesday when I have
19
+ a class from 6 and therefore I have to move my work session earlier, one for Wednesday
20
+ when I have my Spanish class in the morning, one for the other work days,
21
+ one for Saturday and one for Sunday.
22
+
23
+ Using the [holidays gem](https://github.com/holidays/holidays) you can easily
24
+ chose your Sunday schedule for a bank holiday.
25
+
26
+ I have a different morning routine on Mondays and Thursdays, I go swimming, but
27
+ since it fits into the given time frame, I do this in automatically scheduled tasks
28
+ while keeping the schedule the same.
29
+
30
+ ### Automatically scheduled tasks
31
+
32
+ ### Scheduled tasks
data/doc/workflow.md ADDED
@@ -0,0 +1,60 @@
1
+ _This document is WIP._
2
+
3
+ ## The workflow
4
+
5
+ _If you don't understand any term, read [terms](https://github.com/botanicus/now-task-manager/blob/master/doc/terms.md)_
6
+
7
+ ![Workflow diagram](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/diagram.png)
8
+
9
+ ### Planning
10
+
11
+ In the evening you'll do `pomodoro edit tomorrow`. This will check your schedules and picks one to use. Schedule is a list of time frames, for instance for a work day we could have something like this:
12
+
13
+ ```
14
+ Morning routine (from 7:50)
15
+ Work for client 1 (9:20 – 12:00)
16
+ Lunch break (12:00 – 13)
17
+ Work for client 2 (13 – 18)
18
+ ```
19
+
20
+ Then it will try to prepopulate the schedule with tasks. There will be various sources:
21
+
22
+ - The scheduled lists.
23
+ - Automatically scheduled tasks.
24
+ - Unfinished tasks from today and postponed tasks.
25
+
26
+ ## Doing
27
+
28
+ 3. Next day you simply start getting through your list using `pomodoro next` and `pomodoro complete` (as well as `pomodoro postpone` and `pomodoro move_on`).
29
+
30
+ The tasks will be looked for in the current time frame. That is even if you have unfinished tasks, if a new time frame started, the tool will pick a task from the newly started one.
31
+
32
+ ### Today tasks
33
+
34
+ ![](https://raw.githubusercontent.com/botanicus/now-task-manager/master/doc/img/today-annotated.png)
35
+
36
+ - Tasks are stored in readable plain text format.
37
+ - Command-line interface.
38
+ - [Vim plugin](https://github.com/botanicus/now-task-manager/tree/master/support/vim).
39
+ - BitBar plugin.
40
+
41
+ ### Scheduled tasks
42
+
43
+ Scheduled tasks are either scheduled for a certain **date** (tomorrow, next Friday etc), for a ceratin **context** (next time I'm in Prague etc) or just generally for **later**.
44
+
45
+ ```
46
+ Tomorrow
47
+ - Buy milk.
48
+
49
+ Prague
50
+ - Pick up my shoes.
51
+
52
+ Later
53
+ - Fix the expense gem.
54
+ ```
55
+
56
+ That's all there is to it. It's a simple text file and you can edit it to your liking.
57
+
58
+ The only shortcut you get is `pomodoro + Another task.` which will add a task to the list for later.
59
+
60
+ _**Read next**: [getting started](https://github.com/botanicus/now-task-manager/blob/master/doc/getting-started.md)_
data/lib/pomodoro.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'pomodoro/config'
2
+ require 'pomodoro/parser/today_parser'
3
+ require 'pomodoro/parser/today_transformer'
4
+ require 'pomodoro/parser/task_list_parser'
5
+ require 'pomodoro/parser/task_list_transformer'
6
+ require 'pomodoro/task_list'
@@ -0,0 +1,87 @@
1
+ require 'pomodoro/exts/hour'
2
+
3
+ module Pomodoro
4
+ module Commands
5
+ class BitBar
6
+ def self.heading(current_time_frame)
7
+ if current_time_frame
8
+ self.heading_work_in_progress(current_time_frame)
9
+ else
10
+ ['black', self.heading_default_icon]
11
+ end
12
+ end
13
+
14
+ def self.heading_default_icon
15
+ "| image=iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACx1BMVEUAAAAhZ5QmerEmgLkmgLomgLomgLomgLomgLomgLkme7EhZ5QAAAAeYYwlerIcWogZTHkaTn0aTn0aTn0aTn0aTn0aTXocW4klerIfYYwicaUaZJtRXGurrLCur7NWYW4aZZoicaUhcacUWpN7hZWCi5gWXJQhcKcebqUTWZN9h5eDjJsUW5UebqUca6QRV5N8h5eDjJoSWZQca6QaaKMPVZJ8h5eDjJoQV5QaaKMXZqINU5F8h5eDjJoPVZMXZqIVY6AMUZB8h5eDjJoNU5IVY6ETX58LTo98h5eDjJoMUJATX58SXJwKTI18h5eDjJoLTo8SXJwRWJoJSYx9h5eDjJoKS40RWJsQVJcKSYx/iJeBipcKSY0QVJcORHwNU50yUnlVaYZTaIVTaIVTaIVTaIVTaIVUaIUwUXcNU50ORH0GGzENRH8LUZ0JUKAJUaEJUaEJUaEJUaEJUaEJUKALUZ4NRH8GHDIAAAADDBcIJUYILFQILFQILFQILFQILFQILFQILFQIJUYDDRgAAACxs7ewsrewsrewsrexs7f29fT19PT09PT09PT09PT09PT29fX39vb39vX19PPy8vLy8vLy8vLy8vL09PTf39/Jycny8fD19PPy8vLz8/Py8vLy8vLy8vK1tbVeXl6wsLD19fT19PPq6ura2trz8/Py8vKlpaVISEisrKzy8vL19fT29vXS0tJeXl60tLS0tLRFRUWlpaX09PTy8vL19PT19PPx8fGfn59JSUlISEiGhobv7+/z8/Py8vL19PT19PPz8/Pu7u6Pj49lZWXd3d309PTy8vLy8vL19PT19PPy8vLz8/Pl5eXMzMzy8vLy8vLy8vLy8vL19PT19PPy8vLy8vLz8/P09PTy8vLy8vLy8vLy8vL19fTz8e/v7u3v7u3v7u3v7u3v7u3v7u3v7u3v7u3y8e////+EY5Z8AAAAhXRSTlMDW8nf3t7e3t7fylwESeT////////////lS5b///////+YpP////+kpP////+kpP////+kpP////+kpP////+kpP////+kpP////+kpP////+kpP////+ko/////+jhf7////////////+hi3A+/7+/v7+/v77wi8AMomjpKSkpKSjiTMB0B5+TQAAAAFiS0dE7CG5sxsAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfhAhQRBSmWVlRBAAABG0lEQVQY0wEQAe/+AAABAgMEBQYGBgYHCAkKCwwADQ4PEBESExMTExQVFhcYGQAaGxwdhYaHh4eHiIkeHyAhACIjJIqLjI2Njo+QkZIlJicAKCkqk5SVlZaXmJmamyssLQAuLzCcnZ6foKGio6SlMTIzADQ1NqanqKmqq6ytrq83ODkAOjs8sLGys7S1tre4uT0+PwBAQUK6u7y9vr/AwcLDQ0RFAEZHSMTFxsfIycrLzM1JSksATE1Ozs/Q0dLT1NXW109QUQBSU1TY2drb3N3e3+DhVVZXAFhZWuLj5OXm5+jp6utbXF0AXl9gYWJjZGRkZGVmZ2hpagBrbG1ub3BxcXFxcnN0dXZ3AHh5ent8fX5+fn5/gIGCg4Sov3NOEAy3KQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0yMFQxNzowNTo0MS0wNTowMHrHzbIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMjBUMTc6MDU6NDEtMDU6MDALmnUOAAAAAElFTkSuQmCC"
16
+ end
17
+
18
+ def self.heading_work_in_progress(current_time_frame)
19
+ colour = self.colour_based_on_remaining_duration(current_time_frame)
20
+ [colour, "#{current_time_frame.name} | color=#{colour}"]
21
+ end
22
+
23
+ def self.colour_based_on_remaining_duration(current_time_frame)
24
+ if current_time_frame.remaining_duration.nil?
25
+ 'gray'
26
+ elsif current_time_frame.remaining_duration < Hour.new(0, 10)
27
+ 'red'
28
+ elsif current_time_frame.remaining_duration < Hour.new(0, 30)
29
+ 'blue'
30
+ else
31
+ 'green'
32
+ end
33
+ end
34
+
35
+ def self.with_active_time_frame(current_time_frame)
36
+ if current_time_frame
37
+ if current_time_frame.interval[1]
38
+ puts "#{current_time_frame.interval[0]}-#{current_time_frame.interval[1]} (#{current_time_frame.remaining_duration}h remaining) | color=#{colour}"
39
+ else
40
+ puts "After #{current_time_frame.interval[0]} | color=gray"
41
+ end
42
+ current_time_frame.tasks.each do |task|
43
+ colour = {unstarted: 'blue', in_progress: 'red', finished: 'gray', postponed: 'gray'}[task.status]
44
+ puts "#{task} | color=#{colour}"
45
+ end
46
+ elsif Time.now.hour < 14
47
+ today_tasks.each do |time_frame|
48
+ task_lines = time_frame.to_s.split("\n")[1..-1]
49
+ puts "#{time_frame.header} | color=#{task_lines.empty? ? 'gray' : 'green'}"
50
+ puts task_lines.map { |line| "#{line} | color=black" }.join("\n").gsub(/^- /, '-- ')
51
+ end
52
+ puts "Total: XYZ | colour=gray"
53
+ else
54
+ puts "Hours worked: #{Hour.new(0, today_tasks.duration)}"
55
+ end
56
+ end
57
+
58
+ def self.main(today_tasks, task_list)
59
+ if today_tasks && current_time_frame = today_tasks.get_current_time_frame
60
+ colour, icon = self.heading(current_time_frame)
61
+ puts icon, '---'
62
+ self.with_active_time_frame(current_time_frame)
63
+ elsif today_tasks
64
+ colour, icon = self.heading(nil)
65
+ puts icon, '---'
66
+ puts 'TODO: Some day summary and possibly show tomorrow.'
67
+ else
68
+ colour, icon = self.heading(nil)
69
+ puts icon, '---'
70
+ puts "Run 'pomodoro e' to add some tasks. | color=green"
71
+ end
72
+
73
+ if task_list && task_list.any? { |task_group| ! task_group.tasks.empty? }
74
+ puts "Scheduled tasks"
75
+ task_list.each do |task_group|
76
+ unless task_group.tasks.empty?
77
+ puts "-- #{task_group.name}"
78
+ task_group.tasks.each do |task|
79
+ puts "---- #{task} | color=black"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,30 @@
1
+ require 'yaml'
2
+
3
+ module Pomodoro
4
+ class Config
5
+ CONFIG_PATH ||= File.expand_path('~/.config/pomodoro.yml')
6
+
7
+ def initialize
8
+ @data ||= YAML.load_file(CONFIG_PATH)
9
+ rescue
10
+ @data ||= Hash.new
11
+ end
12
+
13
+ {
14
+ task_list_path: '~/pomodoro/tasks.todo',
15
+ today_path: '~/pomodoro/%Y-%m-%d.today',
16
+ schedule_path: '~/pomodoro/schedule.rb',
17
+ routine_path: '~/pomodoro/routine.rb'
18
+ }.each do |key, default_value|
19
+ define_method(key) do |time = Time.now|
20
+ path = @data[key.to_s] || default_value
21
+ path = File.expand_path(time.strftime(path))
22
+ if File.exist?(File.expand_path("#{path}/.."))
23
+ path
24
+ else
25
+ raise "No #{key} found. Either create #{default_value} or add #{key} into #{CONFIG_PATH} pointing the the actual path."
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end