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 @@
1
+ 1.9.3
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 1.9.3
data/CHANGES CHANGED
@@ -1,3 +1,8 @@
1
+ 2013-12-02: version 0.5
2
+
3
+ - Fixed a bug in the calendar causing it to highlight a date in the
4
+ future that has the same month and day in month as today.
5
+
1
6
  2011-12-03: version 0.4
2
7
 
3
8
  - Added a class for printing menus
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec
1
+ source 'https://rubygems.org'
4
2
 
3
+ gemspec
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://secure.travis-ci.org/kjellm/shellout.png)](http://travis-ci.org/kjellm/shellout)
2
+
1
3
  Shellout
2
4
  ========
3
5
 
@@ -19,62 +21,63 @@ Usage
19
21
 
20
22
  ### Shadowboxes
21
23
 
22
- Shadowbox("Hello world").print
24
+ > Shadowbox("Hello world").print
23
25
 
24
- # ┌──────────────────────────────────────────┐
25
- # │ Hello world │▒
26
- # └──────────────────────────────────────────┘▒
27
- # ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
26
+ ┌──────────────────────────────────────────┐
27
+ │ Hello world │▒
28
+ └──────────────────────────────────────────┘▒
29
+ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
28
30
 
29
31
  ### Tables
30
32
 
31
- Table(headers: %w{Team Points},
32
- rows: [['Man City', 22],
33
- ['Man Utd', 20],
34
- ['Chelsea', 19],
35
- ['Newcastle', 16]]).print
33
+ > Table(headers: %w{Team Points},
34
+ rows: [['Man City', 22],
35
+ ['Man Utd', 20],
36
+ ['Chelsea', 19],
37
+ ['Newcastle', 16]]).print
36
38
 
37
- # ┌───────────┬────────┐
38
- # │ Team │ Points │
39
- # ├───────────┼────────┤
40
- # │ Man City │ 22 │
41
- # │ Man Utd │ 20 │
42
- # │ Chelsea │ 19 │
43
- # │ Newcastle │ 16 │
44
- # └───────────┴────────┘
39
+ ┌───────────┬────────┐
40
+ │ Team │ Points │
41
+ ├───────────┼────────┤
42
+ │ Man City │ 22 │
43
+ │ Man Utd │ 20 │
44
+ │ Chelsea │ 19 │
45
+ │ Newcastle │ 16 │
46
+ └───────────┴────────┘
45
47
 
46
48
 
47
49
  ### Calendars
48
50
 
49
- today = Date.today # => "2011-10-31"
51
+ > today = Date.today
52
+ => #<Date: 2011-10-31 (...)>
50
53
 
51
- Calendar(today).print
54
+ > Calendar(today).print
52
55
 
53
- # October 2011
54
- # Mo Tu We Th Fr Sa Su
55
- # 1 2
56
- # 3 4 5 6 7 8 9
57
- # 10 11 12 13 14 15 16
58
- # 17 18 19 20 21 22 23
59
- # 24 25 26 27 28 29 30
60
- # 31
56
+ October 2011
57
+ Mo Tu We Th Fr Sa Su
58
+ 1 2
59
+ 3 4 5 6 7 8 9
60
+ 10 11 12 13 14 15 16
61
+ 17 18 19 20 21 22 23
62
+ 24 25 26 27 28 29 30
63
+ 31
61
64
 
62
- Calendar(today).print3
65
+ > Calendar(today).print3
63
66
 
64
- # 2011
65
- # September October November
66
- # Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
67
- # 1 2 3 4 1 2 1 2 3 4 5 6
68
- # 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
69
- # 12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
70
- # 19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
71
- # 26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
72
- # 31
67
+ 2011
68
+ September October November
69
+ Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
70
+ 1 2 3 4 1 2 1 2 3 4 5 6
71
+ 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
72
+ 12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
73
+ 19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
74
+ 26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
75
+ 31
73
76
 
74
77
 
75
78
  ### Menus
76
79
 
77
- Menu([
80
+ > Menu([
78
81
  "Do this",
79
82
  "No, this",
80
83
  "Or, maybe this",
@@ -89,18 +92,18 @@ Usage
89
92
  "Might as well choose this one",
90
93
  ]).print
91
94
 
92
- # 1. Do this
93
- # 2. No, this
94
- # 3. Or, maybe this
95
- # 4. Forget it, this is the right choice
96
- # 5. Amazing things will happen if you choose this
97
- # 6. Ignore #5. Pick me!
98
- # 7. I'm the obvious choice
99
- # 8. There is no end to the awesomeness that will come from choosing this
100
- # 9. Don't choose this
101
- # 10. Or this
102
- # 11. Things are getting worse
103
- # 12. Might as well choose this one
95
+ 1. Do this
96
+ 2. No, this
97
+ 3. Or, maybe this
98
+ 4. Forget it, this is the right choice
99
+ 5. Amazing things will happen if you choose this
100
+ 6. Ignore #5. Pick me!
101
+ 7. I'm the obvious choice
102
+ 8. There is no end to the awesomeness that will come from choosing this
103
+ 9. Don't choose this
104
+ 10. Or this
105
+ 11. Things are getting worse
106
+ 12. Might as well choose this one
104
107
 
105
108
  Bugs
106
109
  ----
@@ -111,7 +114,7 @@ Report bugs to <http://github.com/kjellm/shellout/issues>
111
114
  Author
112
115
  ------
113
116
 
114
- Kjell-Magne Øierud &lt;kjellm AT acm DOT org&gt;
117
+ Kjell-Magne Øierud &lt;kjellm AT oierud DOT net&gt;
115
118
 
116
119
 
117
120
  License
@@ -119,7 +122,7 @@ License
119
122
 
120
123
  (The MIT License)
121
124
 
122
- Copyright © 2011 Kjell-Magne Øierud
125
+ Copyright © 2011-2013 Kjell-Magne Øierud
123
126
 
124
127
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
125
128
  associated documentation files (the ‘Software’), to deal in the Software without restriction, including
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
- require "bundler/gem_tasks"
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'shellout'
4
+ require 'shellout/command_loop'
5
+ require 'shellout/date_query'
6
+ require 'shellout/menu_query'
7
+ require 'shellout/task'
8
+ require 'shellout/query'
9
+
10
+ class App
11
+
12
+ include Shellout
13
+
14
+ def initialize
15
+ @session = []
16
+ end
17
+
18
+ def define_course_task(dishes)
19
+ Task.new do |t|
20
+ t.dish = MenuQuery.new(dishes)
21
+ t.quantity = Query.new('How many?', 1)
22
+ t.printf("%{quantity} %{dish} added to your order\n")
23
+ t.on_call_done do
24
+ @session << t
25
+ end
26
+ end
27
+ end
28
+
29
+ def main
30
+
31
+ starters_task = define_course_task(%w(Gazpacho Bruschetta))
32
+ main_course_task = define_course_task(%w(Pizza Pasta))
33
+ desserts_task = define_course_task(%w(Gelato Tiramisu))
34
+
35
+ checkout_task = Task.new do |t|
36
+ t.date = DateQuery.new
37
+ t.name = Query.new("Your name")
38
+ t.on_call_done do
39
+ confirmed = Query.new("Confirm (y|n)").call
40
+ @session = [] if confirmed == 'y'
41
+ end
42
+ end
43
+
44
+ view_order_task = ->do
45
+ #FIXME ugly
46
+ rows = @session.map do |t|
47
+ [t.instance_variable_get(:@results)[:quantity], t.instance_variable_get(:@results)[:dish]]
48
+ end
49
+ Table(headers: %w(quantity dish), rows: rows).print
50
+ end
51
+
52
+ main_menu_items = {
53
+ "Starters" => starters_task,
54
+ "Main courses" => main_course_task,
55
+ "Desserts" => desserts_task,
56
+ "View Order" => view_order_task,
57
+ "Checkout" => checkout_task,
58
+ "Exit" => ->{ exit }
59
+ }
60
+ main_menu = MenuQuery.new(main_menu_items, true)
61
+
62
+ Shadowbox("Give up to your hunger!").print
63
+ CommandLoop.new(main_menu).call
64
+ end
65
+ end
66
+
67
+ App.new.main
@@ -0,0 +1,12 @@
1
+ Feature: Order a Pizza
2
+ As a pathetic person who is unable to make my own supper
3
+ I want to order a pizza for tomorrows supper
4
+ In order to not starve to death
5
+
6
+ Scenario: Order a Pizza
7
+ Given that hunger is running
8
+ When I choose main course from the main menu
9
+ And I choose Pizza from the main course menu
10
+ And I choose the default quantity
11
+ And I quit
12
+ Then I should see "1 Pizza added to your order"
@@ -0,0 +1,11 @@
1
+ Feature: Start the app
2
+ As a user of the system
3
+ I want to be able to start the system
4
+ In order to be able to use the system
5
+
6
+ Scenario: Start the app
7
+ Given that hunger is not running
8
+ When I start hunger
9
+ And I quit
10
+ Then I shall see a greeting
11
+ And I shall see the main menu
@@ -0,0 +1,71 @@
1
+ Given /^that hunger is not running$/ do
2
+ end
3
+
4
+ When /^I start hunger$/ do
5
+ steps %{When I run `hunger.rb` interactively}
6
+ end
7
+
8
+ When /^I quit$/ do
9
+ steps %{When I type "6"}
10
+ end
11
+
12
+ Then /^I shall see a greeting$/ do
13
+ steps %{Then the stdout should contain "Give up to your hunger!"}
14
+ end
15
+
16
+ Then /^I shall see the main menu$/ do
17
+ steps %{Then the stdout should contain:
18
+ """
19
+ 1. Starters
20
+ 2. Main courses
21
+ 3. Desserts
22
+ 4. View Order
23
+ 5. Checkout
24
+ 0. Exit
25
+ """
26
+ }
27
+ end
28
+
29
+ Given /^that hunger is running$/ do
30
+ steps %{When I start hunger}
31
+ end
32
+
33
+ When /^I choose main course from the main menu$/ do
34
+ steps %{When I type "2"}
35
+ end
36
+
37
+ When /^I choose Pizza from the main course menu$/ do
38
+ steps %{When I type "1"}
39
+ end
40
+
41
+ When /^I choose the default quantity$/ do
42
+ steps %{When I type ""}
43
+ end
44
+
45
+ Then /^I should see "([^"]*)"$/ do |arg1|
46
+ steps %{Then the stdout should contain "#{arg1}"}
47
+ end
48
+
49
+ Given /^I order (\d+) Pizza$/ do |quantity|
50
+ steps %{
51
+ When I type "2"
52
+ When I type "1"
53
+ When I type "#{quantity}"
54
+ }
55
+ end
56
+
57
+ Given /^I order (\d+) Gelato$/ do |quantity|
58
+ steps %{
59
+ When I type "3"
60
+ When I type "1"
61
+ When I type "#{quantity}"
62
+ }
63
+ end
64
+
65
+ Given /^I choose to view ordered dishes$/ do
66
+ steps %{When I type "4"}
67
+ end
68
+
69
+ Then /^I should see:$/ do |string|
70
+ steps %{Then the stdout should contain "#{string}"}
71
+ end
@@ -0,0 +1 @@
1
+ require 'aruba/cucumber'
@@ -0,0 +1,14 @@
1
+ Feature: View ordered dishes
2
+ As a user
3
+ I want to be able to see what I have ordered
4
+ So that I can verify that the system has gotten it right
5
+
6
+ Scenario: view ordered dishes
7
+ Given that hunger is running
8
+ And I order 1 Pizza
9
+ And I order 2 Gelato
10
+ And I choose to view ordered dishes
11
+ And I quit
12
+ Then I should see "┌──────────┬────────┐\n│ quantity │ dish │\n├──────────┼────────┤\n│ 1 │ Pizza │\n│ 2 │ Gelato │\n└──────────┴────────┘"
13
+ #FIXME Could not get multiline pystrings to work (lexing error)
14
+
@@ -63,7 +63,7 @@ module Shellout
63
63
  # FIXME: UGLY!!!
64
64
  foo = dates.map do |for_date|
65
65
  bar = days(for_date)
66
- if is_current_month?(for_date)
66
+ if is_current_month?(for_date) && is_current_year?(for_date)
67
67
  bar.map! {|d| d == Date.today.day ? ansi_reverse_color(d) : d}
68
68
  end
69
69
  bar
@@ -91,6 +91,10 @@ module Shellout
91
91
  Date.today.month == date.month
92
92
  end
93
93
 
94
+ def is_current_year?(date)
95
+ Date.today.year == date.year
96
+ end
97
+
94
98
  def days(for_date)
95
99
  days = (1..last_day_of_month(for_date).day).to_a
96
100
  unshift_empty_strings_for_missing_week(days, for_date)
@@ -117,4 +121,4 @@ module Shellout
117
121
 
118
122
 
119
123
  end
120
- end
124
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Shellout
3
+ class CommandLoop
4
+
5
+ def initialize(menu)
6
+ @menu = menu
7
+ end
8
+
9
+ def call
10
+ loop do
11
+ begin
12
+ task = @menu.call
13
+ task.call
14
+ rescue Interrupt # ^C
15
+ puts # Add a new line in case we are prompting
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,55 @@
1
+ require 'date'
2
+
3
+ module Shellout
4
+ class Date < ::Date
5
+
6
+ def self.from_str(date_str, base=Date.today)
7
+ raise ArgumentError.new("Can't convert nil to a Date") \
8
+ if date_str.nil?
9
+
10
+ args = [date_str, base]
11
+ return parse_str_from_english(*args) \
12
+ || parse_str_from_offset(*args) \
13
+ || parse_str_from_ymd(*args) \
14
+ || (raise ArgumentError.new(
15
+ "Failed to convert String(#{date_str}) to a Date"))
16
+ end
17
+
18
+ private
19
+
20
+ def self.parse_str_from_english(date_str, base)
21
+ return base if date_str == 'today' || date_str.empty?
22
+ return nil
23
+ end
24
+
25
+ def self.parse_str_from_offset(date_str, base)
26
+ return case date_str.chars.first
27
+ when '-'
28
+ base - Integer(date_str[1..-1])
29
+ when '+'
30
+ base + Integer(date_str[1..-1])
31
+ else
32
+ nil
33
+ end
34
+ end
35
+
36
+ def self.parse_str_from_ymd(date_str, base)
37
+ date = date_str.split('-').collect {|d| d.to_i}
38
+ case date.length
39
+ when 1
40
+ return Date.civil(base.year, base.month, *date)
41
+ when 2
42
+ return Date.civil(base.year, *date)
43
+ when 3
44
+ if date[0] < 70
45
+ date[0] += 2000
46
+ elsif date[0] < 100
47
+ date[0] += 1900
48
+ end
49
+ return Date.civil(*date)
50
+ end
51
+ return nil
52
+ end
53
+
54
+ end
55
+ end