achoo 0.3 → 0.4.1

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.
Files changed (53) hide show
  1. data/CHANGES +12 -0
  2. data/README.rdoc +26 -30
  3. data/Rakefile +3 -0
  4. data/bin/achoo +2 -2
  5. data/lib/achoo.rb +1 -139
  6. data/lib/achoo/achievo.rb +13 -0
  7. data/lib/achoo/achievo/form.rb +22 -0
  8. data/lib/achoo/achievo/hour_administration_form.rb +91 -0
  9. data/lib/achoo/achievo/hour_registration_form.rb +230 -0
  10. data/lib/achoo/achievo/hour_registration_form_ranged.rb +49 -0
  11. data/lib/achoo/achievo/lock_month_form.rb +44 -0
  12. data/lib/achoo/achievo/login_form.rb +27 -0
  13. data/lib/achoo/achievo/table.rb +30 -0
  14. data/lib/achoo/app.rb +153 -0
  15. data/lib/achoo/awake.rb +86 -100
  16. data/lib/achoo/extensions.rb +24 -0
  17. data/lib/achoo/ical.rb +47 -40
  18. data/lib/achoo/rc_loader.rb +42 -42
  19. data/lib/achoo/system.rb +8 -3
  20. data/lib/achoo/system/cstruct.rb +67 -0
  21. data/lib/achoo/system/log_entry.rb +24 -0
  22. data/lib/achoo/system/pm_suspend.rb +17 -20
  23. data/lib/achoo/system/utmp_record.rb +64 -0
  24. data/lib/achoo/system/wtmp.rb +14 -10
  25. data/lib/achoo/temporal.rb +8 -0
  26. data/lib/achoo/temporal/open_timespan.rb +16 -0
  27. data/lib/achoo/temporal/timespan.rb +122 -0
  28. data/lib/achoo/term.rb +58 -56
  29. data/lib/achoo/term/menu.rb +2 -2
  30. data/lib/achoo/term/table.rb +59 -60
  31. data/lib/achoo/ui.rb +13 -9
  32. data/lib/achoo/ui/commands.rb +60 -38
  33. data/lib/achoo/ui/common.rb +10 -7
  34. data/lib/achoo/ui/date_chooser.rb +69 -65
  35. data/lib/achoo/ui/date_choosers.rb +15 -14
  36. data/lib/achoo/ui/exception_handling.rb +14 -12
  37. data/lib/achoo/ui/month_chooser.rb +37 -24
  38. data/lib/achoo/ui/optionally_ranged_date_chooser.rb +29 -25
  39. data/lib/achoo/ui/register_hours.rb +116 -114
  40. data/lib/achoo/vcs.rb +32 -30
  41. data/lib/achoo/vcs/git.rb +18 -14
  42. data/lib/achoo/vcs/subversion.rb +25 -23
  43. metadata +30 -24
  44. data/lib/achoo/binary.rb +0 -7
  45. data/lib/achoo/binary/cstruct.rb +0 -60
  46. data/lib/achoo/binary/utmp_record.rb +0 -59
  47. data/lib/achoo/form.rb +0 -18
  48. data/lib/achoo/hour_administration_form.rb +0 -131
  49. data/lib/achoo/hour_registration_form.rb +0 -227
  50. data/lib/achoo/hour_registration_form_ranged.rb +0 -45
  51. data/lib/achoo/lock_month_form.rb +0 -40
  52. data/lib/achoo/open_timespan.rb +0 -13
  53. data/lib/achoo/timespan.rb +0 -119
data/lib/achoo/ui.rb CHANGED
@@ -1,10 +1,14 @@
1
- class Achoo; class UI; end; end
1
+ require 'achoo'
2
2
 
3
- Achoo::UI.autoload :Commands, 'achoo/ui/commands'
4
- Achoo::UI.autoload :Common, 'achoo/ui/common'
5
- Achoo::UI.autoload :DateChooser, 'achoo/ui/date_chooser'
6
- Achoo::UI.autoload :DateChoosers, 'achoo/ui/date_choosers'
7
- Achoo::UI.autoload :ExceptionHandling, 'achoo/ui/exception_handling'
8
- Achoo::UI.autoload :MonthChooser, 'achoo/ui/month_chooser'
9
- Achoo::UI.autoload :OptionallyRangedDateChooser, 'achoo/ui/optionally_ranged_date_chooser'
10
- Achoo::UI.autoload :RegisterHours, 'achoo/ui/register_hours'
3
+ module Achoo
4
+ module UI
5
+ autoload :Commands, 'achoo/ui/commands'
6
+ autoload :Common, 'achoo/ui/common'
7
+ autoload :DateChooser, 'achoo/ui/date_chooser'
8
+ autoload :DateChoosers, 'achoo/ui/date_choosers'
9
+ autoload :ExceptionHandling, 'achoo/ui/exception_handling'
10
+ autoload :MonthChooser, 'achoo/ui/month_chooser'
11
+ autoload :OptionallyRangedDateChooser, 'achoo/ui/optionally_ranged_date_chooser'
12
+ autoload :RegisterHours, 'achoo/ui/register_hours'
13
+ end
14
+ end
@@ -1,51 +1,73 @@
1
- require 'achoo/hour_administration_form'
2
- require 'achoo/lock_month_form'
1
+ require 'achoo/achievo'
2
+ require 'achoo/term'
3
3
  require 'achoo/ui'
4
4
 
5
- module Achoo::UI::Commands
5
+ module Achoo
6
+ module UI
7
+ module Commands
6
8
 
7
- include Achoo::UI::DateChoosers
8
- include Achoo::UI::Common
9
+ include DateChoosers
10
+ include Common
9
11
 
10
- def show_registered_hours_for_day(agent)
11
- date = date_chooser
12
- form = Achoo::HourAdministrationForm.new(agent)
13
- form.show_registered_hours_for_day(date)
14
- end
12
+ def show_registered_hours_for_day(agent)
13
+ date = date_chooser
14
+ form = Achievo::HourAdministrationForm.new(agent)
15
+ form.show_registered_hours_for_day(date)
16
+ end
15
17
 
16
- def show_registered_hours_for_week(agent)
17
- date = date_chooser
18
- form = Achoo::HourAdministrationForm.new(agent)
19
- form.show_registered_hours_for_week(date)
20
- end
18
+ def show_registered_hours_for_week(agent)
19
+ date = date_chooser
20
+ form = Achievo::HourAdministrationForm.new(agent)
21
+ form.show_registered_hours_for_week(date)
22
+ end
21
23
 
22
24
 
23
- def show_flexi_time(agent)
24
- date = date_chooser
25
- form = Achoo::HourAdministrationForm.new(agent)
26
- balance = form.flexi_time(date)
27
- puts "Flexi time balance: #{Achoo::Term::underline(balance)}"
28
- end
25
+ def show_flexi_time(agent)
26
+ date = date_chooser
27
+ form = Achievo::HourAdministrationForm.new(agent)
28
+ balance = form.flexi_time(date)
29
+ puts "Flexi time balance: #{Term::underline(balance)}"
30
+ end
29
31
 
30
32
 
31
- def lock_month(agent)
32
- month = month_chooser
33
- form = Achoo::LockMonthForm.new(agent)
34
- form.lock_month(month)
35
- form.print_values
36
- if confirm
37
- form.submit
38
- else
39
- puts "Cancelled"
40
- end
41
- end
33
+ def lock_month(agent)
34
+ month = month_chooser
35
+ form = Achievo::LockMonthForm.new(agent)
36
+ form.lock_month(month)
37
+ form.print_values
38
+ if confirm
39
+ form.submit
40
+ else
41
+ puts "Cancelled"
42
+ end
43
+ end
42
44
 
43
45
 
44
- def show_holiday_report(agent)
45
- page = agent.get(RC[:holiday_report_url])
46
- page.body.match(/<b>(\d+,\d+)<\/b>/)
47
- puts "Balance: #{Achoo::Term::underline($1)}"
48
- end
49
-
46
+ def show_holiday_report(agent)
47
+ page = agent.get(RC[:holiday_report_url])
48
+ page.body.match(/<b>(\d+,\d+)<\/b>/)
49
+ puts "Balance: #{Term::underline($1)}"
50
+ end
50
51
 
52
+
53
+ def view_report(agent)
54
+ choices = RC[:reports].keys
55
+ answer = Term.choose('Report', choices)
56
+ key = choices[answer.to_i - 1]
57
+
58
+ puts "Fetching data ..."
59
+ page = agent.get(RC[:url] + RC[:reports][key])
60
+
61
+ table = Achievo::Table.new(page.search('#rl_1 tr'))
62
+ table.select_columns do |c|
63
+ ['Date', 'Project', 'Phase', 'Remark', 'Time'].include?(c[0])
64
+ end
65
+
66
+ Term::Table.new(table.first,
67
+ table[2...table.length-1],
68
+ table.last).print
69
+ end
70
+
71
+ end
72
+ end
51
73
  end
@@ -1,15 +1,18 @@
1
1
  require 'achoo/term'
2
+ require 'achoo/ui'
2
3
 
3
- class Achoo; class UI; end; end
4
+ module Achoo
5
+ module UI
6
+ module Common
4
7
 
5
- module Achoo::UI::Common
8
+ def confirm
9
+ answer = Term::ask "Submit? [Y/n]"
10
+ answer.downcase!
11
+ return answer == 'y' || answer == ''
12
+ end
6
13
 
7
- def confirm
8
- answer = Achoo::Term::ask "Submit? [Y/n]"
9
- answer.downcase!
10
- return answer == 'y' || answer == ''
14
+ end
11
15
  end
12
-
13
16
  end
14
17
 
15
18
 
@@ -1,75 +1,79 @@
1
1
  require 'achoo/term'
2
+ require 'achoo/ui'
2
3
 
3
- class Achoo; class UI; end; end
4
+ module Achoo
5
+ module UI
4
6
 
5
- class Achoo::UI::DateChooser
7
+ class DateChooser
6
8
 
7
- PROMPT = "Date ([today] | ?)"
8
- FORMAT = " today | (+|-)n | [[[YY]YY]-[M]M]-[D]D"
9
+ PROMPT = "Date ([today] | ?)"
10
+ FORMAT = " today | (+|-)n | [[[YY]YY]-[M]M]-[D]D"
9
11
 
10
- def choose
11
- loop do
12
- answer = Achoo::Term::ask PROMPT
13
- begin
14
- date = handle_answer(answer)
15
- return date if date
16
- rescue ArgumentError => e
17
- puts e
12
+ def choose
13
+ loop do
14
+ answer = Term::ask PROMPT
15
+ begin
16
+ date = handle_answer(answer)
17
+ return date if date
18
+ rescue ArgumentError => e
19
+ puts e
20
+ end
21
+ end
22
+ end
23
+
24
+ def parse_date(date_str, base=Date.today)
25
+ raise ArgumentError.new('Invalid date') if date_str.nil?
26
+
27
+ # Today (default)
28
+ if date_str == 'today' || date_str.empty?
29
+ return Date.today
30
+ end
31
+
32
+ # Base offset
33
+ case date_str.chars.first
34
+ when '-'
35
+ return base - Integer(date_str[1..-1])
36
+ when '+'
37
+ return base + Integer(date_str[1..-1])
38
+ end
39
+
40
+ #
41
+ date = date_str.split('-').collect {|d| d.to_i}
42
+ case date.length
43
+ when 1
44
+ return Date.civil(base.year, base.month, *date)
45
+ when 2
46
+ return Date.civil(base.year, *date)
47
+ when 3
48
+ date[0] += 2000 if date[0] < 100
49
+ return Date.civil(*date)
50
+ end
51
+
52
+ raise ArgumentError.new('Invalid date')
53
+ end
54
+
55
+ private
56
+
57
+ def handle_answer(answer)
58
+ if answer == '?'
59
+ print_help_message
60
+ return false
61
+ else
62
+ return parse_date(answer)
63
+ end
64
+ end
65
+
66
+ def print_help_message
67
+ puts "Accepted formats:"
68
+ puts date_format_help_string
69
+ puts
70
+ system 'cal -3m'
71
+ end
72
+
73
+ def date_format_help_string
74
+ FORMAT
18
75
  end
19
- end
20
- end
21
-
22
- def parse_date(date_str, base=Date.today)
23
- raise ArgumentError.new('Invalid date') if date_str.nil?
24
-
25
- # Today (default)
26
- if date_str == 'today' || date_str.empty?
27
- return Date.today
28
- end
29
-
30
- # Base offset
31
- case date_str.chars.first
32
- when '-'
33
- return base - Integer(date_str[1..-1])
34
- when '+'
35
- return base + Integer(date_str[1..-1])
36
- end
37
-
38
- #
39
- date = date_str.split('-').collect {|d| d.to_i}
40
- case date.length
41
- when 1
42
- return Date.civil(base.year, base.month, *date)
43
- when 2
44
- return Date.civil(base.year, *date)
45
- when 3
46
- date[0] += 2000 if date[0] < 100
47
- return Date.civil(*date)
48
- end
49
-
50
- raise ArgumentError.new('Invalid date')
51
- end
52
-
53
- private
54
76
 
55
- def handle_answer(answer)
56
- if answer == '?'
57
- print_help_message
58
- return false
59
- else
60
- return parse_date(answer)
61
77
  end
62
78
  end
63
-
64
- def print_help_message
65
- puts "Accepted formats:"
66
- puts date_format_help_string
67
- puts
68
- system 'cal -3m'
69
- end
70
-
71
- def date_format_help_string
72
- FORMAT
73
- end
74
-
75
79
  end
@@ -1,21 +1,22 @@
1
- require 'achoo/ui/date_chooser'
2
- require 'achoo/ui/optionally_ranged_date_chooser'
3
- require 'achoo/ui/month_chooser'
1
+ require 'achoo/ui'
4
2
 
5
- class Achoo; class UI; end; end
3
+ module Achoo
4
+ module UI
6
5
 
7
- module Achoo::UI::DateChoosers
6
+ module DateChoosers
8
7
 
9
- def date_chooser
10
- Achoo::UI::DateChooser.new.choose
11
- end
8
+ def date_chooser
9
+ DateChooser.new.choose
10
+ end
12
11
 
13
- def optionally_ranged_date_chooser
14
- Achoo::UI::OptionallyRangedDateChooser.new.choose
15
- end
12
+ def optionally_ranged_date_chooser
13
+ OptionallyRangedDateChooser.new.choose
14
+ end
16
15
 
17
- def month_chooser
18
- Achoo::UI::MonthChooser.new.choose
19
- end
16
+ def month_chooser
17
+ MonthChooser.new.choose
18
+ end
20
19
 
20
+ end
21
+ end
21
22
  end
@@ -1,20 +1,22 @@
1
1
  require 'achoo/term'
2
+ require 'achoo/ui'
2
3
 
3
- class Achoo; class UI; end; end;
4
+ module Achoo
5
+ module UI
6
+ module ExceptionHandling
4
7
 
5
- module Achoo::UI::ExceptionHandling
8
+ def handle_exception(user_message, e)
9
+ Term::warn(user_message) + get_exception_reason(e)
10
+ end
6
11
 
7
- def handle_exception(user_message, e)
8
- Achoo::Term::warn(user_message) + get_exception_reason(e)
9
- end
12
+ def handle_fatal_exception(user_message, e)
13
+ abort Term::fatal(user_message) + get_exception_reason(e)
14
+ end
10
15
 
11
- def handle_fatal_exception(user_message, e)
12
- puts Achoo::Term::fatal(user_message) + get_exception_reason(e)
13
- exit 1
14
- end
16
+ def get_exception_reason(e)
17
+ "\nReason: \n\t" + e.message.gsub("\n", "\n\t") + "\n---\n\t" + e.backtrace.join("\n\t")
18
+ end
15
19
 
16
- def get_exception_reason(e)
17
- "\nReason: \n\t" + e.message.gsub("\n", "\n\t") + "\n---\n\t" + e.backtrace.join("\n\t")
20
+ end
18
21
  end
19
-
20
22
  end
@@ -1,27 +1,40 @@
1
1
  require 'achoo/term'
2
-
3
- class Achoo; class UI; end; end
4
-
5
- class Achoo::UI::MonthChooser
6
-
7
- def choose
8
- default = one_month_ago
9
- period = Achoo::Term::ask "Period ([#{default}] | YYYYMM)"
10
- period = default if !period || period.empty?
11
- # FIX validate YYYYMM
12
- period
13
- end
14
-
15
- def one_month_ago
16
- now = Time.now
17
- year = now.year
18
-
19
- # Use -2 + 1 to shift range from 0-11 to 1-12
20
- month = (now.month - 2)%12 + 1
21
- year -= 1 if month > now.month
22
-
23
- sprintf "%d%02d", year, month
2
+ require 'achoo/ui'
3
+
4
+ module Achoo
5
+ module UI
6
+ class MonthChooser
7
+
8
+ def choose
9
+ loop do
10
+ answer = Term::ask "Period ([#{one_month_ago}] | YYYYMM)"
11
+ begin
12
+ return handle_answer(answer)
13
+ rescue ArgumentError => e
14
+ puts e
15
+ end
16
+ end
17
+ end
18
+
19
+ def handle_answer(answer)
20
+ period = !answer || answer.empty? ? one_month_ago : answer
21
+ period =~ /\A \d{4} (?: 0\d | 1[0-2]) \z/x \
22
+ or raise ArgumentError.new('Invalid month')
23
+ period
24
+ end
25
+
26
+ def one_month_ago
27
+ now = Time.now
28
+ year = now.year
29
+
30
+ # Use -2 + 1 to shift range from 0-11 to 1-12
31
+ month = (now.month - 2)%12 + 1
32
+ year -= 1 if month > now.month
33
+
34
+ sprintf "%d%02d", year, month
35
+ end
36
+
37
+ end
24
38
  end
25
-
26
- end
39
+ end
27
40
 
@@ -1,33 +1,37 @@
1
1
  require 'achoo/ui/date_chooser'
2
2
 
3
- class Achoo::UI::OptionallyRangedDateChooser < Achoo::UI::DateChooser
3
+ module Achoo
4
+ module UI
5
+ class OptionallyRangedDateChooser < DateChooser
4
6
 
5
- def parse_date_range(date_range_str)
6
- start_date_str, finish_date_str = *date_range_str.split('->')
7
- start_date = parse_date(start_date_str.strip)
8
- finish_date = parse_date(finish_date_str.strip, start_date)
9
-
10
- if start_date >= finish_date
11
- raise ArgumentError.new('Invalid date range')
12
- end
13
-
14
- [start_date, finish_date]
15
- end
7
+ def parse_date_range(date_range_str)
8
+ start_date_str, finish_date_str = *date_range_str.split('->')
9
+ start_date = parse_date(start_date_str.strip)
10
+ finish_date = parse_date(finish_date_str.strip, start_date)
11
+
12
+ if start_date >= finish_date
13
+ raise ArgumentError.new('Invalid date range')
14
+ end
15
+
16
+ [start_date, finish_date]
17
+ end
16
18
 
17
- private
19
+ private
20
+
21
+ def handle_answer(answer)
22
+ if answer.include? '->'
23
+ return parse_date_range(answer)
24
+ else
25
+ return super
26
+ end
27
+ end
28
+
29
+ def date_format_help_string
30
+ return " DATE [-> DATE]\n" \
31
+ << " DATE:\n" \
32
+ << FORMAT
33
+ end
18
34
 
19
- def handle_answer(answer)
20
- if answer.include? '->'
21
- return parse_date_range(answer)
22
- else
23
- return super
24
35
  end
25
36
  end
26
-
27
- def date_format_help_string
28
- return " DATE [-> DATE]\n" \
29
- << " DATE:\n" \
30
- << FORMAT
31
- end
32
-
33
37
  end