trak 0.0.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.
- data/CHANGELOG.md +90 -0
- data/README.md +107 -0
- data/bin/trak +2 -0
- data/lib/trak.rb +168 -0
- data/lib/trak/blank.rb +16 -0
- data/lib/trak/round_to_nearest.rb +9 -0
- data/lib/trak/tracker_util.rb +103 -0
- metadata +83 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Change log
|
2
|
+
|
3
|
+
## v0.0.0 (2012-04-25)
|
4
|
+
|
5
|
+
Tracker is now known as trak, and it's a RubyGem!
|
6
|
+
|
7
|
+
Changed:
|
8
|
+
|
9
|
+
* Trak has now been ported from Perl to Ruby. The main reason for this
|
10
|
+
was for the ability to support the awesome gem Chronic for natural
|
11
|
+
language date parsing in an upcoming release. But beyond that,
|
12
|
+
RubyGems is fantastic for packaging and distribution and the plan is
|
13
|
+
to make this code seriously more modular over the next little while
|
14
|
+
(the code is a joke at the moment :O).
|
15
|
+
|
16
|
+
## v0.4 (2011-10-17)
|
17
|
+
|
18
|
+
Added:
|
19
|
+
|
20
|
+
* If the EDITOR environment variable is set, this is now used by default
|
21
|
+
to edit a log file with `track -e`.
|
22
|
+
|
23
|
+
* The current time is displayed at the end of the report, like so:
|
24
|
+
|
25
|
+
# Today's logged work
|
26
|
+
...
|
27
|
+
Hours logged until 9:30 AM (since 9:15 AM). Currently 10:13 AM.
|
28
|
+
|
29
|
+
## v0.3
|
30
|
+
|
31
|
+
Added:
|
32
|
+
|
33
|
+
* Report now calculates the total time spent on each task throughout the
|
34
|
+
day
|
35
|
+
* Time can now be logged as either minutes or hours. The time argument
|
36
|
+
can take the format `##<denom>`, where `##` is the amount of time
|
37
|
+
spent, and `<denom>` signifies hours (`h/hr/hour/hours`) or minutes
|
38
|
+
(`m/min/minute/minutes`).
|
39
|
+
|
40
|
+
Changed:
|
41
|
+
|
42
|
+
* Report formatting improvements
|
43
|
+
|
44
|
+
Fixed:
|
45
|
+
|
46
|
+
* Time wrap-around bug where if time logged passed midnight AM/PM would
|
47
|
+
display incorrectly.
|
48
|
+
|
49
|
+
## v0.2.1
|
50
|
+
|
51
|
+
Changed:
|
52
|
+
|
53
|
+
* Change log is now found in CHANGELOG.md rather than README.md.
|
54
|
+
|
55
|
+
Fixed:
|
56
|
+
|
57
|
+
* Fixed a bug where invoking with no arguments would create an entry in
|
58
|
+
the log with no time or message. No arguments is a synonym for `-l` or
|
59
|
+
`-r`.
|
60
|
+
|
61
|
+
## v0.2
|
62
|
+
|
63
|
+
Added:
|
64
|
+
|
65
|
+
* Tracker now automatically calculates the time you started your day
|
66
|
+
based on your first log for that day. This is stored in the time log
|
67
|
+
after the date, and used to calculate how far into the day you have
|
68
|
+
tracked time.
|
69
|
+
|
70
|
+
Changed:
|
71
|
+
|
72
|
+
* Everything after the first argument (the amount of time) is now
|
73
|
+
considered to be the task name (i.e., the task is no longer truncated
|
74
|
+
to the first word).
|
75
|
+
* Formatting improvements
|
76
|
+
|
77
|
+
## v0.1
|
78
|
+
|
79
|
+
Added:
|
80
|
+
|
81
|
+
* Tracker.pl -l will now tell you what time you've logged time until.
|
82
|
+
For example, if your start time is 8:00 AM and you've logged 3 hours,
|
83
|
+
it will output the following:
|
84
|
+
|
85
|
+
Hours logged until 11:00 AM (since 8:00 AM).
|
86
|
+
|
87
|
+
Changed:
|
88
|
+
|
89
|
+
* `-l` and `-r` switches are now synonyms
|
90
|
+
* Formatting improvements
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# Trak: track chunks of time from the command line
|
2
|
+
|
3
|
+
Trak, v0.0.0 (Apr 25, 2012)
|
4
|
+
Written by Adam Sharp
|
5
|
+
|
6
|
+
## Notice
|
7
|
+
|
8
|
+
Trak was recently (i.e., last week) a Perl script. It has been ported to
|
9
|
+
Ruby, but the code really looks like it's taken a beating and is
|
10
|
+
definitely NOT what I want it to ultimately look like. Much more
|
11
|
+
ruby-fying to happen yet, as well as support for the excellent
|
12
|
+
[Chronic](https://github.com/mojombo/chronic) gem for natural language
|
13
|
+
date parsing in the pipeline.
|
14
|
+
|
15
|
+
It's now structured as a RubyGem and should hopefully be available on
|
16
|
+
RubyGems soon.
|
17
|
+
|
18
|
+
Stay tuned.
|
19
|
+
|
20
|
+
## Description
|
21
|
+
|
22
|
+
Trak is a utility for Mac OS X that allows you to quickly make a record
|
23
|
+
of how much time you've spent on various tasks throughout the day.
|
24
|
+
|
25
|
+
Work logs are stored in `/Users/yourusername/Documents/Tracker/` with
|
26
|
+
the format `YEAR-MONTH-DAY-time-log.txt`.
|
27
|
+
|
28
|
+
An example work log that trak will create:
|
29
|
+
|
30
|
+
2011-09-01 9:00
|
31
|
+
30: nap
|
32
|
+
45: procrastinate
|
33
|
+
30: uni
|
34
|
+
120: trak
|
35
|
+
|
36
|
+
## Installation
|
37
|
+
|
38
|
+
Check out this repository and then create a symlink to bin/trak
|
39
|
+
somewhere in your path:
|
40
|
+
|
41
|
+
$ ln -s <repo>/bin/trak /usr/bin/trak
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
trak [-d|--date DATE] ##<denom> <description> # => data entry
|
46
|
+
trak [-d|--date DATE] [-r|-l] # => reporting
|
47
|
+
trak [-d|--date DATE] -e # => manually edit time log
|
48
|
+
|
49
|
+
Where:
|
50
|
+
|
51
|
+
* `##` is a decimal signifying how much time has been spent.
|
52
|
+
* `<denom>` is either hours (`h/hr/hour/hours`) or minutes
|
53
|
+
(`m/min/minute/minutes`). `<denom>` is optional and if ommitted,
|
54
|
+
Tracker will interpret the time entered as minutes.
|
55
|
+
* `<description>` is a string containing a brief description of the
|
56
|
+
activity.
|
57
|
+
* `DATE` is a string of the format `YYYY-MM-DD` which represents any
|
58
|
+
date. This effects any of Tracker's modes, i.e., insertion, editing or
|
59
|
+
reporting.
|
60
|
+
|
61
|
+
### Descriptions
|
62
|
+
|
63
|
+
You can use either
|
64
|
+
|
65
|
+
$ trak 30 "Foo bar"
|
66
|
+
|
67
|
+
or
|
68
|
+
|
69
|
+
$ trak 30 Foo bar
|
70
|
+
|
71
|
+
as everything after the first argument is considered the name of the
|
72
|
+
task.
|
73
|
+
|
74
|
+
### Entering time
|
75
|
+
|
76
|
+
These are all valid commands:
|
77
|
+
|
78
|
+
$ trak 1h Write trak documentation # => 1 hour
|
79
|
+
$ trak 30min Rewrite trak documentation # => 30 minutes
|
80
|
+
$ trak 4hours Refactor trak # => 4 hours
|
81
|
+
$ trak 15 Lunch # => 15 minutes
|
82
|
+
|
83
|
+
## To do
|
84
|
+
|
85
|
+
* Proper handling of incorrectly formatted dates
|
86
|
+
* Write a report that gives a weekly breakdown given a date in that week
|
87
|
+
* Add a `-h` usage/help switch
|
88
|
+
* Make the personal time search more configurable by putting keywords to
|
89
|
+
search in an array
|
90
|
+
* Have the different types of reports, and keywords for those reports,
|
91
|
+
completely stored in a configuration file. The last category in the
|
92
|
+
file is the default report. Because keywords for custom reports would
|
93
|
+
work on a whitelist system, everything that doesn't match goes into
|
94
|
+
the default. For example:
|
95
|
+
|
96
|
+
# Personal
|
97
|
+
lunch
|
98
|
+
uni
|
99
|
+
news
|
100
|
+
# Default
|
101
|
+
Work
|
102
|
+
|
103
|
+
* Have the keywords in the configuration file actually be regexes. When
|
104
|
+
reading the config file, any empty lines or whitespace are ignored.
|
105
|
+
* Give an estimate of completion time, with a configurable default for
|
106
|
+
the length of the work day. Also take into account the default length
|
107
|
+
of lunch break (configurable) if lunch hasn't yet been logged.
|
data/bin/trak
ADDED
data/lib/trak.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# command:
|
4
|
+
# $ Tracker.pl 30 "I did stuff"
|
5
|
+
# $ Tracker.pl 1h "I did twice as much stuff"
|
6
|
+
#
|
7
|
+
# format:
|
8
|
+
# - First arg is how much time spent
|
9
|
+
# - Second arg is a description
|
10
|
+
|
11
|
+
require 'trollop'
|
12
|
+
require 'debugger'
|
13
|
+
|
14
|
+
require "trak/tracker_util"
|
15
|
+
|
16
|
+
# place where data is stored
|
17
|
+
datadir = "#{ENV['HOME']}/Documents/Tracker/"
|
18
|
+
%x[mkdir -p #{datadir}]
|
19
|
+
|
20
|
+
# define command line options
|
21
|
+
opts = Trollop::options do
|
22
|
+
opt :report, "Reporting mode", :short => "-l"
|
23
|
+
opt :edit, "Edit mode"
|
24
|
+
opt :date, "The date", :type => String, :short => "-d"
|
25
|
+
opt :debug, "Debugging mode", :short => "-i"
|
26
|
+
end
|
27
|
+
|
28
|
+
$g_opts = opts
|
29
|
+
def debug(steps = 1)
|
30
|
+
debugger if $g_opts[:debug]
|
31
|
+
end
|
32
|
+
|
33
|
+
# all valid options have been processed, so figure out which mode
|
34
|
+
# we're in...
|
35
|
+
#
|
36
|
+
# if we found a -r or -l option, ignore everything else
|
37
|
+
if opts[:report]
|
38
|
+
MODE = 'report'
|
39
|
+
# now check if the user wants edit mode
|
40
|
+
elsif opts[:edit]
|
41
|
+
MODE = 'edit'
|
42
|
+
# if there are still unprocessed args (that didn't look like switches),
|
43
|
+
# we're in insert mode
|
44
|
+
elsif ARGV.length > 0
|
45
|
+
MODE = 'insert'
|
46
|
+
# if all else fails, there were probably no args to begin with, so we're
|
47
|
+
# in report mode
|
48
|
+
else
|
49
|
+
MODE = 'report'
|
50
|
+
end
|
51
|
+
|
52
|
+
today = Time.now.strftime '%F'
|
53
|
+
|
54
|
+
# did the user supply a date argument that isn't today?
|
55
|
+
if opts[:date] && opts[:date] != today
|
56
|
+
fdate = opts[:date]
|
57
|
+
# otherwise use today's date, formatted, and set date_arg to be false
|
58
|
+
else
|
59
|
+
fdate = today
|
60
|
+
opts[:date] = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# set the output file name
|
64
|
+
filename = "#{datadir}#{fdate}-time-log.txt"
|
65
|
+
|
66
|
+
if MODE == 'report'
|
67
|
+
if File.exist? filename
|
68
|
+
# open the file and get it as an array
|
69
|
+
begin
|
70
|
+
file = File.open(filename).readlines.map &:chomp
|
71
|
+
rescue
|
72
|
+
STDERR.puts "#{__FILE__}: #{$!}"
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
# The keys for each hash are the titles of the various tasks logged.
|
77
|
+
# The values are the total time spent on the task.
|
78
|
+
work = {}
|
79
|
+
personal = {}
|
80
|
+
|
81
|
+
# find the start time for the day we're reporting on
|
82
|
+
startTime = file.first.split[1]
|
83
|
+
|
84
|
+
# process each line of the file
|
85
|
+
file[1..file.size].each do |line|
|
86
|
+
minutes, text = line.split(': ')
|
87
|
+
unless text =~ /personal|uni|lunch|home/
|
88
|
+
work[text] = 0 unless work.include? text
|
89
|
+
work[text] += minutes.to_i
|
90
|
+
else
|
91
|
+
personal[text] = 0 unless personal.include? text
|
92
|
+
personal[text] += minutes.to_i
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# print the report
|
97
|
+
if opts[:date]
|
98
|
+
puts "# Logged work for #{fdate}"
|
99
|
+
else
|
100
|
+
puts "# Today's logged work"
|
101
|
+
end
|
102
|
+
|
103
|
+
workTotal = TrackerUtil::printSubReport(work, "Work")
|
104
|
+
personalTotal = TrackerUtil::printSubReport(personal, "Personal")
|
105
|
+
|
106
|
+
newTimeString = TrackerUtil::to12HourTime(TrackerUtil::newTimeWithMinutes(startTime, workTotal + personalTotal))
|
107
|
+
puts "Hours logged until #{newTimeString} (since #{TrackerUtil::to12HourTime(startTime)}). "
|
108
|
+
|
109
|
+
# if we're reporting for today, print the current time
|
110
|
+
puts "Currently #{TrackerUtil::to12HourTime(TrackerUtil::currentTimeFormatted())}." unless opts[:date]
|
111
|
+
else
|
112
|
+
if opts[:date]
|
113
|
+
STDERR.puts "No time log for #{fdate}. Track some time first."
|
114
|
+
else
|
115
|
+
STDERR.puts "No time log for today. Track some time first.\n"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
elsif MODE == 'edit'
|
120
|
+
if File.exist? filename
|
121
|
+
if ENV['EDITOR']
|
122
|
+
exec "#{ENV['EDITOR']} #{filename}"
|
123
|
+
else
|
124
|
+
exec "open", filename
|
125
|
+
end
|
126
|
+
exit
|
127
|
+
else
|
128
|
+
STDERR.puts "#{__FILE__}: #{filename} does not exist or unable to open."
|
129
|
+
exit 1
|
130
|
+
end
|
131
|
+
|
132
|
+
elsif MODE == 'insert'
|
133
|
+
if opts[:date]
|
134
|
+
puts "WARNING: Adding time to a day other than today is not recommended."
|
135
|
+
print "Continue? (y/n) "
|
136
|
+
input = STDIN.readline.chomp
|
137
|
+
unless input =~ /^y(es)?/i
|
138
|
+
STDERR.puts "Timelog update cancelled."
|
139
|
+
exit 1
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# process arguments
|
144
|
+
debug
|
145
|
+
minutes = TrackerUtil::processTimeArgument ARGV.shift
|
146
|
+
message = ARGV.join(" ")
|
147
|
+
|
148
|
+
# open the output file
|
149
|
+
first_time = !File.exist?(filename)
|
150
|
+
# debug
|
151
|
+
begin
|
152
|
+
File.open filename, 'a', :autoclose => true do |file|
|
153
|
+
if first_time
|
154
|
+
currentTimeInMinutes = TrackerUtil::timeToMinutes(TrackerUtil::currentTimeFormatted)
|
155
|
+
startTime = TrackerUtil::minutesToTime((currentTimeInMinutes - minutes).round_to_nearest 15)
|
156
|
+
file.puts "#{fdate} #{startTime}"
|
157
|
+
end
|
158
|
+
file.puts "#{minutes}: #{message}"
|
159
|
+
end
|
160
|
+
rescue
|
161
|
+
STDERR.puts "Couldn't open #{filename}: #{$!}"
|
162
|
+
exit 1
|
163
|
+
end
|
164
|
+
|
165
|
+
else
|
166
|
+
STDERR.puts "Couldn't determine the correct mode (I was given '#{MODE}'): #{$!}"
|
167
|
+
exit 1
|
168
|
+
end
|
data/lib/trak/blank.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# https://github.com/rails/rails/blob/2a371368c91789a4d689d6a84eb20b238c37678a/activesupport/lib/active_support/core_ext/object/blank.rb#L91
|
2
|
+
class String
|
3
|
+
# 0x3000: fullwidth whitespace
|
4
|
+
NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]!
|
5
|
+
|
6
|
+
# A string is blank if it's empty or contains whitespaces only:
|
7
|
+
#
|
8
|
+
# "".blank? # => true
|
9
|
+
# " ".blank? # => true
|
10
|
+
# " ".blank? # => true
|
11
|
+
# " something here ".blank? # => false
|
12
|
+
#
|
13
|
+
def blank?
|
14
|
+
self !~ NON_WHITESPACE_REGEXP
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "trak/blank"
|
2
|
+
require "trak/round_to_nearest"
|
3
|
+
|
4
|
+
module TrackerUtil
|
5
|
+
TIME_FORMAT_12HOUR = "%l:%M %p"
|
6
|
+
TIME_FORMAT_24HOUR = "%k:%M"
|
7
|
+
|
8
|
+
# expects a hash of tasks mapped to time spent, and a sub-report name
|
9
|
+
# (e.g., work, personal)
|
10
|
+
# prints a formatted sub-report
|
11
|
+
# returns the total hours worked
|
12
|
+
def self.printSubReport(report_hash, report_title)
|
13
|
+
total = 0
|
14
|
+
unless report_hash.empty?
|
15
|
+
count = 0
|
16
|
+
report_out = ""
|
17
|
+
report_hash.each do |title, minutes|
|
18
|
+
total += minutes.to_i
|
19
|
+
count += 1
|
20
|
+
report_out += "=> #{timeString(minutes)}: #{title}"
|
21
|
+
report_out += "\n" unless count == report_hash.size
|
22
|
+
end
|
23
|
+
puts "# #{report_title} time (#{timeString(total)})"
|
24
|
+
puts report_out
|
25
|
+
end
|
26
|
+
total
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.time_with_hours_minutes(*hm)
|
30
|
+
dmy = Time.now.to_a[3..5].reverse
|
31
|
+
Time.new(*dmy, *hm)
|
32
|
+
end
|
33
|
+
|
34
|
+
# expects a number of minutes
|
35
|
+
# if less than 60 returns the number with an "m"
|
36
|
+
# otherwise converts to hours and adds an "h"
|
37
|
+
def self.timeString(minutes)
|
38
|
+
if minutes >= 60
|
39
|
+
hours = minutes/60.0
|
40
|
+
if hours % 1 == 0
|
41
|
+
hours = hours.to_i
|
42
|
+
end
|
43
|
+
"#{hours}h"
|
44
|
+
else
|
45
|
+
"#{minutes}m"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.newTimeWithMinutes(start_time, minutes)
|
50
|
+
hm = start_time.split ':'
|
51
|
+
Time.at(time_with_hours_minutes(*hm).to_i + minutes.to_i*60).strftime(TIME_FORMAT_24HOUR).strip
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.to12HourTime(time)
|
55
|
+
unless time.blank?
|
56
|
+
hm = time.split ':'
|
57
|
+
time_with_hours_minutes(*hm).strftime(TIME_FORMAT_12HOUR).strip
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.currentTimeFormatted
|
62
|
+
Time.now.strftime(TIME_FORMAT_24HOUR)
|
63
|
+
end
|
64
|
+
|
65
|
+
# expects a single argument - the time argument in the format ##m or ##h
|
66
|
+
# if argument has no m/h qualifier, assume m
|
67
|
+
# returns a number of minutes
|
68
|
+
def self.processTimeArgument(time_string)
|
69
|
+
if time_string =~ /^(\d*\.?\d+)((m|min|minute|minutes)|(h|hr|hour|hours))?$/i
|
70
|
+
time = $1.to_i
|
71
|
+
modifier = $2
|
72
|
+
minutes = (modifier =~ /h.*/) ? time * 60 : time
|
73
|
+
|
74
|
+
# check enough time has been logged
|
75
|
+
if minutes < 15
|
76
|
+
STDERR.puts "You must log at least 15 minutes."
|
77
|
+
exit 1
|
78
|
+
end
|
79
|
+
|
80
|
+
minutes.round_to_nearest 15
|
81
|
+
else
|
82
|
+
STDERR.puts "Incorrectly formatted argument."
|
83
|
+
exit 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# expects a time string formatted HH24:MM
|
88
|
+
def self.timeToMinutes(time)
|
89
|
+
hours, minutes = time.split(':')
|
90
|
+
hours*60 + minutes
|
91
|
+
end
|
92
|
+
|
93
|
+
# expects an integer
|
94
|
+
def self.minutesToTime(minutes)
|
95
|
+
time_with_hours_minutes(minutes / 60, minutes % 60).sprintf TIME_FORMAT_24HOUR
|
96
|
+
end
|
97
|
+
|
98
|
+
# expects an integer which is the amount of minutes logged
|
99
|
+
def self.startTimeInMinutes(minutes)
|
100
|
+
currentTimeInMinutes = timeToMinutes(currentTimeFormatted).round_to_nearest 15
|
101
|
+
currentTimeInMinutes - minutes
|
102
|
+
end
|
103
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trak
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Sharp
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: trollop
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.16'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.16'
|
30
|
+
description: ! 'Problem: when tracking time, I don''t want to have to
|
31
|
+
|
32
|
+
start and stop a timer. Trak is a tool that lets me say "I just spent
|
33
|
+
|
34
|
+
15 minutes working on email", instead of "I''m starting to email
|
35
|
+
|
36
|
+
now...whoops! I forgot to tell the computer I stopped." Then later in
|
37
|
+
|
38
|
+
the day when you spend some more time emailing, you don''t have to keep
|
39
|
+
|
40
|
+
the total time you''ve spent for the day in your head. When you tell trak
|
41
|
+
|
42
|
+
to report on your time spent for the day, it tallies each task and gives
|
43
|
+
|
44
|
+
you a breakdown.'
|
45
|
+
email:
|
46
|
+
- adsharp@me.com
|
47
|
+
executables:
|
48
|
+
- trak
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/trak/blank.rb
|
53
|
+
- lib/trak/round_to_nearest.rb
|
54
|
+
- lib/trak/tracker_util.rb
|
55
|
+
- lib/trak.rb
|
56
|
+
- bin/trak
|
57
|
+
- CHANGELOG.md
|
58
|
+
- README.md
|
59
|
+
homepage: http://github.com/sharplet/trak
|
60
|
+
licenses: []
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.8.21
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: A command line tool for tracking chunks of time
|
83
|
+
test_files: []
|