lib/mite_cmd/application.rb
if RUBY_VERSION >= '1.9'
require 'fileutils'
else
require 'ftools'
end
module MiteCmd
class Application
TIME_FORMAT = /^(\d+(\.\d+)?:?\+?)|(\d+:\d+\+?)|\+$/
FLIRTS = [
'I like your hairstyle.', 'What a nice console you have.', 'My favorite color is red on black, monospaced.',
"What a lovely operation system this #{`uname`} is.", 'What about dinner tonight?', 'Your keystrokes are tingling.'
]
def initialize(arguments=[])
@arguments = arguments
MiteCmd.load_configuration unless ['configure', 'help'].include?(arguments.first)
end
def run
if @arguments.empty?
current
else
dispatch(@arguments)
end
end
def say(what)
puts what
end
alias_method :tell, :say
def flirt
FLIRTS[rand(FLIRTS.size)]
end
private
def auto_complete(arguments)
autocomplete = MiteCmd::Autocomplete.new(MiteCmd.calling_script)
autocomplete.completion_table = MiteCmd::CompletionTable.new(cache_file)
autocomplete.suggestions.map(&:quote_if_spaced).each { |s| tell s }
end
def configure(arguments)
raise MiteCmd::Exception.new('mite configure needs two arguments, the account name and the apikey') if @arguments.size < 3 # lol boobs, err... an ice cone!
write_configuration({:account => @arguments[1], :apikey => @arguments[2]})
tell("Couldn't set up bash completion. I'm terribly frustrated. Maybe 'mite help' helps out.") unless try_to_setup_bash_completion
end
def create_time_entry(arguments)
attributes = {}
if time_string = arguments.select { |a| a =~ TIME_FORMAT }.first
attributes[:minutes] = parse_minutes(time_string)
start_tracker = (time_string =~ /\+$/)
end
if project = find_or_create_project(arguments.first)
attributes[:project_id] = project.id
end
if @arguments[1] && service = find_or_create_service(arguments[1])
attributes[:service_id] = service.id
end
if note = parse_note(arguments, time_string)
attributes[:note] = note
end
time_entry = Mite::TimeEntry.create attributes
time_entry.start_tracker if start_tracker
tell time_entry.inspect
end
def current
tell Mite::Tracker.current ? Mite::Tracker.current.inspect : flirt
end
def method_for_command(command)
{
'auto-complete' => :auto_complete,
'configure' => :configure,
'help' => :help,
'lunch' => :stop,
'note' => :note,
'open' => :open,
'pause' => :stop,
'rebuild-cache' => :rebuild_cache,
'start' => :start,
'stop' => :stop
}[command]
end
def dispatch(arguments)
command, *arguments_for_command = arguments
method = method_for_command(command)
if method
send(method, arguments_for_command)
else
if ['today', 'yesterday', 'this_week', 'last_week', 'this_month', 'last_month'].include?(command)
report(command)
else
create_time_entry(arguments)
end
end
end
def help(arguments)
open_or_echo 'http://github.com/Overbryd/mite.cmd'
end
def note(arguments)
if time_entry = Mite::TimeEntry.first(:params => {:at => 'today'})
time_entry.note = [time_entry.note, *arguments].compact.join(' ')
time_entry.save
tell time_entry.inspect
end
end
def open(arguments)
open_or_echo Mite.account_url
end
def rebuild_cache(arguments)
rebuild_completion_table
tell 'The rebuilding of the cache has been done, Master. Your wish is my command.'
end
def report(arguments)
total_minutes = 0
total_revenue = Mite::TimeEntry.all(:params => {:at => arguments, :user_id => 'current'}).each do |time_entry|
total_minutes += time_entry.minutes
tell time_entry.inspect
end.map(&:revenue).compact.sum
tell ("%s:%.2d" % [total_minutes/60, total_minutes-total_minutes/60*60]).colorize(:lightred) + ", " + ("%.2f $" % (total_revenue/100)).colorize(:lightgreen)
end
def start(arguments)
if time_entry = Mite::TimeEntry.first(:params => {:at => 'today'})
time_entry.start_tracker
tell time_entry.inspect
else
tell "Oh my dear! I tried hard, but I could'nt find any time entry for today."
end
end
def stop(arguments)
if current_tracker = (Mite::Tracker.current ? Mite::Tracker.current.stop : nil)
tell current_tracker.time_entry.inspect
end
end
def find_or_create_by_name(repository, name)
object = repository.first(:params => {:name => name})
return nil if name =~ TIME_FORMAT
object ? object : repository.create(:name => name)
end
def find_or_create_project(name)
find_or_create_by_name(Mite::Project, name)
end
def find_or_create_service(name)
find_or_create_by_name(Mite::Service, name)
end
def parse_note(args, time_string)
if args[3]
args[3]
elsif time_string.nil? && args[2]
args[2]
elsif time_string && args[args.index(time_string)+1]
args[args.index(time_string)+1]
else
nil
end
end
def parse_minutes(string)
string = string.sub(/\+$/, '')
if string.blank?
0
elsif string =~ /^\d+:\d+$/
string.split(':').first.to_i*60 + string.split(':').last.to_i
elsif string =~ /^\d+(\.\d+)?:?$/
(string.to_f*60).to_i
end
end
def rebuild_completion_table
MiteCmd::CompletionTable.new(cache_file).rebuild
end
def cache_file
File.expand_path('~/.mite.cache')
end
def open_or_echo(open_argument)
exec "open '#{open_argument}' || echo '#{open_argument}'"
end
def write_configuration(config)
File.open(File.expand_path('~/.mite.yml'), 'w') do |f|
YAML.dump(config, f)
end
File.chmod(0600, File.expand_path('~/.mite.yml'))
end
def try_to_setup_bash_completion
bash_code = "\n\n#{MiteCmd::BASH_COMPLETION}"
['~/.bash_completion', '~/.bash_profile', '~/.bash_login', '~/.bashrc'].each do |file|
bash_config_file = File.expand_path file
next unless File.file?(bash_config_file)
unless File.read(bash_config_file) =~ /#{bash_code}/
File.open(bash_config_file, 'a') do |f|
f.puts bash_code
end
return true
else
return true
end
end
return false
end
end
end