achoo 0.4.2 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGES +13 -0
  2. data/README.rdoc +26 -22
  3. data/lib/achoo/achievo/hour_administration_form.rb +2 -3
  4. data/lib/achoo/achievo/hour_registration_form.rb +12 -15
  5. data/lib/achoo/achievo/hour_registration_form_ranged.rb +5 -2
  6. data/lib/achoo/achievo/lock_month_form.rb +1 -5
  7. data/lib/achoo/achievo/login_form.rb +3 -3
  8. data/lib/achoo/app.rb +27 -28
  9. data/lib/achoo/awake.rb +1 -1
  10. data/lib/achoo/extensions.rb +4 -0
  11. data/lib/achoo/ical.rb +6 -2
  12. data/lib/achoo/plugin/awake.rb +23 -0
  13. data/lib/achoo/plugin/ical.rb +47 -0
  14. data/lib/achoo/plugin/vcs.rb +26 -0
  15. data/lib/achoo/plugin_base.rb +6 -0
  16. data/lib/achoo/rc_loader.rb +9 -0
  17. data/lib/achoo/temporal/timespan.rb +3 -3
  18. data/lib/achoo/term.rb +7 -3
  19. data/lib/achoo/term/table.rb +5 -6
  20. data/lib/achoo/ui/commands.rb +12 -12
  21. data/lib/achoo/ui/date_chooser.rb +1 -1
  22. data/lib/achoo/ui/exception_handling.rb +1 -1
  23. data/lib/achoo/ui/register_hours.rb +50 -50
  24. data/lib/achoo/vcs/git.rb +5 -3
  25. data/test/acceptance/test_flexi_time.rb +41 -0
  26. data/test/acceptance/test_lock_month.rb +39 -0
  27. data/test/acceptance/test_register_hours.rb +161 -0
  28. data/test/lib/achievo_mock.rb +76 -0
  29. data/test/lib/achoo_runner.rb +54 -0
  30. data/test/lib/test_helpers.rb +43 -0
  31. data/test/unit/test_achievo_date_field.rb +34 -0
  32. data/test/unit/test_awake.rb +98 -0
  33. data/test/unit/test_extensions_array.rb +25 -0
  34. data/test/unit/test_system_cstruct.rb +28 -0
  35. data/test/unit/test_system_log_entry.rb +31 -0
  36. data/test/unit/test_term_menu.rb +71 -0
  37. data/test/unit/test_term_table.rb +52 -0
  38. data/test/unit/test_timespan.rb +48 -0
  39. data/test/unit/test_ui_date_chooser.rb +36 -0
  40. metadata +101 -74
@@ -0,0 +1,26 @@
1
+ require 'achoo'
2
+ require 'achoo/vcs'
3
+ require 'achoo/ui'
4
+ require 'plugman/plugin_base'
5
+
6
+ module Achoo
7
+ class Plugin
8
+ class VCS < Plugman::PluginBase
9
+
10
+ include UI::ExceptionHandling
11
+
12
+ def state_ok?; RC.has_key?(:vcs_dirs); end
13
+
14
+ def before_register_hour_remark(date)
15
+ puts '-' * 80
16
+ puts "VCS logs for #{date}:"
17
+ begin
18
+ Achoo::VCS.print_logs_for(date, RC[:vcs_dirs])
19
+ rescue Exception => e
20
+ puts handle_exception("Failed to retrieve VCS logs.", e)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ require 'plugman/plugin_base'
2
+
3
+ module Achoo
4
+ class PluginBase < Plugman::PluginBase
5
+ end
6
+ end
@@ -49,6 +49,15 @@ module Achoo
49
49
  RC[key] = []
50
50
  end
51
51
  end
52
+
53
+ if RC.has_key?(:ical)
54
+ RC[:ical].each do |cal|
55
+ if cal.has_key?(:host)
56
+ puts Term.warn "You are using the old configuration format for ical. See the README for information on the new format"
57
+ return
58
+ end
59
+ end
60
+ end
52
61
  end
53
62
 
54
63
  end
@@ -18,14 +18,14 @@ module Achoo
18
18
  def contains?(timeish_or_timespan)
19
19
  if timeish_or_timespan.is_a? Timespan
20
20
  time = timeish_or_timespan
21
- include?(time.first) && include?(time.last)
21
+ cover?(time.first) && cover?(time.last)
22
22
  else
23
- include?(to_time(timeish_or_timespan))
23
+ cover?(to_time(timeish_or_timespan))
24
24
  end
25
25
  end
26
26
 
27
27
  def overlaps?(timespan)
28
- include?(timespan.first) || include?(timespan.last) ||
28
+ cover?(timespan.first) || cover?(timespan.last) ||
29
29
  timespan.contains?(self)
30
30
  end
31
31
 
data/lib/achoo/term.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'achoo'
4
+ require 'readline'
4
5
 
5
6
  module Achoo
6
7
  class Term
@@ -20,6 +21,11 @@ module Achoo
20
21
  def self.warn(text); effect(YELLOW, text); end
21
22
  def self.fatal(text); effect(RED, text); end
22
23
 
24
+ def self.clearscreen
25
+ print "\e[2J\e[H"
26
+ $stdout.flush
27
+ end
28
+
23
29
  def self.password
24
30
  `stty -echo`
25
31
  pas = ask('Password')
@@ -30,9 +36,7 @@ module Achoo
30
36
  def self.ask(question='')
31
37
  answer = nil
32
38
  loop do
33
- print bold("#{question}> ")
34
- $stdout.flush
35
- answer = gets
39
+ answer = Readline.readline(bold("#{question}> "), true)
36
40
 
37
41
  # Answer is nil if user hits C-d on an empty input
38
42
  if answer.nil?
@@ -65,13 +65,12 @@ module Achoo
65
65
  end
66
66
 
67
67
  def calculate_table_cell_widths
68
- lengths = []
69
- @headers.each_with_index do |h, i|
70
- lengths[i] = h.length
71
- end
72
- @data_rows.each do |r|
68
+ rows = [@headers] + @data_rows
69
+ rows += [@summaries] unless @summaries.nil?
70
+ lengths = Array.new(@headers.length, 0)
71
+ rows.each do |r|
73
72
  r.each_with_index do |d, i|
74
- lengths[i] = [d.length, lengths[i]].max
73
+ lengths[i] = [d.scan(/./mu).length, lengths[i]].max # FIX scan is a 1.8 hack
75
74
  end
76
75
  end
77
76
  lengths
@@ -9,30 +9,30 @@ module Achoo
9
9
  include DateChoosers
10
10
  include Common
11
11
 
12
- def show_registered_hours_for_day(agent)
12
+ def show_registered_hours_for_day
13
13
  date = date_chooser
14
- form = Achievo::HourAdministrationForm.new(agent)
14
+ form = Achievo::HourAdministrationForm.new
15
15
  form.show_registered_hours_for_day(date)
16
16
  end
17
17
 
18
- def show_registered_hours_for_week(agent)
18
+ def show_registered_hours_for_week
19
19
  date = date_chooser
20
- form = Achievo::HourAdministrationForm.new(agent)
20
+ form = Achievo::HourAdministrationForm.new
21
21
  form.show_registered_hours_for_week(date)
22
22
  end
23
23
 
24
24
 
25
- def show_flexi_time(agent)
25
+ def show_flexi_time
26
26
  date = date_chooser
27
- form = Achievo::HourAdministrationForm.new(agent)
27
+ form = Achievo::HourAdministrationForm.new
28
28
  balance = form.flexi_time(date)
29
29
  puts "Flexi time balance: #{Term::underline(balance)}"
30
30
  end
31
31
 
32
32
 
33
- def lock_month(agent)
33
+ def lock_month
34
34
  month = month_chooser
35
- form = Achievo::LockMonthForm.new(agent)
35
+ form = Achievo::LockMonthForm.new
36
36
  form.lock_month(month)
37
37
  form.print_values
38
38
  if confirm
@@ -43,20 +43,20 @@ module Achoo
43
43
  end
44
44
 
45
45
 
46
- def show_holiday_report(agent)
47
- page = agent.get(RC[:holiday_report_url])
46
+ def show_holiday_report
47
+ page = AGENT.get(RC[:holiday_report_url])
48
48
  page.body.match(/<b>(\d+,\d+)<\/b>/)
49
49
  puts "Balance: #{Term::underline($1)}"
50
50
  end
51
51
 
52
52
 
53
- def view_report(agent)
53
+ def view_report
54
54
  choices = RC[:reports].keys
55
55
  answer = Term.choose('Report', choices)
56
56
  key = choices[answer.to_i - 1]
57
57
 
58
58
  puts "Fetching data ..."
59
- page = agent.get(RC[:url] + RC[:reports][key])
59
+ page = AGENT.get(RC[:url] + RC[:reports][key])
60
60
 
61
61
  table = Achievo::Table.new(page.search('#rl_1 tr'))
62
62
  table.select_columns do |c|
@@ -67,7 +67,7 @@ module Achoo
67
67
  puts "Accepted formats:"
68
68
  puts date_format_help_string
69
69
  puts
70
- system 'cal -3m'
70
+ system 'cal -3'
71
71
  end
72
72
 
73
73
  def date_format_help_string
@@ -14,7 +14,7 @@ module Achoo
14
14
  end
15
15
 
16
16
  def get_exception_reason(e)
17
- "\nReason: \n\t" + e.message.gsub("\n", "\n\t") + "\n---\n\t" + e.backtrace.join("\n\t")
17
+ "\nType:\t" + e.class.to_s + "\nReason: \n\t" + e.message.gsub("\n", "\n\t") + "\n---\n\t" + e.backtrace.join("\n\t")
18
18
  end
19
19
 
20
20
  end
@@ -1,9 +1,7 @@
1
1
  require 'achoo/achievo'
2
- require 'achoo/awake'
3
- require 'achoo/ical'
4
2
  require 'achoo/term'
5
3
  require 'achoo/ui'
6
- require 'achoo/vcs'
4
+ require 'readline'
7
5
 
8
6
  module Achoo
9
7
  module UI
@@ -12,7 +10,10 @@ module Achoo
12
10
  include DateChoosers
13
11
  include ExceptionHandling
14
12
 
15
- def register_hours(agent)
13
+ def initialize
14
+ end
15
+
16
+ def register_hours
16
17
  date = optionally_ranged_date_chooser
17
18
 
18
19
  puts "Fetching data ..."
@@ -20,14 +21,14 @@ module Achoo
20
21
  Achievo::HourRegistrationFormRanged
21
22
  else
22
23
  Achievo::HourRegistrationForm
23
- end.new(agent)
24
+ end.new
24
25
 
25
26
  form.date = date
26
27
  form.project = project_chooser(form)
27
28
  form.phase = phase_chooser(form)
28
- print_remark_help(date) unless date.class == Array
29
+ PLUGINS.send_before_register_hour_remark(date) unless date.class == Array
29
30
  form.remark = remark_chooser
30
- print_hours_help(date) unless date.class == Array
31
+ PLUGINS.send_before_register_hour_hours(date) unless date.class == Array
31
32
  form.hours = hours_chooser
32
33
 
33
34
  answer = Term.ask("Do you want to change the defaults for worktime period and/or billing percentage? [N/y]").downcase
@@ -43,6 +44,8 @@ module Achoo
43
44
  else
44
45
  puts "Cancelled"
45
46
  end
47
+
48
+ date
46
49
  end
47
50
 
48
51
 
@@ -53,17 +56,6 @@ module Achoo
53
56
  end
54
57
 
55
58
 
56
- def print_hours_help(date)
57
- puts "Awake log:"
58
- begin
59
- awake = Awake.new
60
- awake.at(date)
61
- puts
62
- rescue Exception => e
63
- print handle_exception("Failed to retrieve awake log.", e)
64
- end
65
- end
66
-
67
59
  def hours_chooser
68
60
  answer = Term::ask 'Hours [7:30]'
69
61
  return answer == '' ? '7.5' : answer
@@ -83,25 +75,6 @@ module Achoo
83
75
  true)
84
76
  end
85
77
 
86
- def print_remark_help(date)
87
- puts "VCS logs for #{date}:"
88
- begin
89
- VCS.print_logs_for(date, RC[:vcs_dirs])
90
- rescue Exception => e
91
- puts handle_exception("Failed to retrieve VCS logs.", e)
92
- end
93
- puts '-' * 80
94
- puts "Calendar events for #{date}:"
95
- puts '---'
96
- begin
97
- RC[:ical].each do |config|
98
- ICal.from_http_request(config).print_events(date)
99
- end
100
- rescue Exception => e
101
- puts handle_exception("Failed to retrieve calendar events.", e)
102
- end
103
- end
104
-
105
78
  def remark_chooser
106
79
  Term::ask 'Remark'
107
80
  end
@@ -112,29 +85,56 @@ module Achoo
112
85
  projects = form.recent_projects
113
86
  answer = Term.choose('Project [1]', projects.collect { |p| p[1] },
114
87
  'Other', [''])
115
- case answer
116
- when ''
117
- projects[0][0]
118
- when '0'
119
- return all_projects_chooser(form)
120
- else
121
- return projects[answer.to_i-1][0]
122
- end
88
+ return case answer
89
+ when '0'
90
+ all_projects_chooser(form)
91
+ when ''
92
+ projects[0][0]
93
+ else
94
+ projects[answer.to_i-1][0]
95
+ end
123
96
  end
124
97
 
125
98
 
126
99
 
127
100
  def all_projects_chooser(form)
128
- chooser_helper(form.all_projects,
129
- 'All projects',
130
- 'Project')
101
+ projects = form.all_projects
102
+
103
+ p projects
104
+
105
+ # FIX move readline stuff to the term modules
106
+ original_readline_comp_proc = Readline.completion_proc
107
+ original_readline_comp_append_char = Readline.completion_append_character
108
+ Readline.completion_append_character = ''
109
+ Readline.completion_proc = proc do |s|
110
+ projects.collect {|p| p[1] }.grep(/^#{Regexp.escape(s)}/)
111
+ end
112
+
113
+
114
+ answer = chooser_helper(projects,
115
+ 'All projects',
116
+ 'Project')
117
+
118
+ Readline.completion_proc = original_readline_comp_proc
119
+ Readline.completion_append_character = original_readline_comp_append_char
120
+
121
+ answer
131
122
  end
132
123
 
133
124
  def chooser_helper(options, heading, prompt, empty_allowed=false)
134
- puts heading
135
125
  extra = empty_allowed ? [''] : []
136
- answer = Achoo::Term.choose(prompt, options.collect {|p| p[1] }, nil, [''])
126
+ project_names = options.collect {|p| p[1] }
127
+ if heading == 'All projects'
128
+ # FIX ugly conditional
129
+ extra += project_names
130
+ end
131
+ answer = Achoo::Term.choose(prompt, options.collect {|p| p[1] }, nil, extra)
137
132
  answer = '1' if answer.empty?
133
+ if heading == 'All projects'
134
+ # FIX ugly conditional
135
+ index = project_names.find_index(answer) + 1
136
+ answer = index unless index.nil?
137
+ end
138
138
  options[answer.to_i-1][0]
139
139
  end
140
140
 
data/lib/achoo/vcs/git.rb CHANGED
@@ -13,10 +13,12 @@ module Achoo
13
13
  end
14
14
 
15
15
  def log_for(date)
16
- today = date.strftime('%Y-%m-%d')
17
- tomorrow = date.next.strftime('%Y-%m-%d')
16
+ format = '%Y-%m-%dT00:00:00'
17
+ from = date.strftime(format)
18
+ to = (date+1).strftime(format)
18
19
 
19
- `cd #@dir; git log --author=#{ENV['USER']} --oneline --after=#{today} --before=#{tomorrow} | cut -d ' ' -f 2-`
20
+ cmd = "cd #@dir; git log --author=#{ENV['USER']} --oneline --after=#{from} --before=#{to} | cut -d ' ' -f 2-"
21
+ `#{cmd}`
20
22
  end
21
23
 
22
24
  end
@@ -0,0 +1,41 @@
1
+ require 'test_helpers'
2
+
3
+ class TestFlexiTime < Test::Unit::TestCase
4
+
5
+ include AcceptanceBase
6
+
7
+ def setup
8
+ super
9
+
10
+ hour_administration_html = %q{
11
+ <html>
12
+ <head></head>
13
+ <body>
14
+ <form name="dayview">
15
+ <input type="text" name="viewdate[day]" value="20">
16
+ <input type="text" name="viewdate[month]" value="03">
17
+ <input type="text" name="viewdate[year]" value="2010">
18
+ </form>
19
+
20
+ <p>Flexi time balance: -44:30</p>
21
+
22
+ </body>
23
+ </html>
24
+ }
25
+
26
+ @server.register(:get, '/time_registration', [ 200, nil, hour_administration_html ])
27
+ end
28
+
29
+ def test_flexi_time
30
+ achoo(:verbose => $DEBUG) do
31
+ expect '2. Show flexitime balance'
32
+ expect_main_prompt
33
+ puts '2'
34
+ puts '2010-03-20'
35
+ expect /Flexi time balance:.*-44:30/
36
+ expect_main_prompt
37
+ puts 'q'
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helpers'
2
+
3
+ class TestLockMonth < Test::Unit::TestCase
4
+
5
+ include AcceptanceBase
6
+
7
+ def setup
8
+ super
9
+
10
+ lock_month_html = %q{
11
+ <html>
12
+ <head></head>
13
+ <body>
14
+ <form name="entryform">
15
+ <input type="text" name="period" value="">
16
+ </form>
17
+ </body>
18
+ </html>
19
+ }
20
+
21
+ @server.register(:get, '/lock_months', [ 200, nil, lock_month_html ])
22
+ end
23
+
24
+ def test_lock_month
25
+ achoo(:verbose => $DEBUG) do
26
+ expect '6. Lock month'
27
+ expect_main_prompt
28
+ puts '6'
29
+ expect /Period \(\[\d{6}\] | YYYYMM\)>/
30
+ puts '201003'
31
+ expect 'Month: 201003'
32
+ expect 'Submit? [Y/n]>'
33
+ puts 'n'
34
+ expect 'Cancelled'
35
+ expect_main_prompt
36
+ puts 'q'
37
+ end
38
+ end
39
+ end