diff options
| author | Zack Hobson | 2009-08-09 18:53:44 -0700 | 
|---|---|---|
| committer | Zack Hobson | 2009-08-09 18:53:44 -0700 | 
| commit | 09513e8446030d508fbf22daf926ec0d9647ea5d (patch) | |
| tree | c53edd78b8f6ced5933381ebe3eb72fa6cd95636 /lib | |
| parent | 3c224404e03412c9e13a7aa161bba55d2c1a6b7a (diff) | |
| download | hcl-09513e8446030d508fbf22daf926ec0d9647ea5d.tar.bz2 | |
Code cleanup and documentation.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/hcl/app.rb | 249 | ||||
| -rw-r--r-- | lib/hcl/commands.rb | 90 | ||||
| -rw-r--r-- | lib/hcl/utility.rb | 7 | 
3 files changed, 185 insertions, 161 deletions
| diff --git a/lib/hcl/app.rb b/lib/hcl/app.rb index 1afe2b3..a3f3153 100644 --- a/lib/hcl/app.rb +++ b/lib/hcl/app.rb @@ -11,6 +11,7 @@ require 'highline/import'  ## app dependencies  require 'hcl/utility' +require 'hcl/commands'  require 'hcl/timesheet_resource'  require 'hcl/project'  require 'hcl/task' @@ -30,50 +31,61 @@ end  module HCl    class App -  include HCl::Utility - -  SETTINGS_FILE = "#{ENV['HOME']}/.hcl_settings" -  CONFIG_FILE = "#{ENV['HOME']}/.hcl_config" - -  class UnknownCommand < StandardError; end +    include HCl::Utility +    include HCl::Commands +   +    SETTINGS_FILE = "#{ENV['HOME']}/.hcl_settings" +    CONFIG_FILE = "#{ENV['HOME']}/.hcl_config" +   +    class UnknownCommand < StandardError; end +   +    def initialize +      read_config +      read_settings +    end -  def self.command *args -    hcl = new.process_args(*args).run -  end +    # Run the given command and arguments. +    def self.command *args +      hcl = new.process_args(*args).run +    end -  def run -    begin -      if @command -        if respond_to? @command -          result = send @command, *@args -          if not result.nil? -            if result.respond_to? :to_a -              puts result.to_a.join(', ') -            elsif result.respond_to? :to_s -              puts result +    # Return true if the string is a known command, false otherwise. +    # +    # @param [#to_s] command name of command +    # @return [true, false] +    def command? command +      Commands.instance_methods.include? command.to_s +    end +   +    # Start the application. +    def run +      begin +        if @command +          if command? @command +            result = send @command, *@args +            if not result.nil? +              if result.respond_to? :to_a +                puts result.to_a.join(', ') +              elsif result.respond_to? :to_s +                puts result +              end              end +          else +            raise UnknownCommand, "unrecognized command `#{@command}'"            end          else -          raise UnknownCommand, "unrecognized command `#{@command}'" +          show          end -      else -        show +      rescue TimesheetResource::Failure => e +        puts "Internal failure. #{e}" +        exit 1        end -    rescue TimesheetResource::Failure => e -      puts "Internal failure. #{e}" -      exit 1      end -  end - -  def initialize -    read_config -    read_settings -  end - -  def process_args *args -    Trollop::options(args) do -      stop_on %w[ show tasks set unset note add rm start stop ] -      banner <<-EOM +   +    def process_args *args +      Trollop::options(args) do +        stop_on Commands.instance_methods +        banner <<-EOM  HCl is a command-line client for manipulating Harvest time sheets.  Commands: @@ -81,6 +93,7 @@ Commands:      hcl tasks      hcl aliases      hcl set <key> <value ...> +    hcl unset <key>      hcl start <task> [msg]      hcl stop [msg]      hcl note <msg> @@ -95,140 +108,54 @@ Examples:  Options:  EOM -    end -    @command = args.shift -    @args = args -    self -  end - -  def tasks -    tasks = Task.all -    if tasks.empty? -      puts "No cached tasks. Run `hcl show' to populate the cache and try again." -    else -      tasks.each { |task| puts "#{task.project.id} #{task.id}\t#{task}" } -    end -    nil -  end - -  def read_config -    if File.exists? CONFIG_FILE -      config = YAML::load File.read(CONFIG_FILE) -      TimesheetResource.configure config -    elsif File.exists? old_conf = File.dirname(__FILE__) + "/../hcl_conf.yml" -      config = YAML::load File.read(old_conf) -      TimesheetResource.configure config -      write_config config -    else -      config = {} -      puts "Please specify your Harvest credentials.\n" -      config['login'] = ask("Email Address: ") -      config['password'] = ask("Password: ") { |q| q.echo = false } -      config['subdomain'] = ask("Subdomain: ") -      TimesheetResource.configure config -      write_config config -    end -  end - -  def write_config config -    puts "Writing configuration to #{CONFIG_FILE}." -    File.open(CONFIG_FILE, 'w') do |f| -     f.write config.to_yaml -    end -  end - -  def read_settings -    if File.exists? SETTINGS_FILE -      @settings = YAML.load(File.read(SETTINGS_FILE)) -    else -      @settings = {} -    end -  end - -  def write_settings -    File.open(SETTINGS_FILE, 'w') do |f| -     f.write @settings.to_yaml -    end -    nil -  end - -  def set key = nil, *args -    if key.nil? -      @settings.each do |k, v| -        puts "#{k}: #{v}"        end -    else -      value = args.join(' ') -      @settings ||= {} -      @settings[key] = value -      write_settings +      @command = args.shift +      @args = args +      self      end -    nil -  end -  def unset key -    @settings.delete key -    write_settings -  end - -  def aliases -    @settings.keys.select { |s| s =~ /^task\./ }.map { |s| s.slice(5..-1) } -  end - -  def start *args -    starting_time = args.detect {|x| x =~ /^\+\d*(\.|:)\d+$/ } -    if starting_time -      args.delete(starting_time) -      starting_time = time2float starting_time -    end -    ident = args.shift -    task_ids = if @settings.key? "task.#{ident}" -        @settings["task.#{ident}"].split(/\s+/) +    protected +   +    def read_config +      if File.exists? CONFIG_FILE +        config = YAML::load File.read(CONFIG_FILE) +        TimesheetResource.configure config +      elsif File.exists? old_conf = File.dirname(__FILE__) + "/../hcl_conf.yml" +        config = YAML::load File.read(old_conf) +        TimesheetResource.configure config +        write_config config        else -        [ident, args.shift] +        config = {} +        puts "Please specify your Harvest credentials.\n" +        config['login'] = ask("Email Address: ") +        config['password'] = ask("Password: ") { |q| q.echo = false } +        config['subdomain'] = ask("Subdomain: ") +        TimesheetResource.configure config +        write_config config        end -    task = Task.find *task_ids -    if task.nil? -      puts "Unknown project/task alias, try one of the following: #{aliases.join(', ')}." -      exit 1      end -    timer = task.start(:starting_time => starting_time, :note => args.join(' ')) -    puts "Started timer for #{timer}." -  end - -  def stop -    entry = DayEntry.with_timer -    if entry -      entry.toggle -      puts "Stopped #{entry}." -    else -      puts "No running timers found." +   +    def write_config config +      puts "Writing configuration to #{CONFIG_FILE}." +      File.open(CONFIG_FILE, 'w') do |f| +       f.write config.to_yaml +      end      end -  end - -  def note *args -    message = args.join ' ' -    entry = DayEntry.with_timer -    if entry -      entry.append_note message -      puts "Added note '#{message}' to #{entry}." -    else -      puts "No running timers found." +   +    def read_settings +      if File.exists? SETTINGS_FILE +        @settings = YAML.load(File.read(SETTINGS_FILE)) +      else +        @settings = {} +      end      end -  end - -  def show *args -    date = args.empty? ? nil : Chronic.parse(args.join(' ')) -    total_hours = 0.0 -    DayEntry.all(date).each do |day| -      running = day.running? ? '(running) ' : '' -      puts "\t#{day.formatted_hours}\t#{running}#{day.project} #{day.notes}"[0..78] -      total_hours = total_hours + day.hours.to_f +   +    def write_settings +      File.open(SETTINGS_FILE, 'w') do |f| +       f.write @settings.to_yaml +      end +      nil      end -    puts "\t" + '-' * 13 -    puts "\t#{as_hours total_hours}\ttotal" -  end -    end  end diff --git a/lib/hcl/commands.rb b/lib/hcl/commands.rb new file mode 100644 index 0000000..5bc564f --- /dev/null +++ b/lib/hcl/commands.rb @@ -0,0 +1,90 @@ +module HCl +  module Commands +    def tasks +      tasks = Task.all +      if tasks.empty? +        puts "No cached tasks. Run `hcl show' to populate the cache and try again." +      else +        tasks.each { |task| puts "#{task.project.id} #{task.id}\t#{task}" } +      end +      nil +    end +   +    def set key = nil, *args +      if key.nil? +        @settings.each do |k, v| +          puts "#{k}: #{v}" +        end +      else +        value = args.join(' ') +        @settings ||= {} +        @settings[key] = value +        write_settings +      end +      nil +    end +   +    def unset key +      @settings.delete key +      write_settings +    end +   +    def aliases +      @settings.keys.select { |s| s =~ /^task\./ }.map { |s| s.slice(5..-1) } +    end +   +    def start *args +      starting_time = args.detect {|x| x =~ /^\+\d*(\.|:)\d+$/ } +      if starting_time +        args.delete(starting_time) +        starting_time = time2float starting_time +      end +      ident = args.shift +      task_ids = if @settings.key? "task.#{ident}" +          @settings["task.#{ident}"].split(/\s+/) +        else +          [ident, args.shift] +        end +      task = Task.find *task_ids +      if task.nil? +        puts "Unknown project/task alias, try one of the following: #{aliases.join(', ')}." +        exit 1 +      end +      timer = task.start(:starting_time => starting_time, :note => args.join(' ')) +      puts "Started timer for #{timer}." +    end +   +    def stop +      entry = DayEntry.with_timer +      if entry +        entry.toggle +        puts "Stopped #{entry}." +      else +        puts "No running timers found." +      end +    end +   +    def note *args +      message = args.join ' ' +      entry = DayEntry.with_timer +      if entry +        entry.append_note message +        puts "Added note '#{message}' to #{entry}." +      else +        puts "No running timers found." +      end +    end +   +    def show *args +      date = args.empty? ? nil : Chronic.parse(args.join(' ')) +      total_hours = 0.0 +      DayEntry.all(date).each do |day| +        running = day.running? ? '(running) ' : '' +        puts "\t#{day.formatted_hours}\t#{running}#{day.project} #{day.notes}"[0..78] +        total_hours = total_hours + day.hours.to_f +      end +      puts "\t" + '-' * 13 +      puts "\t#{as_hours total_hours}\ttotal" +    end +  end +end diff --git a/lib/hcl/utility.rb b/lib/hcl/utility.rb index 18782f6..bbd5065 100644 --- a/lib/hcl/utility.rb +++ b/lib/hcl/utility.rb @@ -1,11 +1,18 @@  module HCl    module Utility      # Convert from decimal to a string of the form HH:MM. +    # +    # @param [#to_f] hours number of hours in decimal +    # @return [String] of the form "HH:MM"      def as_hours hours        minutes = hours.to_f * 60.0        sprintf "%d:%02d", (minutes / 60).to_i, (minutes % 60).to_i      end +    # Convert from a time span in hour or decimal format to a float. +    # +    # @param [String] time_string either "M:MM" or decimal +    # @return [#to_f] converted to a floating-point number      def time2float time_string        if time_string =~ /:/          hours, minutes = time_string.split(':') | 
