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 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
@@ -0,0 +1,11 @@
1
+ Gemfile.lock
2
+ TODO
3
+ test.rb
4
+ clear.rb
5
+ build/
6
+ *.db
7
+ tmp/
8
+ test/
9
+ doc/
10
+ .yardoc/
11
+ test_db*
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