shellout 0.4 → 0.5

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.
@@ -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