dayrb 2.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/LICENSE +8 -0
- data/Rakefile +118 -0
- data/VERSION +1 -0
- data/bin/day.rb +144 -0
- data/changelog.md +100 -0
- data/dayrb.gemspec +14 -0
- data/lib/day/configuration.rb +140 -0
- data/lib/day/parser.rb +168 -0
- data/lib/day/presenter.rb +223 -0
- data/lib/day/task.rb +44 -0
- data/lib/day/tasklist.rb +44 -0
- data/readme.md +53 -0
- data/spec/configuration_spec.rb +142 -0
- data/spec/parser_spec.rb +191 -0
- data/spec/spec_helper.rb +35 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 24d90143cff6a871b07c09646fcd44dbb01e4fe0
|
4
|
+
data.tar.gz: 13093c6ae051e3c92a97b8f2bc4411d87f12ef71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28521616cd3e8ef9641d9729a19663a5b059f049a56ea652be9a5a2e24b507162d8629005e69b6cc6e44e067f0cd6642363e20eb719e4750bdd411f4cd8e6b11
|
7
|
+
data.tar.gz: 474459e87e7a6e9b3a09d1511407f179c86b160f8be7fcb924a0b014a0331b60700f6ee4ec056730f78a21ec0b2abda1807e4bc724875ca5156db479b8078ea8
|
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
Copyright © 2014 Cameron Carroll, http://ckcarroll.herokuapp.com
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Rakefile for day.rb
|
2
|
+
# Author: Cameron Carroll; December 2013
|
3
|
+
# Purpose: Compiles a single-file version of the program for easy distribution and installation.
|
4
|
+
# Also increments version numbers based on VERSION file.
|
5
|
+
|
6
|
+
puts "Day.rb Build Tool"
|
7
|
+
puts "-----------------"
|
8
|
+
|
9
|
+
task :default => [:update_version, :compile]
|
10
|
+
|
11
|
+
task :update_version do
|
12
|
+
current_version = nil
|
13
|
+
open('VERSION', 'r') do |file|
|
14
|
+
current_version = file.gets
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Current Version: #{current_version}"
|
18
|
+
|
19
|
+
split_version = current_version.split('.')
|
20
|
+
|
21
|
+
next_patch_version = update_patch(split_version, 1)
|
22
|
+
previous_patch_version = update_patch(split_version, -1)
|
23
|
+
|
24
|
+
next_minor_version = update_minor(split_version, 1)
|
25
|
+
previous_minor_version = update_minor(split_version, -1)
|
26
|
+
|
27
|
+
next_major_version = update_major(split_version, 1)
|
28
|
+
previous_major_version = update_major(split_version, -1)
|
29
|
+
|
30
|
+
previous_versions = [previous_patch_version, previous_minor_version, previous_major_version]
|
31
|
+
next_versions = [next_patch_version, next_minor_version, next_major_version]
|
32
|
+
|
33
|
+
# Unlikely to happen, but if the source files get ahead of VERSION file we should warn and break.
|
34
|
+
next_versions.each do |version|
|
35
|
+
next_version_in_dayrb = `grep #{version} day.rb`.length > 0
|
36
|
+
next_version_in_readme = `grep #{version} readme.md`.length > 0
|
37
|
+
|
38
|
+
if next_version_in_dayrb || next_version_in_readme
|
39
|
+
puts "VERSION file is behind source files! Breaking; Please fix manually."
|
40
|
+
abort
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
old_version_in_readme, old_version_in_dayrb, old_version = nil, nil, nil
|
46
|
+
|
47
|
+
# Check authoritative version source (VERSION file) against source files.
|
48
|
+
# If source files have an older version, update it.
|
49
|
+
previous_versions.each do |version|
|
50
|
+
unless old_version_in_dayrb && old_version_in_readme
|
51
|
+
old_version_in_dayrb = `grep #{version} day.rb`.length > 0
|
52
|
+
old_version_in_readme = `grep #{version} readme.md`.length > 0
|
53
|
+
old_version = version if old_version_in_readme || old_version_in_dayrb
|
54
|
+
puts "Version in question: " + version if old_version
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
if old_version_in_dayrb
|
60
|
+
puts "Replacing version #{old_version} with #{current_version} in day.rb"
|
61
|
+
`sed -i 's/#{old_version}/#{current_version}/g' day.rb`
|
62
|
+
end
|
63
|
+
|
64
|
+
if old_version_in_readme
|
65
|
+
today_date = Time.new.strftime("%m/%d/%y")
|
66
|
+
puts "Replacing version #{old_version} with #{current_version} in readme.md"
|
67
|
+
puts "Replacing old date with #{today_date} in day.rb"
|
68
|
+
`sed -i 's/#{old_version}/#{current_version}/g' readme.md`
|
69
|
+
`sed -i 's%[0-9][0-9]/[0-9][0-9]/[0-9][0-9])%#{today_date})%' readme.md`
|
70
|
+
end
|
71
|
+
|
72
|
+
if !old_version_in_dayrb && !old_version_in_readme
|
73
|
+
puts "Didn't find any version errors."
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
task :compile do
|
78
|
+
`mkdir -p "build"`
|
79
|
+
target = "build/day.rb"
|
80
|
+
|
81
|
+
`cat /dev/null > #{target}`
|
82
|
+
|
83
|
+
# First we need to find out where to cut day.rb...
|
84
|
+
cut_line = `grep -n "CUT HERE" day.rb`.split(':').first
|
85
|
+
|
86
|
+
# Then we need to get the first chunk of day.rb, which includes intro comments
|
87
|
+
# and user configuration.
|
88
|
+
# But we want to strip off the require statements and the whitespace leftover.
|
89
|
+
`awk 'NR >= 1 && NR <= #{cut_line}' day.rb | sed 's/require_relative.*//g' | uniq >> #{target}`
|
90
|
+
|
91
|
+
# Add all library files:
|
92
|
+
FileList['lib/*.rb'].each do |source|
|
93
|
+
`cat #{source} >> #{target}`
|
94
|
+
`echo "\n" >> #{target}`
|
95
|
+
end
|
96
|
+
|
97
|
+
# Now finally we want to add the remaining body of day.rb
|
98
|
+
lines_in_dayrb = `wc -l day.rb`.to_i
|
99
|
+
`awk 'NR >= #{cut_line} && NR <= #{lines_in_dayrb+1}' day.rb >> #{target}`
|
100
|
+
end
|
101
|
+
|
102
|
+
def update_patch(split_version, increment)
|
103
|
+
different_patch = split_version[2].to_i + increment
|
104
|
+
different_patch_version = split_version[0..1].push(different_patch)
|
105
|
+
different_patch_version.join('.')
|
106
|
+
end
|
107
|
+
|
108
|
+
def update_minor(split_version, increment)
|
109
|
+
different_minor = split_version[1].to_i + increment
|
110
|
+
different_minor_version = [split_version[0],different_minor,split_version[2]]
|
111
|
+
different_minor_version.join('.')
|
112
|
+
end
|
113
|
+
|
114
|
+
def update_major(split_version, increment)
|
115
|
+
different_major = split_version[0].to_i + increment
|
116
|
+
different_major_version = split_version[1,2].unshift(different_major)
|
117
|
+
different_major_version.join('.')
|
118
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.1
|
data/bin/day.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# DayRB Main File
|
4
|
+
# Day.rb is a minimalistic command-line to-do and time-tracking application.
|
5
|
+
# Created in July 2013
|
6
|
+
# See 'day.rb help' for usage.
|
7
|
+
#
|
8
|
+
# MIT License; See LICENSE file; Cameron Carroll 2014
|
9
|
+
|
10
|
+
require_relative '../lib/day/configuration'
|
11
|
+
require_relative '../lib/day/tasklist'
|
12
|
+
require_relative '../lib/day/parser'
|
13
|
+
require_relative '../lib/day/presenter'
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
|
17
|
+
VERSION = '2.0.1'
|
18
|
+
|
19
|
+
#-------------- User Configuration:
|
20
|
+
#-------------- Please DO edit the following to your liking:
|
21
|
+
|
22
|
+
# Configuration File: Stores tasks and their data
|
23
|
+
CONFIG_DIR = ENV['HOME'] + '/.config/dayrb/'
|
24
|
+
CONFIG_FILE = CONFIG_DIR + 'daytodo'
|
25
|
+
|
26
|
+
# Colorization:
|
27
|
+
# Use ANSI color codes...
|
28
|
+
# (See http://bluesock.org/~willg/dev/ansi.html for codes.)
|
29
|
+
# (Change values back to 0 for no colorization.)
|
30
|
+
COMPLETION_COLOR = 0 # -- Used for completion printouts
|
31
|
+
CONTEXT_SWITCH_COLOR = 0 # -- Used to declare `Enter/Exit Context'
|
32
|
+
STAR_COLOR = 0 # -- Used for the description indicator star
|
33
|
+
TITLE_COLOR = 0 # -- Used for any titles
|
34
|
+
TEXT_COLOR = 0 # -- Used for basically everything that doesn't fit under the others.
|
35
|
+
INDEX_COLOR = 0 # -- Used for the index key which refers to tasks.
|
36
|
+
TASK_COLOR = 0 # -- Used for task name in printouts.
|
37
|
+
|
38
|
+
# Editor constant. Change to your preferred editor for adding descriptions.
|
39
|
+
EDITOR = 'vim'
|
40
|
+
|
41
|
+
#--------------
|
42
|
+
|
43
|
+
#[CUT HERE] Used in build script. Please don't remove.
|
44
|
+
|
45
|
+
#-------------- Monkey-Patch Definitions:
|
46
|
+
|
47
|
+
class String
|
48
|
+
def nan?
|
49
|
+
self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
|
50
|
+
end
|
51
|
+
|
52
|
+
def number?
|
53
|
+
!self.nan?
|
54
|
+
end
|
55
|
+
|
56
|
+
def colorize(color_code)
|
57
|
+
"\e[#{color_code}m#{self}\e[0m"
|
58
|
+
end
|
59
|
+
|
60
|
+
def color_completion
|
61
|
+
colorize(COMPLETION_COLOR)
|
62
|
+
end
|
63
|
+
|
64
|
+
def color_context_switch
|
65
|
+
colorize(CONTEXT_SWITCH_COLOR)
|
66
|
+
end
|
67
|
+
|
68
|
+
def color_star
|
69
|
+
colorize(STAR_COLOR)
|
70
|
+
end
|
71
|
+
|
72
|
+
def color_title
|
73
|
+
colorize(TITLE_COLOR)
|
74
|
+
end
|
75
|
+
|
76
|
+
def color_text
|
77
|
+
colorize(TEXT_COLOR)
|
78
|
+
end
|
79
|
+
|
80
|
+
def color_index
|
81
|
+
colorize(INDEX_COLOR)
|
82
|
+
end
|
83
|
+
|
84
|
+
def color_task
|
85
|
+
colorize(TASK_COLOR)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#-------------- Application Logic:
|
90
|
+
|
91
|
+
FileUtils.mkdir_p(CONFIG_DIR) unless Dir.exists? CONFIG_DIR
|
92
|
+
|
93
|
+
db = YAML::DBM.new(CONFIG_FILE)
|
94
|
+
config = Configuration.new(db)
|
95
|
+
opts = Parser.parse_options(config)
|
96
|
+
|
97
|
+
# Build task objects and separate into two lists, valid today and all tasks.
|
98
|
+
tasklist_object = Tasklist.new(config)
|
99
|
+
all_tasks = tasklist_object.all_tasks
|
100
|
+
valid_tasks = tasklist_object.valid_tasks
|
101
|
+
|
102
|
+
# Include either all days ("-a" flag) or just valid daily tasks:
|
103
|
+
if opts[:all]
|
104
|
+
tasklist = all_tasks
|
105
|
+
else
|
106
|
+
tasklist = valid_tasks
|
107
|
+
end
|
108
|
+
|
109
|
+
# Easier (named) access to config and opts:
|
110
|
+
new_context = opts[:task]
|
111
|
+
current_context = config.data['context']
|
112
|
+
old_time = Time.now - config.data['entry_time'] if config.data['entry_time']
|
113
|
+
|
114
|
+
# Take action based on operation:
|
115
|
+
case opts[:operation]
|
116
|
+
when :print
|
117
|
+
Presenter.print_list(tasklist, current_context, old_time)
|
118
|
+
when :print_info
|
119
|
+
Presenter.print_info(tasklist, new_context)
|
120
|
+
when :print_help
|
121
|
+
Presenter.print_help
|
122
|
+
when :print_version
|
123
|
+
Presenter.print_version
|
124
|
+
when :new
|
125
|
+
Presenter.announce_new_task(new_context)
|
126
|
+
config.new_task(opts)
|
127
|
+
when :switch
|
128
|
+
Presenter.announce_switch(new_context, current_context, old_time)
|
129
|
+
config.switch_to(new_context)
|
130
|
+
when :clear
|
131
|
+
Presenter.announce_clear(new_context)
|
132
|
+
config.clear_fulfillment(new_context)
|
133
|
+
when :leave
|
134
|
+
Presenter.announce_leave_context(current_context, old_time)
|
135
|
+
config.clear_context
|
136
|
+
when :delete
|
137
|
+
Presenter.announce_deletion(new_context, config.data['tasks'][new_context]['description'])
|
138
|
+
config.delete(new_context)
|
139
|
+
else
|
140
|
+
Presenter.print_error_unknown
|
141
|
+
end
|
142
|
+
|
143
|
+
config.save
|
144
|
+
db.close
|
data/changelog.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
2.0.1 -- 08/12/14
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* Makes sure data store directory exists.
|
5
|
+
|
6
|
+
2.0.0 -- 08/11/14
|
7
|
+
------------------
|
8
|
+
|
9
|
+
### Feature Additions:
|
10
|
+
|
11
|
+
* Added "-a" / "-A" flag, for "all tasks." This allows you to see tasks that aren't enabled for today.
|
12
|
+
* You can now refer to tasks by name rather than only by numerical index.
|
13
|
+
|
14
|
+
### Deprecations:
|
15
|
+
|
16
|
+
* Removed DESCRIPTION flag and deprecated its functionality, which would print full descriptions instead of asterisk in the tasklist.
|
17
|
+
|
18
|
+
### Internal Changes:
|
19
|
+
|
20
|
+
* Major internal rewrite; Disassembled god class (List) and also significantly simplified the configuration. (One module and YAML/DBM instead of three modules and hand-rolled YAML file access.)
|
21
|
+
* Separated all printing logic into presenter module.
|
22
|
+
* Separated all DB access logic into configuration module.
|
23
|
+
* Created Tasklist to manage task objects and maintain lists of valid tasks and all tasks.
|
24
|
+
* Wrote specs for Configuration and Parser.
|
25
|
+
* Added YARD-style documentation to all methods and classes.
|
26
|
+
|
27
|
+
1.9.1 -- 1/21/14
|
28
|
+
-------------------
|
29
|
+
|
30
|
+
* Added editor-based descriptions: Define EDITOR in user config section and then include it in the new_task arglist to launch editor and capture description.
|
31
|
+
* Times printed out in certain places are converted to minutes/hours/days as appropriate.
|
32
|
+
* Added colorization on index key and task names in printout.
|
33
|
+
* Some internal upgrades (refactoring, spacing issues, etc.)
|
34
|
+
|
35
|
+
1.8.1 -- 12/30/13
|
36
|
+
-------------------
|
37
|
+
|
38
|
+
* Add "(No tasks in list.)" declaration so that the program always has SOME output.
|
39
|
+
* Removed extra newline after task list printout. (Just trying to make thins look cleaner and more compact.)
|
40
|
+
* Fixed build tool; Added a CUT HERE comment to day.rb which the build tool uses to split the file.
|
41
|
+
* Updated build tool :update_version task to handle SemVer.
|
42
|
+
|
43
|
+
1.8 -- 12/28/13
|
44
|
+
-------------------
|
45
|
+
|
46
|
+
* Removed unused 'commit' command code.
|
47
|
+
* Added VERSION file to act as authoritative version source.
|
48
|
+
* Added Rakefile to build project, incrementing version and date and also building one-file distributable.
|
49
|
+
* Added string helper String.number? to avoid !nan? double negative & clarifying intention.
|
50
|
+
* Added a general 'info' command which prints out all descriptions.
|
51
|
+
* Updated options parsing when creating a new task so that everything after task name can be in any order. (Previously, the description had to come first.)
|
52
|
+
* Added a very rudimentary help command and version printout command.
|
53
|
+
* Added task-specific fulfillment clear function rather than forcing clear on all of them.
|
54
|
+
|
55
|
+
1.7 -- 12/18/13
|
56
|
+
-------------------
|
57
|
+
|
58
|
+
* Changed 'info' command behavior to print out task title instead of just declaring `Description:'.
|
59
|
+
* Added aliases: 'c' for clear, 'i' for info and 'rm' for delete
|
60
|
+
* Added colorized output, but it's off by default. (I didn't want to make any assumptions regarding readability.) Colored output can be configured for titles, enter/exits, completion printouts, and the description-indicating star specifically, as well as all of the remaining text generally.
|
61
|
+
* Cleaned up some cosmetic issues in code and comments, and a tiny typo in readme.
|
62
|
+
* Updated error messages for clarity, verbosity, and style.
|
63
|
+
* Extended list of enabled-day glyphs to include more partial-spellings of day names.
|
64
|
+
|
65
|
+
1.6 -- 11/05/13
|
66
|
+
-------------------
|
67
|
+
|
68
|
+
* Removed bundler dependency, deleted Gemfile. (Literally the only dependency was bundler itself. I guess hardly anyone will NOT have bundler, but nevertheless it's useless and gone.)
|
69
|
+
|
70
|
+
1.5 -- 10/29/13
|
71
|
+
-------------------
|
72
|
+
|
73
|
+
* Changed wording in program to use estimates instead of commitments.
|
74
|
+
* Added optional descriptions for tasks.
|
75
|
+
* Added info command to print out descriptions without checking-in.
|
76
|
+
|
77
|
+
1.4 -- 9/13/13
|
78
|
+
-------------------
|
79
|
+
|
80
|
+
* Fixed daily fulfillments. Previously every time you exited a context it would reset the daily fulfillment counter.
|
81
|
+
* Changed all time printouts to use 1 digit past the decimal.
|
82
|
+
* Tracks and displays daily fulfillment for tasks that don't have commitments.
|
83
|
+
|
84
|
+
1.3 -- 8/27/13
|
85
|
+
-------------------
|
86
|
+
|
87
|
+
* Printout will now clearly show tasks with commitments but no fulfillments.
|
88
|
+
* Only update fulfillment on tasks that actually have commitments
|
89
|
+
* Added day_fulfillment property on all tasks which resets every day and prints out how much progress you've made today.
|
90
|
+
|
91
|
+
1.2 -- 8/23/13
|
92
|
+
-------------------
|
93
|
+
|
94
|
+
* Only display tasks if their specified days are blank or include today
|
95
|
+
|
96
|
+
1.1 -- 8/23/13
|
97
|
+
-------------------
|
98
|
+
|
99
|
+
* Task list printout will now give progress on current task.
|
100
|
+
|
data/dayrb.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'dayrb'
|
3
|
+
s.version = '2.0.2'
|
4
|
+
s.summary = "To-do & Time-Tracking CLI App"
|
5
|
+
s.description = "Create and track time on tasks via command-line."
|
6
|
+
s.authors = ["Cameron Carroll"]
|
7
|
+
s.email = 'ckcarroll4@gmail.com'
|
8
|
+
s.files = `git ls-files`.split($/)
|
9
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
10
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
11
|
+
s.homepage =
|
12
|
+
'http://github.com/sanarothe/day'
|
13
|
+
s.license = 'MIT'
|
14
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# DayRB Configuration (Data-Access Layer) Module
|
2
|
+
#
|
3
|
+
# Provides convenience methods for database access and holds db data.
|
4
|
+
#
|
5
|
+
# MIT License; See LICENSE file; Cameron Carroll 2014
|
6
|
+
|
7
|
+
require 'yaml/dbm'
|
8
|
+
|
9
|
+
# Config class handles access to our config file, which mostly just provides a data-access layer.
|
10
|
+
# Schema:
|
11
|
+
# configuration = {
|
12
|
+
# context = :task_key,
|
13
|
+
# entry_time = :task_start_time
|
14
|
+
# tasks = {
|
15
|
+
# :key => {
|
16
|
+
# :description => (string),
|
17
|
+
# :active_days => [(keys of active days)],
|
18
|
+
# :estimate => (integer in minutes),
|
19
|
+
# :fulfillment => (integer in minutes)
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
# }
|
23
|
+
|
24
|
+
class Configuration
|
25
|
+
attr_reader :data, :context, :entry_time
|
26
|
+
|
27
|
+
# Load DB data and bootstrap it if empty.
|
28
|
+
#
|
29
|
+
# @param db [PSYCH::DBM] database (hash-like) initialized and closed by caller.
|
30
|
+
def initialize(db)
|
31
|
+
@db = db
|
32
|
+
@data = @db.to_hash
|
33
|
+
bootstrap_db if @data.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Interface to save_task which decomposes opts hash.
|
37
|
+
#
|
38
|
+
# @param opts [Hash] options hash containing input data
|
39
|
+
def new_task(opts)
|
40
|
+
save_task(opts[:task], opts[:description], opts[:days], opts[:estimate])
|
41
|
+
end
|
42
|
+
|
43
|
+
# Change context to a different task.
|
44
|
+
# (Saves fulfillment for previous task.)
|
45
|
+
#
|
46
|
+
# @param next_key [String] the name of the task to switch to.
|
47
|
+
def switch_to(next_key)
|
48
|
+
cap_current_fulfillment if @context
|
49
|
+
@data['context'] = next_key if @data['tasks'].has_key?(next_key)
|
50
|
+
@data['entry_time'] = Time.now.getutc
|
51
|
+
end
|
52
|
+
|
53
|
+
# Exit context without switching to a new one.
|
54
|
+
def clear_context()
|
55
|
+
cap_current_fulfillment
|
56
|
+
@data['context'], @data['entry_time'] = nil, nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Clear fulfillment for one or all tasks.
|
60
|
+
#
|
61
|
+
# @param task [String] valid task name to specify action for (defaults to all otherwise)
|
62
|
+
def clear_fulfillment(task)
|
63
|
+
if task
|
64
|
+
clear_fulfillment_for task
|
65
|
+
else
|
66
|
+
@data['tasks'].each do |task, task_data|
|
67
|
+
clear_fulfillment_for task
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Remove a task from config object data.
|
73
|
+
# (Note that this doesn't persist to the DBM files by itself...
|
74
|
+
# And again, the responsibility for calling save() and closing DB lies
|
75
|
+
# with the consumer of this class.)
|
76
|
+
#
|
77
|
+
# @param task_key [String] Valid task name to delete.
|
78
|
+
def delete(task_key)
|
79
|
+
@data['tasks'].delete task_key
|
80
|
+
end
|
81
|
+
|
82
|
+
# Reload class objects from config data.
|
83
|
+
# (Used during testing.)
|
84
|
+
def reload()
|
85
|
+
@context = @data['context']
|
86
|
+
@entry_time = @data['entry_time']
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
# To be called at the very end of the script to write data back into YAML::DBM
|
91
|
+
def save()
|
92
|
+
@db.replace(@data)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Used to verify that a task actually exists and to cross-reference indices to names
|
96
|
+
#
|
97
|
+
# @param task [String] name or index reference to task
|
98
|
+
def lookup_task(task)
|
99
|
+
if task.number?
|
100
|
+
@data['tasks'].keys[task.to_i]
|
101
|
+
else
|
102
|
+
task if @data['tasks'].has_key? task
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Add a new task to the DB.
|
109
|
+
#
|
110
|
+
# @param task [String] the task name
|
111
|
+
# @param description [String] a text description (optional)
|
112
|
+
# @param valid_days [Array] contains keys corresponding to the valid days, ie ['monday', 'tuesday'] (optional)
|
113
|
+
# @param estimate [String] a time estimate in integer minutes.
|
114
|
+
def save_task(task, description, valid_days, estimate)
|
115
|
+
if task
|
116
|
+
@data['tasks'][task] = {'description' => description, 'valid_days' => valid_days,
|
117
|
+
'estimate' => estimate, 'fulfillment' => nil}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Builds initial structure for the database file.
|
122
|
+
def bootstrap_db
|
123
|
+
@data['context'] = nil
|
124
|
+
@data['entry_time'] = nil
|
125
|
+
@data['tasks'] = {}
|
126
|
+
end
|
127
|
+
|
128
|
+
# Add the elapsed time since entering a context. (Used when exiting that context.)
|
129
|
+
def cap_current_fulfillment
|
130
|
+
@data['tasks'][@data['context']]['fulfillment'] ||= 0
|
131
|
+
@data['tasks'][@data['context']]['fulfillment'] += Time.now - @data['entry_time']
|
132
|
+
end
|
133
|
+
|
134
|
+
# Actually modify fulfillment data for a task.
|
135
|
+
#
|
136
|
+
# @param task [String] Valid task name to verify data for.
|
137
|
+
def clear_fulfillment_for(task)
|
138
|
+
@data['tasks'][task]['fulfillment'] = nil
|
139
|
+
end
|
140
|
+
end
|