tracking 1.0.0 → 1.1.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/.travis.yml +5 -2
 - data/CHANGELOG.md +9 -0
 - data/Gemfile +14 -7
 - data/README.md +24 -9
 - data/Rakefile +10 -10
 - data/VERSION +1 -1
 - data/bin/tracking +1 -1
 - data/lib/tracking.rb +9 -20
 - data/lib/tracking/cli.rb +117 -109
 - data/lib/tracking/config.rb +34 -15
 - data/lib/tracking/list.rb +77 -57
 - data/lib/tracking/task.rb +99 -0
 - data/spec/cli_spec.rb +36 -0
 - data/spec/helper.rb +21 -0
 - data/tracking.gemspec +81 -0
 - metadata +103 -22
 - data/test/helper.rb +0 -39
 - data/test/test_cli.rb +0 -47
 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -1,14 +1,21 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            source  
     | 
| 
      
 1 
     | 
    
         
            +
            source :rubygems
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # Add dependencies required to use your gem here.
         
     | 
| 
      
 4 
     | 
    
         
            +
            gem 'colorize', '~> 0.5'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            # Add dependencies to develop your gem here.
         
     | 
| 
       6 
7 
     | 
    
         
             
            # Include everything needed to run rake, tests, features, etc.
         
     | 
| 
       7 
8 
     | 
    
         
             
            group :development do
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
            	gem 'rdoc', '~> 3.12'
         
     | 
| 
      
 10 
     | 
    
         
            +
            	gem 'bundler', '>= 1.0.0'
         
     | 
| 
      
 11 
     | 
    
         
            +
            	gem 'jeweler', '~> 1.8.4'
         
     | 
| 
      
 12 
     | 
    
         
            +
            	gem 'simplecov'
         
     | 
| 
      
 13 
     | 
    
         
            +
            	gem 'yard'
         
     | 
| 
      
 14 
     | 
    
         
            +
            	gem 'rspec'
         
     | 
| 
      
 15 
     | 
    
         
            +
            	platforms :ruby do
         
     | 
| 
      
 16 
     | 
    
         
            +
            		gem 'redcarpet'
         
     | 
| 
      
 17 
     | 
    
         
            +
            	end
         
     | 
| 
      
 18 
     | 
    
         
            +
            	platforms :jruby do
         
     | 
| 
      
 19 
     | 
    
         
            +
            		gem 'kramdown'
         
     | 
| 
      
 20 
     | 
    
         
            +
            	end
         
     | 
| 
       14 
21 
     | 
    
         
             
            end
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,11 +1,13 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #tracking [](http://travis-ci.org/thenickperson/tracking)
         
     | 
| 
      
 1 
     | 
    
         
            +
            #tracking [](http://travis-ci.org/thenickperson/tracking) [](https://gemnasium.com/thenickperson/tracking) [](https://codeclimate.com/github/thenickperson/tracking)
         
     | 
| 
       2 
2 
     | 
    
         
             
            A simple and configurable command line time tracker.
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            ##Installation
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            `gem install tracking`
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            If you're on Windows, you should set up 
     | 
| 
      
 8 
     | 
    
         
            +
            If you're on Windows, you should set up
         
     | 
| 
      
 9 
     | 
    
         
            +
            [Ruby Installer](http://rubyinstaller.org/downloads/) and
         
     | 
| 
      
 10 
     | 
    
         
            +
            [DevKit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) first.
         
     | 
| 
       9 
11 
     | 
    
         | 
| 
       10 
12 
     | 
    
         
             
            Also, tracking does not work on Ruby 1.8 (yet). Please upgrade to Ruby 1.9.3.
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
         @@ -73,6 +75,8 @@ The default settings are listed below, along with a description of each setting. 
     | 
|
| 
       73 
75 
     | 
    
         
             
            :task_width: 40
         
     | 
| 
       74 
76 
     | 
    
         
             
            # format to use for elapsed time display (:colons or :letters)
         
     | 
| 
       75 
77 
     | 
    
         
             
            :elapsed_format: :colons
         
     | 
| 
      
 78 
     | 
    
         
            +
            # toggle colored display of the current (last) task
         
     | 
| 
      
 79 
     | 
    
         
            +
            :color_current_task: true
         
     | 
| 
       76 
80 
     | 
    
         
             
            # toggle header describing tracking's display columns (true or false)
         
     | 
| 
       77 
81 
     | 
    
         
             
            :show_header: true
         
     | 
| 
       78 
82 
     | 
    
         
             
            # toggle display of seconds in elapsed time (true of false)
         
     | 
| 
         @@ -80,7 +84,8 @@ The default settings are listed below, along with a description of each setting. 
     | 
|
| 
       80 
84 
     | 
    
         
             
            ```
         
     | 
| 
       81 
85 
     | 
    
         | 
| 
       82 
86 
     | 
    
         
             
            ##Elapsed Time Formats
         
     | 
| 
       83 
     | 
    
         
            -
            Elapsed times are displayed in this order: days, hours, minutes, seconds (if 
     | 
| 
      
 87 
     | 
    
         
            +
            Elapsed times are displayed in this order: days, hours, minutes, seconds (if
         
     | 
| 
      
 88 
     | 
    
         
            +
            enabled)
         
     | 
| 
       84 
89 
     | 
    
         
             
            - hide elapsed seconds
         
     | 
| 
       85 
90 
     | 
    
         
             
            	- colons: `01:02:03` (default)
         
     | 
| 
       86 
91 
     | 
    
         
             
            	- letters: `01d 02h 03m`
         
     | 
| 
         @@ -89,18 +94,28 @@ Elapsed times are displayed in this order: days, hours, minutes, seconds (if ena 
     | 
|
| 
       89 
94 
     | 
    
         
             
            	- letters: `01d 02h 03m 04s`
         
     | 
| 
       90 
95 
     | 
    
         | 
| 
       91 
96 
     | 
    
         
             
            ##Contributing to tracking
         
     | 
| 
       92 
     | 
    
         
            -
            - Check out the latest master to make sure the feature hasn't been implemented 
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
      
 97 
     | 
    
         
            +
            - Check out the latest master to make sure the feature hasn't been implemented
         
     | 
| 
      
 98 
     | 
    
         
            +
            or the bug hasn't been fixed yet.
         
     | 
| 
      
 99 
     | 
    
         
            +
            - Check out the issue tracker to make sure someone already hasn't requested it
         
     | 
| 
      
 100 
     | 
    
         
            +
            and/or contributed it.
         
     | 
| 
       94 
101 
     | 
    
         
             
            - Fork the project.
         
     | 
| 
       95 
102 
     | 
    
         
             
            - Start a feature/bugfix branch.
         
     | 
| 
       96 
103 
     | 
    
         
             
            - Commit and push until you are happy with your contribution.
         
     | 
| 
       97 
     | 
    
         
            -
            - Make sure to add tests for it. This is important so I don't break it in a 
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
      
 104 
     | 
    
         
            +
            - Make sure to add tests for it. This is important so I don't break it in a
         
     | 
| 
      
 105 
     | 
    
         
            +
            future version unintentionally.
         
     | 
| 
      
 106 
     | 
    
         
            +
            - Please try not to mess with the Rakefile, version, or history. If you want to
         
     | 
| 
      
 107 
     | 
    
         
            +
            have your own version, or is otherwise necessary, that is fine, but please
         
     | 
| 
      
 108 
     | 
    
         
            +
            isolate to its own commit so I can cherry-pick around it.
         
     | 
| 
       99 
109 
     | 
    
         | 
| 
       100 
110 
     | 
    
         
             
            ##Similar Projects
         
     | 
| 
       101 
111 
     | 
    
         
             
            - [timetrap](https://github.com/samg/timetrap)
         
     | 
| 
       102 
112 
     | 
    
         
             
            - [d-time-tracker](https://github.com/DanielVF/d-time-tracker)
         
     | 
| 
      
 113 
     | 
    
         
            +
            - [to-do](http://github.com/kristenmills/to-do) if you want a good command line
         
     | 
| 
      
 114 
     | 
    
         
            +
            todo manager to complement tracking
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            ##Special Thanks
         
     | 
| 
      
 117 
     | 
    
         
            +
            - [to-do](http://github.com/kristenmills/to-do) and
         
     | 
| 
      
 118 
     | 
    
         
            +
            [timetrap](https://github.com/samg/timetrap) for letting me borrow some code
         
     | 
| 
       103 
119 
     | 
    
         | 
| 
       104 
120 
     | 
    
         
             
            ##Copyright
         
     | 
| 
       105 
     | 
    
         
            -
            Copyright (c) 2012 Nicolas McCurdy. See LICENSE.txt for
         
     | 
| 
       106 
     | 
    
         
            -
            further details.
         
     | 
| 
      
 121 
     | 
    
         
            +
            Copyright (c) 2012 Nicolas McCurdy. See LICENSE.txt for further details.
         
     | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -6,7 +6,7 @@ begin 
     | 
|
| 
       6 
6 
     | 
    
         
             
              Bundler.setup(:default, :development)
         
     | 
| 
       7 
7 
     | 
    
         
             
            rescue Bundler::BundlerError => e
         
     | 
| 
       8 
8 
     | 
    
         
             
              $stderr.puts e.message
         
     | 
| 
       9 
     | 
    
         
            -
              $stderr.puts  
     | 
| 
      
 9 
     | 
    
         
            +
              $stderr.puts 'Run `bundle install` to install missing gems'
         
     | 
| 
       10 
10 
     | 
    
         
             
              exit e.status_code
         
     | 
| 
       11 
11 
     | 
    
         
             
            end
         
     | 
| 
       12 
12 
     | 
    
         
             
            require 'rake'
         
     | 
| 
         @@ -14,13 +14,13 @@ require 'rake' 
     | 
|
| 
       14 
14 
     | 
    
         
             
            require 'jeweler'
         
     | 
| 
       15 
15 
     | 
    
         
             
            Jeweler::Tasks.new do |gem|
         
     | 
| 
       16 
16 
     | 
    
         
             
              # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
         
     | 
| 
       17 
     | 
    
         
            -
              gem.name =  
     | 
| 
       18 
     | 
    
         
            -
              gem.homepage =  
     | 
| 
       19 
     | 
    
         
            -
              gem.license =  
     | 
| 
       20 
     | 
    
         
            -
              gem.summary =  
     | 
| 
       21 
     | 
    
         
            -
              gem.description =  
     | 
| 
       22 
     | 
    
         
            -
              gem.email =  
     | 
| 
       23 
     | 
    
         
            -
              gem.authors = [ 
     | 
| 
      
 17 
     | 
    
         
            +
              gem.name = 'tracking'
         
     | 
| 
      
 18 
     | 
    
         
            +
              gem.homepage = 'http://github.com/thenickperson/tracking'
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.license = 'MIT'
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.summary = 'A simple and configurable command line time tracker.'
         
     | 
| 
      
 21 
     | 
    
         
            +
              gem.description = 'See README for more information.'
         
     | 
| 
      
 22 
     | 
    
         
            +
              gem.email = 'thenickperson@gmail.com'
         
     | 
| 
      
 23 
     | 
    
         
            +
              gem.authors = ['Nicolas McCurdy']
         
     | 
| 
       24 
24 
     | 
    
         
             
              # dependencies defined in Gemfile
         
     | 
| 
       25 
25 
     | 
    
         
             
            end
         
     | 
| 
       26 
26 
     | 
    
         
             
            Jeweler::RubygemsDotOrgTasks.new
         
     | 
| 
         @@ -32,9 +32,9 @@ Rake::TestTask.new(:test) do |test| 
     | 
|
| 
       32 
32 
     | 
    
         
             
              test.verbose = true
         
     | 
| 
       33 
33 
     | 
    
         
             
            end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
            desc  
     | 
| 
      
 35 
     | 
    
         
            +
            desc 'Code coverage detail'
         
     | 
| 
       36 
36 
     | 
    
         
             
            task :simplecov do
         
     | 
| 
       37 
     | 
    
         
            -
            	ENV['COVERAGE'] =  
     | 
| 
      
 37 
     | 
    
         
            +
            	ENV['COVERAGE'] = 'true'
         
     | 
| 
       38 
38 
     | 
    
         
             
            	Rake::Task['spec'].execute
         
     | 
| 
       39 
39 
     | 
    
         
             
            end
         
     | 
| 
       40 
40 
     | 
    
         | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            1. 
     | 
| 
      
 1 
     | 
    
         
            +
            1.1.0
         
     | 
    
        data/bin/tracking
    CHANGED
    
    
    
        data/lib/tracking.rb
    CHANGED
    
    | 
         @@ -1,21 +1,10 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require File.join(File.dirname(__FILE__),  
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            #create config file
         
     | 
| 
       11 
     | 
    
         
            -
            if not File.exist? File.join(ENV["HOME"], ".tracking", "config.yml")
         
     | 
| 
       12 
     | 
    
         
            -
            	Tracking::Config.write
         
     | 
| 
      
 1 
     | 
    
         
            +
            # Require all of tracking's stuff
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'tracking', 'config')
         
     | 
| 
      
 3 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'tracking', 'list')
         
     | 
| 
      
 4 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'tracking', 'task')
         
     | 
| 
      
 5 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'tracking', 'cli')
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Tracking is the main namespace that all of the other modules and classes are a
         
     | 
| 
      
 8 
     | 
    
         
            +
            # part of
         
     | 
| 
      
 9 
     | 
    
         
            +
            module Tracking
         
     | 
| 
       13 
10 
     | 
    
         
             
            end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            #create data file
         
     | 
| 
       16 
     | 
    
         
            -
            if not File.exist? File.expand_path Tracking::Config[:data_file]
         
     | 
| 
       17 
     | 
    
         
            -
            	FileUtils.touch File.expand_path Tracking::Config[:data_file]
         
     | 
| 
       18 
     | 
    
         
            -
            end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
            require File.join(File.dirname(__FILE__), "tracking", "list")
         
     | 
| 
       21 
     | 
    
         
            -
            require File.join(File.dirname(__FILE__), "tracking", "cli")
         
     | 
    
        data/lib/tracking/cli.rb
    CHANGED
    
    | 
         @@ -1,152 +1,153 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'colorize'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            #imports
         
     | 
| 
       4 
     | 
    
         
            -
            require "optparse"
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            #view module methods
         
     | 
| 
       7 
4 
     | 
    
         
             
            module Tracking
         
     | 
| 
      
 5 
     | 
    
         
            +
            	# Contains methods for displaying the list in a command line and parsing
         
     | 
| 
      
 6 
     | 
    
         
            +
            	# command line arguments.
         
     | 
| 
       8 
7 
     | 
    
         
             
            	module CLI
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
8 
     | 
    
         
             
            		extend self
         
     | 
| 
       11 
9 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            		# 
     | 
| 
       13 
     | 
    
         
            -
            		 
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
            			data_file.each_with_index do |line, index|
         
     | 
| 
       37 
     | 
    
         
            -
            				if index+1 > file_length - Config[:lines]
         
     | 
| 
       38 
     | 
    
         
            -
            					data << line
         
     | 
| 
       39 
     | 
    
         
            -
            				end
         
     | 
| 
       40 
     | 
    
         
            -
            			end
         
     | 
| 
       41 
     | 
    
         
            -
            			#display data
         
     | 
| 
       42 
     | 
    
         
            -
            			for i in 0..data.length-1
         
     | 
| 
       43 
     | 
    
         
            -
            				if data[i].length == 2
         
     | 
| 
       44 
     | 
    
         
            -
            					begin
         
     | 
| 
       45 
     | 
    
         
            -
            						#grab and reformat data
         
     | 
| 
       46 
     | 
    
         
            -
            						time_string = Time.parse(data[i][0]).strftime("%H:%M")
         
     | 
| 
       47 
     | 
    
         
            -
            						task_string = data[i][1].chomp
         
     | 
| 
       48 
     | 
    
         
            -
            						start_time = Time.parse(data[i][0])
         
     | 
| 
       49 
     | 
    
         
            -
            						end_time = i<data.length-1 ? Time.parse(data[i+1][0]) : Time.now
         
     | 
| 
       50 
     | 
    
         
            -
            						elapsed_string = List.get_elapsed_time(start_time,end_time)
         
     | 
| 
       51 
     | 
    
         
            -
            						#format data into lines
         
     | 
| 
       52 
     | 
    
         
            -
            						lines = []
         
     | 
| 
       53 
     | 
    
         
            -
            						split_task(task_string).each_with_index do |task_line, i|
         
     | 
| 
       54 
     | 
    
         
            -
            							col_1 = pad(i==0 ? time_string : nil, 5)
         
     | 
| 
       55 
     | 
    
         
            -
            							col_2 = pad(task_line, Config[:task_width])
         
     | 
| 
       56 
     | 
    
         
            -
            							col_3 = pad(i==0 ? elapsed_string : nil, elapsed_time_length)
         
     | 
| 
       57 
     | 
    
         
            -
            							lines << "| #{col_1} | #{col_2} | #{col_3} |"
         
     | 
| 
       58 
     | 
    
         
            -
            						end
         
     | 
| 
       59 
     | 
    
         
            -
            						#display lines
         
     | 
| 
       60 
     | 
    
         
            -
            						if valid_lines == 0
         
     | 
| 
       61 
     | 
    
         
            -
            							puts horizontal_border
         
     | 
| 
       62 
     | 
    
         
            -
            							if Config[:show_header]
         
     | 
| 
       63 
     | 
    
         
            -
            								puts header
         
     | 
| 
       64 
     | 
    
         
            -
            								puts horizontal_border
         
     | 
| 
       65 
     | 
    
         
            -
            							end
         
     | 
| 
      
 10 
     | 
    
         
            +
            		# Width of the first column (start time)
         
     | 
| 
      
 11 
     | 
    
         
            +
            		@start_time_width = 5
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            		# Width of the second column (name)
         
     | 
| 
      
 14 
     | 
    
         
            +
            		@name_width = Config[:task_width]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            		# Width of the third column (elapsed time)
         
     | 
| 
      
 17 
     | 
    
         
            +
            		@elapsed_time_width = Task.elapsed_time_length
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            		# Displays part of the list in the command line
         
     | 
| 
      
 20 
     | 
    
         
            +
            		#
         
     | 
| 
      
 21 
     | 
    
         
            +
            		# @param [Integer] max the maximum number of items to display
         
     | 
| 
      
 22 
     | 
    
         
            +
            		def display max=Config[:lines]
         
     | 
| 
      
 23 
     | 
    
         
            +
            			display_object :top
         
     | 
| 
      
 24 
     | 
    
         
            +
            			tasks = List.get max
         
     | 
| 
      
 25 
     | 
    
         
            +
            			if tasks.length > 0
         
     | 
| 
      
 26 
     | 
    
         
            +
            				tasks.each_with_index do |task, task_index|
         
     | 
| 
      
 27 
     | 
    
         
            +
            					current_task = (task_index + 1 == tasks.length)
         
     | 
| 
      
 28 
     | 
    
         
            +
            					split_task(task.name).each_with_index do |name_line, line_index|
         
     | 
| 
      
 29 
     | 
    
         
            +
            						col_1 = pad(line_index==0 ? task.start_time : nil, 5)
         
     | 
| 
      
 30 
     | 
    
         
            +
            						col_2 = pad(name_line, @name_width)
         
     | 
| 
      
 31 
     | 
    
         
            +
            						col_3 = pad(line_index==0 ? task.elapsed_time : nil, @elapsed_time_width)
         
     | 
| 
      
 32 
     | 
    
         
            +
            						if current_task and Config[:color_current_task]
         
     | 
| 
      
 33 
     | 
    
         
            +
            							col_1,col_2,col_3 = col_1.yellow,col_2.yellow,col_3.yellow
         
     | 
| 
       66 
34 
     | 
    
         
             
            						end
         
     | 
| 
       67 
     | 
    
         
            -
            						 
     | 
| 
       68 
     | 
    
         
            -
            						valid_lines += 1
         
     | 
| 
       69 
     | 
    
         
            -
            					rescue
         
     | 
| 
       70 
     | 
    
         
            -
            						invalid_lines += 1
         
     | 
| 
      
 35 
     | 
    
         
            +
            						puts "| #{col_1} | #{col_2} | #{col_3} |"
         
     | 
| 
       71 
36 
     | 
    
         
             
            					end
         
     | 
| 
       72 
     | 
    
         
            -
            				else
         
     | 
| 
       73 
     | 
    
         
            -
            					invalid_lines += 1
         
     | 
| 
       74 
37 
     | 
    
         
             
            				end
         
     | 
| 
       75 
     | 
    
         
            -
            			end
         
     | 
| 
       76 
     | 
    
         
            -
            			#display intro, if needed
         
     | 
| 
       77 
     | 
    
         
            -
            			if valid_lines > 0
         
     | 
| 
       78 
     | 
    
         
            -
            				puts horizontal_border
         
     | 
| 
       79 
38 
     | 
    
         
             
            			else
         
     | 
| 
       80 
     | 
    
         
            -
            				 
     | 
| 
      
 39 
     | 
    
         
            +
            				display_object :intro
         
     | 
| 
       81 
40 
     | 
    
         
             
            			end
         
     | 
| 
       82 
     | 
    
         
            -
            			 
     | 
| 
      
 41 
     | 
    
         
            +
            			display_object :bottom
         
     | 
| 
      
 42 
     | 
    
         
            +
            			# Display a warning, if needed
         
     | 
| 
      
 43 
     | 
    
         
            +
            =begin
         
     | 
| 
       83 
44 
     | 
    
         
             
            			if invalid_lines > 0
         
     | 
| 
       84 
     | 
    
         
            -
            				warn "Error: #{invalid_lines} invalid line#{ 
     | 
| 
      
 45 
     | 
    
         
            +
            				warn "Error: #{invalid_lines} invalid line#{'s' if invalid_lines > 1} found in data file."
         
     | 
| 
       85 
46 
     | 
    
         
             
            			end
         
     | 
| 
      
 47 
     | 
    
         
            +
            =end
         
     | 
| 
       86 
48 
     | 
    
         
             
            		end
         
     | 
| 
       87 
49 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
            		# 
     | 
| 
      
 50 
     | 
    
         
            +
            		# Displays commonly used text objects in the command line
         
     | 
| 
      
 51 
     | 
    
         
            +
            		#
         
     | 
| 
      
 52 
     | 
    
         
            +
            		# @param type the type of text object to display (:top/:bottom/:intro)
         
     | 
| 
      
 53 
     | 
    
         
            +
            		def display_object type
         
     | 
| 
      
 54 
     | 
    
         
            +
            			horizontal_border = "+-------+-#{'-'*@name_width}-+-#{'-'*@elapsed_time_width}-+"
         
     | 
| 
      
 55 
     | 
    
         
            +
            			case type
         
     | 
| 
      
 56 
     | 
    
         
            +
            			when :top
         
     | 
| 
      
 57 
     | 
    
         
            +
            				puts horizontal_border
         
     | 
| 
      
 58 
     | 
    
         
            +
            				if Config[:show_header]
         
     | 
| 
      
 59 
     | 
    
         
            +
            					puts "| start | #{pad('task', @name_width, :center)} | #{pad('elapsed', @elapsed_time_width, :center)} |"
         
     | 
| 
      
 60 
     | 
    
         
            +
            					puts horizontal_border
         
     | 
| 
      
 61 
     | 
    
         
            +
            				end
         
     | 
| 
      
 62 
     | 
    
         
            +
            			when :bottom
         
     | 
| 
      
 63 
     | 
    
         
            +
            				puts horizontal_border
         
     | 
| 
      
 64 
     | 
    
         
            +
            			when :intro
         
     | 
| 
      
 65 
     | 
    
         
            +
            				intro_text = <<-EOF
         
     | 
| 
      
 66 
     | 
    
         
            +
            You haven't started any tasks yet! :(
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            Run this to begin your first task:
         
     | 
| 
      
 69 
     | 
    
         
            +
              tracking starting some work
         
     | 
| 
      
 70 
     | 
    
         
            +
            				EOF
         
     | 
| 
      
 71 
     | 
    
         
            +
            				intro_text.each_line do |line|
         
     | 
| 
      
 72 
     | 
    
         
            +
            					puts "|       | #{pad(line.chomp, @name_width)} | #{pad(nil, @elapsed_time_width)} |"
         
     | 
| 
      
 73 
     | 
    
         
            +
            				end
         
     | 
| 
      
 74 
     | 
    
         
            +
            			end
         
     | 
| 
      
 75 
     | 
    
         
            +
            		end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            		# Pads tasks with whitespace to align them for display
         
     | 
| 
      
 78 
     | 
    
         
            +
            		#
         
     | 
| 
      
 79 
     | 
    
         
            +
            		# @param [String] string the string to pad
         
     | 
| 
      
 80 
     | 
    
         
            +
            		# @param [Integer] length the length of the resultant string
         
     | 
| 
      
 81 
     | 
    
         
            +
            		# @param [Symbol] align the alignment of the start string within the end
         
     | 
| 
      
 82 
     | 
    
         
            +
            		# string (:left/:right/:center)
         
     | 
| 
      
 83 
     | 
    
         
            +
            		# @return [String] the padded string
         
     | 
| 
       89 
84 
     | 
    
         
             
            		def pad(string, length, align=:left)
         
     | 
| 
       90 
85 
     | 
    
         
             
            			if string == nil
         
     | 
| 
       91 
     | 
    
         
            -
            				return  
     | 
| 
      
 86 
     | 
    
         
            +
            				return ' ' * length
         
     | 
| 
       92 
87 
     | 
    
         
             
            			elsif string.length >= length
         
     | 
| 
       93 
88 
     | 
    
         
             
            				return string
         
     | 
| 
       94 
89 
     | 
    
         
             
            			else
         
     | 
| 
       95 
90 
     | 
    
         
             
            				difference = (length - string.length).to_f
         
     | 
| 
       96 
91 
     | 
    
         
             
            				case align
         
     | 
| 
       97 
92 
     | 
    
         
             
            				when :left
         
     | 
| 
       98 
     | 
    
         
            -
            					return string +  
     | 
| 
      
 93 
     | 
    
         
            +
            					return string + ' ' * difference
         
     | 
| 
       99 
94 
     | 
    
         
             
            				when :right
         
     | 
| 
       100 
     | 
    
         
            -
            					return  
     | 
| 
      
 95 
     | 
    
         
            +
            					return ' ' * difference + string
         
     | 
| 
       101 
96 
     | 
    
         
             
            				when :center
         
     | 
| 
       102 
     | 
    
         
            -
            					return  
     | 
| 
      
 97 
     | 
    
         
            +
            					return ' '*(difference/2).floor + string + ' '*(difference/2).ceil
         
     | 
| 
       103 
98 
     | 
    
         
             
            				else
         
     | 
| 
       104 
99 
     | 
    
         
             
            					return string
         
     | 
| 
       105 
100 
     | 
    
         
             
            				end
         
     | 
| 
       106 
101 
     | 
    
         
             
            			end
         
     | 
| 
       107 
102 
     | 
    
         
             
            		end
         
     | 
| 
       108 
103 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
            		# 
     | 
| 
      
 104 
     | 
    
         
            +
            		# Word wraps tasks into multiple lines for display (based on the user's task
         
     | 
| 
      
 105 
     | 
    
         
            +
            		# width setting)
         
     | 
| 
      
 106 
     | 
    
         
            +
            		#
         
     | 
| 
      
 107 
     | 
    
         
            +
            		# @param [String] task the task string to split up
         
     | 
| 
      
 108 
     | 
    
         
            +
            		# @return [Array] an array of strings, each containing an individual line of
         
     | 
| 
      
 109 
     | 
    
         
            +
            		# wrapped text
         
     | 
| 
       110 
110 
     | 
    
         
             
            		def split_task task
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
            			# 
     | 
| 
      
 112 
     | 
    
         
            +
            			# If the task fits
         
     | 
| 
       113 
113 
     | 
    
         
             
            			if task.length <= Config[:task_width]
         
     | 
| 
       114 
114 
     | 
    
         
             
            				return [task]
         
     | 
| 
       115 
115 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
            			# 
     | 
| 
      
 116 
     | 
    
         
            +
            			# If the task needs to be split
         
     | 
| 
       117 
117 
     | 
    
         
             
            			else
         
     | 
| 
       118 
     | 
    
         
            -
            				words = task.split( 
     | 
| 
      
 118 
     | 
    
         
            +
            				words = task.split(' ')
         
     | 
| 
       119 
119 
     | 
    
         
             
            				split = []
         
     | 
| 
       120 
     | 
    
         
            -
            				line =  
     | 
| 
      
 120 
     | 
    
         
            +
            				line = ''
         
     | 
| 
       121 
121 
     | 
    
         
             
            				words.each do |word|
         
     | 
| 
       122 
122 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
            					# 
     | 
| 
      
 123 
     | 
    
         
            +
            					# If the word needs to be split
         
     | 
| 
       124 
124 
     | 
    
         
             
            					if word.length > Config[:task_width]
         
     | 
| 
       125 
     | 
    
         
            -
            						# 
     | 
| 
      
 125 
     | 
    
         
            +
            						# Add the start of the word onto the first line (even if it has
         
     | 
| 
      
 126 
     | 
    
         
            +
            						# already started)
         
     | 
| 
       126 
127 
     | 
    
         
             
            						while line.length < Config[:task_width]
         
     | 
| 
       127 
128 
     | 
    
         
             
            							line += word[0]
         
     | 
| 
       128 
129 
     | 
    
         
             
            							word = word[1..-1]
         
     | 
| 
       129 
130 
     | 
    
         
             
            						end
         
     | 
| 
       130 
131 
     | 
    
         
             
            						split << line
         
     | 
| 
       131 
     | 
    
         
            -
            						# 
     | 
| 
      
 132 
     | 
    
         
            +
            						# Split the rest of the word up onto new lines
         
     | 
| 
       132 
133 
     | 
    
         
             
            						split_word = word.scan(%r[.{1,#{Config[:task_width]}}])
         
     | 
| 
       133 
134 
     | 
    
         
             
            						split_word[0..-2].each do |word_section|
         
     | 
| 
       134 
135 
     | 
    
         
             
            							split << word_section
         
     | 
| 
       135 
136 
     | 
    
         
             
            						end
         
     | 
| 
       136 
137 
     | 
    
         
             
            						line = split_word.last
         
     | 
| 
       137 
138 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
            					# 
     | 
| 
      
 139 
     | 
    
         
            +
            					# If the word would fit on a new line
         
     | 
| 
       139 
140 
     | 
    
         
             
            					elsif (line + word).length > Config[:task_width]
         
     | 
| 
       140 
141 
     | 
    
         
             
            						split << line.chomp
         
     | 
| 
       141 
142 
     | 
    
         
             
            						line = word
         
     | 
| 
       142 
143 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
            					# 
     | 
| 
      
 144 
     | 
    
         
            +
            					# If the word can be added to this line
         
     | 
| 
       144 
145 
     | 
    
         
             
            					else
         
     | 
| 
       145 
146 
     | 
    
         
             
            						line += word
         
     | 
| 
       146 
147 
     | 
    
         
             
            					end
         
     | 
| 
       147 
148 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
            					# 
     | 
| 
       149 
     | 
    
         
            -
            					line +=  
     | 
| 
      
 149 
     | 
    
         
            +
            					# Add a space to the end of the last word, if it would fit
         
     | 
| 
      
 150 
     | 
    
         
            +
            					line += ' ' if line.length != Config[:task_width]
         
     | 
| 
       150 
151 
     | 
    
         | 
| 
       151 
152 
     | 
    
         
             
            				end
         
     | 
| 
       152 
153 
     | 
    
         
             
            				split << line
         
     | 
| 
         @@ -154,47 +155,54 @@ EOF 
     | 
|
| 
       154 
155 
     | 
    
         
             
            			end
         
     | 
| 
       155 
156 
     | 
    
         
             
            		end
         
     | 
| 
       156 
157 
     | 
    
         | 
| 
       157 
     | 
    
         
            -
            		# 
     | 
| 
      
 158 
     | 
    
         
            +
            		# Use option parser to parse command line arguments and run the selected
         
     | 
| 
      
 159 
     | 
    
         
            +
            		# command with its selected options
         
     | 
| 
       158 
160 
     | 
    
         
             
            		def parse
         
     | 
| 
       159 
161 
     | 
    
         
             
            			#options = {}
         
     | 
| 
       160 
162 
     | 
    
         
             
            			done = false
         
     | 
| 
       161 
163 
     | 
    
         | 
| 
       162 
164 
     | 
    
         
             
            			OptionParser.new do |opts|
         
     | 
| 
       163 
     | 
    
         
            -
            				# 
     | 
| 
       164 
     | 
    
         
            -
            				version_path = File.expand_path( 
     | 
| 
       165 
     | 
    
         
            -
            				opts.version = File.exist?(version_path) ? File.read(version_path) :  
     | 
| 
       166 
     | 
    
         
            -
            				# 
     | 
| 
       167 
     | 
    
         
            -
            				opts.banner =  
     | 
| 
       168 
     | 
    
         
            -
            				opts.separator  
     | 
| 
       169 
     | 
    
         
            -
            				opts.separator  
     | 
| 
       170 
     | 
    
         
            -
            				# 
     | 
| 
       171 
     | 
    
         
            -
            				opts.on( 
     | 
| 
       172 
     | 
    
         
            -
            					List. 
     | 
| 
       173 
     | 
    
         
            -
            					 
     | 
| 
      
 165 
     | 
    
         
            +
            				# Setup
         
     | 
| 
      
 166 
     | 
    
         
            +
            				version_path = File.expand_path('../../VERSION', File.dirname(__FILE__))
         
     | 
| 
      
 167 
     | 
    
         
            +
            				opts.version = File.exist?(version_path) ? File.read(version_path) : ''
         
     | 
| 
      
 168 
     | 
    
         
            +
            				# Start of help text
         
     | 
| 
      
 169 
     | 
    
         
            +
            				opts.banner = 'Usage: tracking [mode]'
         
     | 
| 
      
 170 
     | 
    
         
            +
            				opts.separator '                                     display tasks'
         
     | 
| 
      
 171 
     | 
    
         
            +
            				opts.separator '    <task description>               start a new task with the given text (spaces allowed)'
         
     | 
| 
      
 172 
     | 
    
         
            +
            				# Modes
         
     | 
| 
      
 173 
     | 
    
         
            +
            				opts.on('-r', '--rename', 'rename the last task') do
         
     | 
| 
      
 174 
     | 
    
         
            +
            					List.rename ARGV.join(' ').gsub("\t",'')
         
     | 
| 
      
 175 
     | 
    
         
            +
            					display
         
     | 
| 
       174 
176 
     | 
    
         
             
            					done = true
         
     | 
| 
       175 
177 
     | 
    
         
             
            					return
         
     | 
| 
       176 
178 
     | 
    
         
             
            				end
         
     | 
| 
       177 
     | 
    
         
            -
            				opts.on( 
     | 
| 
      
 179 
     | 
    
         
            +
            				opts.on('-d', '--delete', 'delete the last task') do
         
     | 
| 
       178 
180 
     | 
    
         
             
            					List.delete
         
     | 
| 
       179 
181 
     | 
    
         
             
            					display
         
     | 
| 
       180 
182 
     | 
    
         
             
            					done = true
         
     | 
| 
       181 
183 
     | 
    
         
             
            					return
         
     | 
| 
       182 
184 
     | 
    
         
             
            				end
         
     | 
| 
       183 
     | 
    
         
            -
            				opts.on( 
     | 
| 
      
 185 
     | 
    
         
            +
            				opts.on('-c', '--clear', 'delete all tasks') do
         
     | 
| 
      
 186 
     | 
    
         
            +
            					List.clear
         
     | 
| 
      
 187 
     | 
    
         
            +
            					puts 'List cleared.'
         
     | 
| 
      
 188 
     | 
    
         
            +
            					done = true
         
     | 
| 
      
 189 
     | 
    
         
            +
            					return
         
     | 
| 
      
 190 
     | 
    
         
            +
            				end
         
     | 
| 
      
 191 
     | 
    
         
            +
            				opts.on('-h', '--help', 'display this help information') do
         
     | 
| 
       184 
192 
     | 
    
         
             
            					puts opts
         
     | 
| 
       185 
193 
     | 
    
         
             
            					done = true
         
     | 
| 
       186 
194 
     | 
    
         
             
            					return
         
     | 
| 
       187 
195 
     | 
    
         
             
            				end
         
     | 
| 
       188 
196 
     | 
    
         
             
            			end.parse!
         
     | 
| 
       189 
197 
     | 
    
         | 
| 
       190 
     | 
    
         
            -
            			# 
     | 
| 
       191 
     | 
    
         
            -
            			 
     | 
| 
      
 198 
     | 
    
         
            +
            			# Basic modes (display and add)
         
     | 
| 
      
 199 
     | 
    
         
            +
            			unless done
         
     | 
| 
       192 
200 
     | 
    
         
             
            				if ARGV.count == 0
         
     | 
| 
       193 
     | 
    
         
            -
            					# 
     | 
| 
      
 201 
     | 
    
         
            +
            					# Display all tasks
         
     | 
| 
       194 
202 
     | 
    
         
             
            					display
         
     | 
| 
       195 
203 
     | 
    
         
             
            				else
         
     | 
| 
       196 
     | 
    
         
            -
            					# 
     | 
| 
       197 
     | 
    
         
            -
            					List.add ARGV.join( 
     | 
| 
      
 204 
     | 
    
         
            +
            					# Start a new task
         
     | 
| 
      
 205 
     | 
    
         
            +
            					List.add ARGV.join(' ').gsub("\t",'')
         
     | 
| 
       198 
206 
     | 
    
         
             
            					display
         
     | 
| 
       199 
207 
     | 
    
         
             
            				end
         
     | 
| 
       200 
208 
     | 
    
         
             
            			end
         
     |