shellout 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'shellout/query'
3
+ require 'shellout/date'
4
+
5
+ module Shellout
6
+ class DateQuery < Query
7
+
8
+ def initialize
9
+ super("Date (?)", "today")
10
+ end
11
+
12
+ def call
13
+ loop do
14
+ date = super
15
+ return date if date
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def ask
22
+ answer = super
23
+ if answer == '?'
24
+ print_help
25
+ return
26
+ end
27
+ parse(answer)
28
+ end
29
+
30
+ def parse(answer)
31
+ Shellout::Date.from_str(answer)
32
+ rescue => e
33
+ puts e.message
34
+ end
35
+
36
+ def print_help
37
+ puts <<'EOT'
38
+ Accepted input formats:
39
+ today - today
40
+ [+|-]N - ±N days from today
41
+ D?D - FIXME
42
+ M?M-D?D - FIXME
43
+ (YY)?YY-M?M-D?D - FIXME
44
+
45
+ EOT
46
+ Shellout::Calendar.new.print3
47
+ end
48
+
49
+ end
50
+ end
@@ -1,8 +1,9 @@
1
1
  module Shellout
2
2
  class Menu
3
3
 
4
- def initialize(items)
5
- @items = items
4
+ def initialize(items, zero_item=nil)
5
+ @items = items
6
+ @zero_item = zero_item
6
7
  end
7
8
 
8
9
  def padding; 1; end
@@ -12,6 +13,7 @@ module Shellout
12
13
  @items.each_with_index do |item, i|
13
14
  out.printf format, i+1, item
14
15
  end
16
+ out.printf format, 0, @zero_item unless @zero_item.nil?
15
17
  end
16
18
 
17
19
  private
@@ -0,0 +1,51 @@
1
+ require 'shellout/query'
2
+ require 'shellout'
3
+
4
+ module Shellout
5
+ class MenuQuery
6
+
7
+ include Shellout
8
+
9
+ def initialize(items, last_is_the_zero_item=false)
10
+ @items = items.is_a?(Array) ? Hash[*(items.zip(items).flatten)] : items
11
+ @has_a_zero_item = last_is_the_zero_item
12
+ initialize_menu
13
+ @prompt_class = Query
14
+ end
15
+
16
+ def call
17
+ loop do
18
+ @menu.print
19
+ answer = ask
20
+ return answer if answer
21
+ puts "Invalid user input!"
22
+ end
23
+ end
24
+
25
+ def prompt_class=(klass)
26
+ @prompt_class = klass
27
+ end
28
+
29
+ def ask
30
+ return @items.values[0] if only_one_option?
31
+ answer = @prompt_class.new('', 1).call.to_i
32
+ return nil if answer < 0
33
+ return nil if answer == 0 and !@has_a_zero_item
34
+ index = (@has_a_zero_item and answer == "0") ? -1 : answer.to_i-1
35
+ @items.values[index]
36
+ end
37
+
38
+ private
39
+
40
+ def initialize_menu
41
+ menu_items = @items.keys
42
+ zero_item = @has_a_zero_item ? menu_items.pop : nil
43
+ @menu = Menu(menu_items, zero_item)
44
+ end
45
+
46
+ def only_one_option?
47
+ @items.length == 1 && !@has_a_zero_item
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ module Shellout
2
+ class Paragraph
3
+
4
+ def initialize(str)
5
+ @str = str
6
+ @padding = 0
7
+ @width = 80
8
+ end
9
+
10
+ def width(width)
11
+ @width = width
12
+ self
13
+ end
14
+
15
+ def padding(width)
16
+ @padding = width
17
+ self
18
+ end
19
+
20
+ def print(out=$stdout)
21
+ text_width = @width - @padding
22
+ text = ' '*@padding + @str
23
+ # Stolen from ActionView::Helpers::TextHelper#word_wrap
24
+ p = text.split("\n").collect do |line|
25
+ line.length > text_width ? line.gsub(/(.{1,#{text_width}})(\s+|$)/, "\\1\n" + ' '*@padding).rstrip : line
26
+ end * "\n"
27
+ out.puts p
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'readline'
2
+
3
+ module Shellout
4
+ class Query
5
+
6
+ def initialize(question='', default=nil)
7
+ @question = question + (default.nil? ? '' : " [#{default}]")
8
+ @default = default
9
+ @io = Readline
10
+ end
11
+
12
+ def io=(io)
13
+ @io = io
14
+ end
15
+
16
+ def call
17
+ answer = ask
18
+ return answer == '' ? @default : answer
19
+ end
20
+
21
+ private
22
+
23
+ def bold(text); "\e[1m#{text}\e[0m"; end
24
+
25
+ def ask
26
+ answer = @io.readline(bold("#{@question}> "), true)
27
+ answer.strip
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Shellout
2
+ class Task
3
+
4
+ # For executing sub tasks in correct order, we depend on the fact that
5
+ # hash iteration is in insert order
6
+
7
+ def initialize
8
+ @sub_tasks = {}
9
+ @on_call_done = ->{}
10
+ yield self if block_given?
11
+ end
12
+
13
+ def method_missing(name, *args)
14
+ super unless name =~ /=$/
15
+ add_sub_task(name.to_s.chop, args.first)
16
+ end
17
+
18
+ def add_sub_task(name, sub)
19
+ @sub_tasks[name.to_sym] = sub
20
+ end
21
+
22
+ def printf(format)
23
+ @sub_tasks['printf'] = -> do
24
+ super(format, @results)
25
+ end
26
+ end
27
+
28
+ def on_call_done(&callback)
29
+ @on_call_done = callback
30
+ end
31
+
32
+ def call
33
+ @results = {}
34
+ @sub_tasks.each do |k, sub|
35
+ @results[k] = sub.call
36
+ end
37
+ @on_call_done.call
38
+ end
39
+
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Shellout
2
- VERSION = '0.4'
2
+ VERSION = '0.5'
3
3
  end
@@ -16,9 +16,12 @@ Gem::Specification.new do |s|
16
16
  s.test_files = `git ls-files -- spec/*`.split("\n")
17
17
  s.require_paths = ["lib"]
18
18
 
19
- s.add_development_dependency "rspec"
20
- s.add_development_dependency "guard"
21
- s.add_development_dependency "guard-rspec"
19
+ s.add_development_dependency "rspec", '2.14.1'
20
+ s.add_development_dependency "guard", '1.8.2'
21
+ s.add_development_dependency "guard-rspec", '3.0.2'
22
+ s.add_development_dependency "rake", '10.1.0'
23
+ s.add_development_dependency "cucumber", '1.3.10'
24
+ s.add_development_dependency "aruba", '0.5.3'
22
25
 
23
26
  if RUBY_PLATFORM.downcase.include?("darwin")
24
27
  s.add_development_dependency 'rb-fsevent'
@@ -45,6 +45,35 @@ Mo Tu We Th Fr Sa Su
45
45
  17 18 19 20 21 22 23
46
46
  24 25 26 27 28 29 \e[7m30\e[0m
47
47
  31
48
+ EOC
49
+ end
50
+
51
+ it 'should highlight todays date if calendar is todays month' do
52
+ Calendar().print(@out)
53
+ res = @out.string.gsub(/\s+\n/, "\n")
54
+ res.should == <<EOC
55
+ October 2011
56
+ Mo Tu We Th Fr Sa Su
57
+ 1 2
58
+ 3 4 5 6 7 8 9
59
+ 10 11 12 13 14 15 16
60
+ 17 18 19 20 21 22 23
61
+ 24 25 26 27 28 29 \e[7m30\e[0m
62
+ 31
63
+ EOC
64
+ end
65
+
66
+ it 'should not highlight todays date if calendar is todays month, but not the same year' do
67
+ Calendar(Date.new(2012, 10, 30)).print(@out)
68
+ res = @out.string.gsub(/\s+\n/, "\n")
69
+ res.should == <<EOC
70
+ October 2012
71
+ Mo Tu We Th Fr Sa Su
72
+ 1 2 3 4 5 6 7
73
+ 8 9 10 11 12 13 14
74
+ 15 16 17 18 19 20 21
75
+ 22 23 24 25 26 27 28
76
+ 29 30 31
48
77
  EOC
49
78
  end
50
79
 
@@ -79,4 +108,4 @@ Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
79
108
  EOC
80
109
  end
81
110
  end
82
- end
111
+ end
@@ -0,0 +1,9 @@
1
+ require 'shellout/command_loop'
2
+
3
+ module Shellout
4
+ describe CommandLoop do
5
+
6
+ # It compiles!
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'shellout/date_query'
2
+
3
+ module Shellout
4
+ describe DateQuery do
5
+
6
+ # It compiles!
7
+
8
+ end
9
+ end
@@ -0,0 +1,87 @@
1
+ require 'shellout/date'
2
+
3
+ module Shellout
4
+ describe Date do
5
+
6
+ describe "#from_str" do
7
+
8
+ before(:each) do
9
+ @today = Date.today
10
+ end
11
+
12
+
13
+ context "when English date string is given" do
14
+ it "should parse 'today'" do
15
+ Date.from_str("today").should == @today
16
+ end
17
+
18
+ it "should parse '' as 'today'" do
19
+ Date.from_str("").should == @today
20
+ end
21
+ end
22
+
23
+
24
+ context "when an offset is given" do
25
+ it "should parse '+1' as tomorrow" do
26
+ Date.from_str("+1").should == @today+1
27
+ end
28
+
29
+ it "should parse '-1' as yesterday" do
30
+ Date.from_str("-1").should == @today-1
31
+ end
32
+ end
33
+
34
+
35
+ context "when only the day of month is given" do
36
+ it "should parse '1'" do
37
+ Date.from_str("1").should == Date.civil(@today.year, @today.month, 1)
38
+ end
39
+
40
+ it "should parse '20'" do
41
+ Date.from_str("20").should == Date.civil(@today.year, @today.month, 20)
42
+ end
43
+ end
44
+
45
+
46
+ context "when the month and day of month are given" do
47
+ it "should parse '11-1'" do
48
+ Date.from_str("11-1").should == Date.civil(@today.year, 11, 1)
49
+ end
50
+
51
+ it "should parse '11-01'" do
52
+ Date.from_str("11-01").should == Date.civil(@today.year, 11, 1)
53
+ end
54
+ end
55
+
56
+ context "when year, month, and day of month are given" do
57
+
58
+ # Two digits in year
59
+ it "should parse '11-11-11' as 2011-11-11" do
60
+ Date.from_str("11-11-11").should == Date.civil(2011, 11, 11)
61
+ end
62
+
63
+ it "should parse '91-11-11' as 1991-11-11" do
64
+ Date.from_str("91-11-11").should == Date.civil(1991, 11, 11)
65
+ end
66
+
67
+ # > Two digits in year
68
+ it "should parse '111-11-1' as 111-11-1" do
69
+ Date.from_str("111-11-1").should == Date.civil(111, 11, 1)
70
+ end
71
+
72
+ it "should parse '2008-08-26' as 2008-08-26" do
73
+ Date.from_str("2008-08-26").should == Date.civil(2008, 8, 26)
74
+ end
75
+ end
76
+
77
+ it "should fail on nil" do
78
+ expect { Date.from_str(nil) }.to raise_error(ArgumentError)
79
+ end
80
+
81
+ it "should fail on strings containing junk" do
82
+ expect { Date.from_str("foobar") }.to raise_error(ArgumentError)
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,39 @@
1
+ require 'shellout/menu_query'
2
+
3
+ module Shellout
4
+ describe MenuQuery do
5
+
6
+ describe "#ask" do
7
+ before :each do
8
+ @query = MenuQuery.new(%w(a b c))
9
+ end
10
+
11
+ def make_prompt_return(value)
12
+ prompt = double('prompt')
13
+ prompt.stub_chain(:new, :call).and_return(value)
14
+ @query.prompt_class = prompt
15
+ end
16
+
17
+ it "should return first element when prompt query returns '1'" do
18
+ make_prompt_return('1')
19
+ @query.ask.should == 'a'
20
+ end
21
+
22
+ it "should return second element when prompt query returns '2'" do
23
+ make_prompt_return('2')
24
+ @query.ask.should == 'b'
25
+ end
26
+
27
+ it "should return nil if user answer is invalid (too large)" do
28
+ make_prompt_return('9')
29
+ @query.ask.should == nil
30
+ end
31
+
32
+ it "should return nil if user answer is invalid (0)" do
33
+ make_prompt_return('0')
34
+ @query.ask.should == nil
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -1,31 +1,32 @@
1
1
  require 'stringio'
2
2
  require 'shellout'
3
3
 
4
- describe Shellout::Menu do
4
+ module Shellout
5
+ describe Menu do
5
6
 
6
- include Shellout
7
+ include Shellout
7
8
 
8
- before(:each) do
9
- @out = StringIO.new
10
- end
9
+ before(:each) do
10
+ @out = StringIO.new
11
+ end
11
12
 
12
- it "should work for a basic example" do
13
- Menu(%w(a b c)).print(@out)
14
- @out.string.should == <<EOT
13
+ it "should work for a basic example" do
14
+ Menu(%w(a b c)).print(@out)
15
+ @out.string.should == <<EOT
15
16
  1. a
16
17
  2. b
17
18
  3. c
18
19
  EOT
19
- end
20
+ end
20
21
 
21
- it "should print nothing when no items are given" do
22
- Menu([]).print(@out)
23
- @out.string.should == ''
24
- end
22
+ it "should print nothing when no items are given" do
23
+ Menu([]).print(@out)
24
+ @out.string.should == ''
25
+ end
25
26
 
26
- it "should right justify the menu item number" do
27
- Menu(('a'..'j').to_a).print(@out)
28
- @out.string.should == <<EOT
27
+ it "should right justify the menu item number" do
28
+ Menu(('a'..'j').to_a).print(@out)
29
+ @out.string.should == <<EOT
29
30
  1. a
30
31
  2. b
31
32
  3. c
@@ -37,7 +38,17 @@ EOT
37
38
  9. i
38
39
  10. j
39
40
  EOT
40
- end
41
+ end
41
42
 
42
-
43
+ it "should put the zero item last, prefixed by a '0.'" do
44
+ Menu(%w(a b c), 'd').print(@out)
45
+ @out.string.should == <<EOT
46
+ 1. a
47
+ 2. b
48
+ 3. c
49
+ 0. d
50
+ EOT
51
+ end
52
+
53
+ end
43
54
  end