james 0.0.3-universal-darwin-10 → 0.0.4-universal-darwin-10

Sign up to get free protection for your applications and to get access to all the features.
data/aux/james/cli.rb CHANGED
@@ -4,18 +4,26 @@ module James
4
4
 
5
5
  class CLI
6
6
 
7
- def execute *dialogues
8
- all_dialogues = Dir["**/*_dialog{,ue}.rb"]
9
- all_dialogues.select! { |dialogue| dialogues.any? { |given| dialogue =~ %r{#{given}_dialog(ue)?.rb$} } } unless dialogues.empty?
7
+ def execute *given_dialogues
8
+ dialogues = find_dialogues
9
+ dialogues.select! { |dialogue| given_dialogues.any? { |given| dialogue =~ %r{#{given}_dialog(ue)?.rb$} } } unless given_dialogues.empty?
10
10
 
11
- puts "James: Using #{all_dialogues.join(', ')} for our conversation, Sir."
11
+ puts "James: I haven't found anything to talk about (No *_dialog{ue,}.rb files found). Exiting." or exit!(1) if dialogues.empty?
12
12
 
13
- all_dialogues.each do |dialogue|
14
- require File.expand_path dialogue, Dir.pwd
15
- end
13
+ puts "James: Using #{dialogues.join(', ')} for our conversation, Sir."
14
+
15
+ require_all dialogues
16
16
 
17
17
  James.listen
18
18
  end
19
+ def find_dialogues
20
+ Dir["**/*_dialog{,ue}.rb"]
21
+ end
22
+ def require_all dialogues
23
+ dialogues.each do |dialogue|
24
+ require File.expand_path dialogue, Dir.pwd
25
+ end
26
+ end
19
27
 
20
28
  end
21
29
 
data/lib/james.rb CHANGED
@@ -2,6 +2,7 @@ module James; end
2
2
 
3
3
  require File.expand_path '../james/timer', __FILE__
4
4
  require File.expand_path '../james/visitor', __FILE__
5
+ require File.expand_path '../james/visitors', __FILE__
5
6
  require File.expand_path '../james/dialogues', __FILE__
6
7
 
7
8
  require File.expand_path '../james/dialogue_api', __FILE__
@@ -0,0 +1,27 @@
1
+ class CoreDialogue
2
+
3
+ include James::Dialogue
4
+
5
+ state :awake do
6
+ chainable # If James is awake, he offers more dialogues on this state, if there are any.
7
+
8
+ hear 'Leave me alone, James.' => :away,
9
+ "That's it for today, James." => :exit,
10
+ "Something else, James." => :awake
11
+ into { "Sir?" }
12
+ end
13
+
14
+ state :away do
15
+ hear 'James?' => :awake,
16
+ "That's it for today, James." => :exit
17
+ into { "Of course, Sir!" }
18
+ end
19
+
20
+ state :exit do
21
+ into do
22
+ puts "James: Exits through a side door."
23
+ Kernel.exit
24
+ end
25
+ end
26
+
27
+ end
@@ -7,6 +7,8 @@ require File.expand_path '../inputs/terminal', __FILE__
7
7
  require File.expand_path '../outputs/audio', __FILE__
8
8
  require File.expand_path '../outputs/terminal', __FILE__
9
9
 
10
+ require File.expand_path '../builtin/core_dialogue', __FILE__
11
+
10
12
  module James
11
13
 
12
14
  class Controller
@@ -14,7 +16,9 @@ module James
14
16
  attr_reader :visitor
15
17
 
16
18
  def initialize
17
- @visitor = initialize_dialogues.visitor
19
+ user_visitor = initialize_dialogues.visitor
20
+ system_visitor = Visitor.new CoreDialogue.new.state_for(:awake)
21
+ @visitor = Visitors.new system_visitor, user_visitor
18
22
  end
19
23
 
20
24
  def applicationDidFinishLaunching notification
@@ -80,29 +84,31 @@ module James
80
84
  end
81
85
  end
82
86
  def expects
83
- @visitor.expects
87
+ possibilities = @visitor.expects
88
+ puts "Possibilities:\n #{possibilities.join("\n ")}"
89
+ possibilities
84
90
  end
85
91
 
86
92
  def listen
87
93
  app = NSApplication.sharedApplication
88
94
  app.delegate = self
89
95
 
90
- # window = NSWindow.alloc.initWithContentRect([200, 300, 300, 100],
96
+ # window = NSWindow.alloc.initWithContentRect([100, 300, 300, 100],
91
97
  # styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask,
92
98
  # backing:NSBackingStoreBuffered,
93
99
  # defer:false)
94
- # window.title = 'MacRuby: The Definitive Guide'
100
+ # window.title = 'James Debug/Info'
95
101
  # window.level = 3
96
102
  # window.delegate = app.delegate
103
+
104
+ # @button = NSButton.alloc.initWithFrame([10, 10, 400, 10])
105
+ # @button.bezelStyle = 4
106
+ # @button.title = ''
107
+ # @button.target = app.delegate
108
+ # @button.action = 'say_hello:'
97
109
  #
98
- # button = NSButton.alloc.initWithFrame([80, 10, 120, 80])
99
- # button.bezelStyle = 4
100
- # button.title = 'Hello World!'
101
- # button.target = app.delegate
102
- # button.action = 'say_hello:'
103
- #
104
- # window.contentView.addSubview(button)
105
- #
110
+ # window.contentView.addSubview(@button)
111
+
106
112
  # window.display
107
113
  # window.orderFrontRegardless
108
114
 
@@ -11,7 +11,7 @@ module James
11
11
 
12
12
  def self.included into
13
13
  into.extend ClassMethods
14
- Dialogues << into
14
+ Dialogues << into unless into == CoreDialogue # TODO Dirty as hell.
15
15
  end
16
16
 
17
17
  #
@@ -58,6 +58,15 @@ module James
58
58
  @exit_block = block
59
59
  end
60
60
 
61
+ # By default, a state is not chainable.
62
+ #
63
+ def chainable?
64
+ @chainable
65
+ end
66
+ def chainable
67
+ @chainable = true
68
+ end
69
+
61
70
  # Description of self using name and transitions.
62
71
  #
63
72
  def to_s
data/lib/james/visitor.rb CHANGED
@@ -21,13 +21,13 @@ module James
21
21
  @current = initial
22
22
 
23
23
  @initial = initial
24
- @timer = timer || Timer.new
24
+ # @timer = timer || Timer.new
25
25
  end
26
26
 
27
27
  # Escapes the current state back to the initial.
28
28
  #
29
- def escape
30
- timer.stop
29
+ def reset
30
+ # timer.stop
31
31
  self.current = initial
32
32
  end
33
33
 
@@ -53,7 +53,7 @@ module James
53
53
  end
54
54
  def hear phrase, &block
55
55
  return unless hears? phrase
56
- timer.restart
56
+ # timer.restart
57
57
  exit_text = exit &block
58
58
  transition phrase
59
59
  check &block
@@ -66,6 +66,15 @@ module James
66
66
  def expects
67
67
  current.phrases
68
68
  end
69
+ # Does the current state allow penetration into another dialogue?
70
+ #
71
+ def chainable?
72
+ current.chainable?
73
+ end
74
+
75
+ def to_s
76
+ "#{self.class.name}(#{initial}, current: #{current})"
77
+ end
69
78
 
70
79
  end
71
80
 
@@ -22,14 +22,39 @@ module James
22
22
  @visitors = visitors
23
23
  end
24
24
 
25
+ # Hear tries all visitors in order
26
+ # until one hears a phrase he knows.
27
+ #
28
+ # After that, all remaining visitors are reset.
29
+ #
25
30
  def hear phrase, &block
26
- visitors.each do |visitor|
31
+ enumerator = visitors.dup
32
+
33
+ while visitor = enumerator.shift
27
34
  visitor.hear phrase, &block and break
28
35
  end
36
+
37
+ while visitor = enumerator.shift
38
+ visitor.reset
39
+ end
29
40
  end
30
41
 
42
+ # Enter enters the first dialogue.
43
+ #
44
+ def enter
45
+ visitors.first.enter
46
+ end
47
+
48
+ # Simply returns the sum of what phrases all dialogues expect.
49
+ #
50
+ # Stops as soon as a visitor is not in a chainable state anymore.
51
+ #
31
52
  def expects
32
- visitors.inject([]) { |expects, visitor| expects + visitor.expects }
53
+ visitors.inject([]) do |expects, visitor|
54
+ total = expects + visitor.expects
55
+ break total unless visitor.chainable?
56
+ total
57
+ end
33
58
  end
34
59
 
35
60
  end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ #
3
+ require File.expand_path '../../../../aux/james/cli', __FILE__
4
+
5
+ describe James::CLI do
6
+
7
+ before(:each) do
8
+ Dir.stub! :[] => ['test_dialogue.rb', 'test_dialog.rb', 'test/test_dialogue.rb']
9
+ end
10
+
11
+ let(:cli) { James::CLI.new }
12
+
13
+ describe 'find_dialogues' do
14
+ it 'returns the right ones' do
15
+ cli.find_dialogues.should == ['test_dialogue.rb', 'test_dialog.rb', 'test/test_dialogue.rb']
16
+ end
17
+ end
18
+
19
+ end
@@ -8,6 +8,30 @@ describe James::Visitor do
8
8
  let(:timer) { stub :timer }
9
9
  let(:visitor) { described_class.new initial, timer }
10
10
 
11
+ describe 'reset' do
12
+ it 'works' do
13
+ expect { visitor.reset }.to_not raise_error
14
+ end
15
+ # it 'calls methods in order' do
16
+ # timer.should_receive(:stop).once.with
17
+ # visitor.should_receive(:current=).once.with initial
18
+ #
19
+ # visitor.reset
20
+ # end
21
+ it 'survives a functional test' do
22
+ next_state = stub :next_state
23
+ initial.stub! :next_for => next_state
24
+
25
+ visitor.current.should == initial
26
+ visitor.transition :some_phrase
27
+ visitor.current.should == next_state
28
+
29
+ visitor.reset
30
+
31
+ visitor.current.should == initial
32
+ end
33
+ end
34
+
11
35
  describe 'current' do
12
36
  it { visitor.current.should == initial }
13
37
  end
@@ -62,19 +86,10 @@ describe James::Visitor do
62
86
  end
63
87
  end
64
88
 
65
- describe 'escape' do
66
- it 'calls methods in order' do
67
- timer.should_receive(:stop).once.with
68
- visitor.should_receive(:current=).once.with initial
69
-
70
- visitor.escape
71
- end
72
- end
73
-
74
89
  describe 'hear' do
75
90
  it 'calls methods in order' do
76
91
  visitor.should_receive(:hears?).once.ordered.with(:some_phrase).and_return true
77
- timer.should_receive(:restart).once.ordered.with
92
+ # timer.should_receive(:restart).once.ordered.with
78
93
  visitor.should_receive(:exit).once.ordered.with
79
94
  visitor.should_receive(:transition).once.ordered.with :some_phrase
80
95
  # visitor.should_receive(:check).once.ordered.with
@@ -15,11 +15,14 @@ describe James::Visitors do
15
15
  second.stub! :hear => nil
16
16
  end
17
17
  it 'works' do
18
+ second.stub! :reset
19
+
18
20
  visitors.hear 'some phrase'
19
21
  end
20
22
  it 'calls the second never' do
21
23
  first.should_receive(:hear).once.and_return true
22
24
  second.should_receive(:hear).never
25
+ second.should_receive(:reset).once
23
26
 
24
27
  visitors.hear 'some phrase'
25
28
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 3
9
- version: 0.0.3
8
+ - 4
9
+ version: 0.0.4
10
10
  platform: universal-darwin-10
11
11
  authors:
12
12
  - Florian Hanke
@@ -42,7 +42,7 @@ executables:
42
42
  extensions: []
43
43
  extra_rdoc_files: []
44
44
  files:
45
- - lib/james/builtin/main_dialogue.rb
45
+ - lib/james/builtin/core_dialogue.rb
46
46
  - lib/james/controller.rb
47
47
  - lib/james/dialogue_api.rb
48
48
  - lib/james/dialogue_internals.rb
@@ -50,7 +50,6 @@ files:
50
50
  - lib/james/inputs/audio.rb
51
51
  - lib/james/inputs/base.rb
52
52
  - lib/james/inputs/terminal.rb
53
- - lib/james/main_dialogue.rb
54
53
  - lib/james/outputs/audio.rb
55
54
  - lib/james/outputs/terminal.rb
56
55
  - lib/james/state_api.rb
@@ -90,6 +89,7 @@ signing_key:
90
89
  specification_version: 3
91
90
  summary: 'James: Modular Electronic Butler.'
92
91
  test_files:
92
+ - spec/aux/james/cli_spec.rb
93
93
  - spec/integration/test_dialogue_spec.rb
94
94
  - spec/lib/james/controller_spec.rb
95
95
  - spec/lib/james/dialogue_spec.rb
@@ -1,25 +0,0 @@
1
- class Bla
2
-
3
- include James::Dialogue
4
-
5
- hear 'James?' => :awake
6
-
7
- state :awake do
8
- hear 'Leave me alone, James' => :away
9
- into { "Sir?" }
10
- end
11
-
12
- state :away do
13
- hear 'Are you there, James?' => :awake,
14
- "That's it for today, James" => :exit
15
- into { "Goodbye, Sir" }
16
- end
17
-
18
- state :exit do
19
- into do
20
- puts "James: Exits through a side door."
21
- Kernel.exit
22
- end
23
- end
24
-
25
- end
@@ -1,15 +0,0 @@
1
- module James
2
-
3
- # MainDialogue for first visitor.
4
- #
5
- module MainDialogue
6
-
7
- extend Dialogue
8
-
9
- def self.included into
10
- into.extend ClassMethods
11
- end
12
-
13
- end
14
-
15
- end