summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfelix <felix@seconddrawer.com.au>2011-05-16 14:42:36 +0000
committerfelix <felix@seconddrawer.com.au>2011-05-16 14:42:36 +0000
commit61b89c1d892879cd4f262ec85b52944a5a42d642 (patch)
treef779e100c83ed85b25128b1b11224e75730d52a1
parent8f64d8e8d1534aed13c85a9a3420146ee1f63ebf (diff)
downloadtimetrackr-61b89c1d892879cd4f262ec85b52944a5a42d642.tar.gz
timetrackr-61b89c1d892879cd4f262ec85b52944a5a42d642.tar.bz2
rework the innards
-rw-r--r--README.mkd2
-rwxr-xr-xbin/timetrackr64
-rw-r--r--lib/timetrackr.rb22
-rw-r--r--lib/timetrackr/period.rb21
-rw-r--r--lib/timetrackr/yaml.rb57
5 files changed, 110 insertions, 56 deletions
diff --git a/README.mkd b/README.mkd
index 8b906c4..54e8893 100644
--- a/README.mkd
+++ b/README.mkd
@@ -15,7 +15,7 @@ A simple CLI time tracking utility.
>tt clear work
>tt time
- play * 0h 0m 1s
+ play * 0h 0m 5s
diff --git a/bin/timetrackr b/bin/timetrackr
index 6d42dac..7baee6b 100755
--- a/bin/timetrackr
+++ b/bin/timetrackr
@@ -3,13 +3,16 @@
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'timetrackr'
+require 'timetrackr/period'
DEFAULTS = {
:backend => 'yaml',
:verbose => false,
:single_task => false,
:path => File.join(ENV['HOME'],'.timetrackr.db'),
- :time_format => "% -30<task>s %2<hours>dh %2<minutes>dm %2<seconds>ds"
+ :relative_format => "%2<hours>dh %2<minutes>dm %2<seconds>ds",
+ :absolute_time => "%H:%m",
+ :absolute_day => "%Y-%m-%d"
}
def show_help
@@ -32,12 +35,11 @@ def show_help
HELP
end
-def format_time(task, time, fmt_str)
+def format_time(time, fmt_str)
hours = time.to_i/3600.to_i
minutes = (time/60 - hours * 60).to_i
seconds = (time - (minutes * 60 + hours * 3600))
format(fmt_str,{
- :task => task,
:hours => hours,
:minutes => minutes,
:seconds => seconds})
@@ -71,37 +73,36 @@ trackr = TimeTrackr.create(config[:backend], config)
case cmd
when 'start','in','s'
task = ARGV.shift
- details = {:action => 'start', :notes => ARGV.join(' ')}
+ notes = ARGV.join(' ')
# switch tasks if config says so
if config[:single_task] && trackr.current != task
- trackr.current.each do |t|
- trackr.event(t,Time.now,details.merge(:action => 'stop')) unless t == task
- end
- trackr.event(task,Time.now,details)
+ trackr.current.each { |t|
+ trackr.stop(t) unless t == task
+ }
puts "Switched to task '#{task}'" if $verbose
else
- trackr.event(task,Time.now, details)
puts "Started task '#{task}'" if $verbose
end
+ trackr.start(task, notes)
when 'stop','out','kill','k'
- task = ARGV.shift
- tasks = []
- details = {:action => 'stop', :notes => ARGV.join(' ')}
- tasks = [*task] if trackr.current.include?(task)
- tasks = trackr.tasks if task == 'all'
+ if ARGV[0] == 'all' || ARGV[0].nil?
+ tasks = trackr.tasks
+ else
+ tasks = ARGV
+ end
tasks.each do |task|
- trackr.event(task, Time.now, details)
+ trackr.stop(task)
puts "Stopped task '#{task}'" if $verbose
end
when 'switch','sw'
task = ARGV.shift
- details = {:notes => ARGV.join(' ')}
+ notes = ARGV.join(' ')
trackr.current.each do |t|
- trackr.event(t, Time.now, details.merge(:action => 'stop')) unless t == task
+ trackr.stop(t) unless t == task
end
- trackr.event(task, Time.now, details.merge(:action => 'start'))
+ trackr.start(task, notes)
puts "Switched to task '#{task}'" if $verbose
when 'time','status',nil
@@ -112,10 +113,35 @@ when 'time','status',nil
tasks = trackr.tasks.each
end
tasks.each do |task|
+ total = trackr.history(task).reduce(0){ |t, period|
+ t = t + period.length
+ }
name = trackr.current.include?(task) ? task+' *' : task
- puts format_time(name, trackr.time(task),config[:time_format])
+ puts name.ljust(15) << format_time(total,config[:relative_format])
end
+when 'log'
+ if ARGV[0] == 'all' || ARGV[0].nil?
+ tasks = trackr.tasks
+ else
+ tasks = ARGV
+ end
+ table = []
+ periods = tasks.each.collect{ |t| trackr.history(t) }.flatten
+ lastday = nil
+ table << periods.sort{|x,y| x.start <=> y.start}.collect{ |period|
+ currday = period.start.strftime(config[:absolute_day])
+ day = (currday == lastday) ? ' ' : currday
+ lastday = currday
+ name = period.current? ? period.task+' *' : period.task
+ start = period.start.strftime(config[:absolute_time])
+ stop = period.current? ? ' ' : period.stop.strftime(config[:absolute_time])
+ length = format_time(period.length, config[:relative_format])
+ "#{day.ljust(12)} #{name.ljust(15)} #{start.ljust(7)} #{stop.ljust(7)} #{length}"
+ }
+ puts table.join("\n")
+
+
when 'clear','delete','del'
tasks = ARGV
tasks = trackr.tasks if task == 'all'
diff --git a/lib/timetrackr.rb b/lib/timetrackr.rb
index 75bf520..c93da9b 100644
--- a/lib/timetrackr.rb
+++ b/lib/timetrackr.rb
@@ -34,6 +34,20 @@ class TimeTrackr
end
#
+ # start a period
+ #
+ def start(task,notes)
+ raise 'Not implemented'
+ end
+
+ #
+ # stop a period
+ #
+ def stop(task)
+ raise 'Not implemented'
+ end
+
+ #
# return an array of all tasks
#
def tasks
@@ -42,21 +56,19 @@ class TimeTrackr
#
# time in task in seconds
- # only considers 'start' and 'stop' events
#
def time(task)
- raise 'Not Implemented'
end
#
- # write an event
+ # get task history as an array of Periods
#
- def event(task, time=Time.now, details={})
+ def history(task)
raise 'Not Implemented'
end
#
- # clear an event
+ # clear an task
#
def clear(task)
raise 'Not Implemented'
diff --git a/lib/timetrackr/period.rb b/lib/timetrackr/period.rb
new file mode 100644
index 0000000..ce83c82
--- /dev/null
+++ b/lib/timetrackr/period.rb
@@ -0,0 +1,21 @@
+class Period
+
+ attr_accessor :task, :start, :stop, :notes
+
+ def initialize(task, start, stop=nil, notes='')
+ @task = task
+ @start = start
+ @stop = stop
+ @notes = notes
+ end
+
+ def length
+ stop = @stop || Time.now
+ stop - @start
+ end
+
+ def current?
+ stop.nil?
+ end
+
+end
diff --git a/lib/timetrackr/yaml.rb b/lib/timetrackr/yaml.rb
index ac5e299..f3547bc 100644
--- a/lib/timetrackr/yaml.rb
+++ b/lib/timetrackr/yaml.rb
@@ -1,3 +1,15 @@
+#
+# keeps the following format in a yaml file:
+#
+# :current: []
+#
+# :tasks:
+# foo:
+# - :start: 2011-05-16 14:26:26.263449 +07:00
+# :stop: 2011-05-16 14:26:27 +07:00
+# :notes: "blah blah blah"
+#
+
class YamlTimeTrackr < TimeTrackr
def initialize(path)
@@ -18,33 +30,25 @@ class YamlTimeTrackr < TimeTrackr
@db[:tasks].keys.compact.uniq || []
end
- def time(task)
- total = 0 # seconds
- split = nil
- @db[:tasks][task].sort{|x,y| x[:time] <=> y[:time]}.each do |event|
- if event[:action] == 'start'
- split = event[:time]
- end
- if split && (event[:action] == 'stop')
- total = total + (event[:time] - split)
- split = nil
- end
+ def start(task, notes)
+ @db[:tasks][task] = Array[] unless @db[:tasks][task]
+ if !@db[:current].include?(task)
+ @db[:current].unshift(task)
+ @db[:tasks][task].push({:start => Time.now, :notes => notes})
end
- total = (total + (Time.now - split)) if split
- total.to_i
end
- def event(task='default', time=Time.now, details={})
- details[:action] ||= 'start'
- details[:time] = time
- if details[:action].to_s == 'stop' && @db[:current].delete(task)
- write_event(task,details)
+ def stop(task)
+ if @db[:current].include?(task)
+ @db[:current].delete(task)
+ @db[:tasks][task].last[:stop] = Time.now
end
+ end
- if details[:action].to_s == 'start' && !@db[:current].include?(task)
- @db[:current].unshift(task)
- write_event(task,details)
- end
+ def history(task, p_begin=nil, p_end=nil)
+ @db[:tasks][task].sort{|x,y| x[:start] <=> y[:start]}.collect {|p|
+ Period.new(task,p[:start],p[:stop],p[:notes])
+ } unless !@db[:tasks].include? task
end
def close
@@ -58,15 +62,6 @@ class YamlTimeTrackr < TimeTrackr
private
- def write_event(task, details)
- @db[:tasks] = {} unless @db[:tasks]
- if @db[:tasks][task]
- @db[:tasks][task].push(details)
- else
- @db[:tasks][task] = Array[details]
- end
- end
-
def write_file
File.open(@log_path,'w') do |fh|
YAML.dump(@db,fh)