diff options
| author | felix <felix@seconddrawer.com.au> | 2011-05-16 14:42:36 +0000 |
|---|---|---|
| committer | felix <felix@seconddrawer.com.au> | 2011-05-16 14:42:36 +0000 |
| commit | 61b89c1d892879cd4f262ec85b52944a5a42d642 (patch) | |
| tree | f779e100c83ed85b25128b1b11224e75730d52a1 | |
| parent | 8f64d8e8d1534aed13c85a9a3420146ee1f63ebf (diff) | |
| download | timetrackr-61b89c1d892879cd4f262ec85b52944a5a42d642.tar.gz timetrackr-61b89c1d892879cd4f262ec85b52944a5a42d642.tar.bz2 | |
rework the innards
| -rw-r--r-- | README.mkd | 2 | ||||
| -rwxr-xr-x | bin/timetrackr | 64 | ||||
| -rw-r--r-- | lib/timetrackr.rb | 22 | ||||
| -rw-r--r-- | lib/timetrackr/period.rb | 21 | ||||
| -rw-r--r-- | lib/timetrackr/yaml.rb | 57 |
5 files changed, 110 insertions, 56 deletions
@@ -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) |
