james 0.1.0-universal-darwin-10 → 0.1.1-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
@@ -5,6 +5,10 @@ module James
5
5
  class CLI
6
6
 
7
7
  def execute *patterns
8
+ silent = patterns.delete '-s'
9
+ silent_input = patterns.delete '-si'
10
+ silent_output = patterns.delete '-so'
11
+
8
12
  dialogs = find_dialogs_for patterns
9
13
 
10
14
  puts "James: I haven't found anything to talk about (No files found). Exiting." or exit!(1) if dialogs.empty?
@@ -12,7 +16,11 @@ module James
12
16
 
13
17
  load_all dialogs
14
18
 
15
- James.listen
19
+ options = {}
20
+ options[:input] = Inputs::Terminal if silent || silent_input
21
+ options[:output] = Outputs::Terminal if silent || silent_output
22
+
23
+ James.listen options
16
24
  end
17
25
  def find_dialogs_for patterns
18
26
  patterns = ["**/*_dialog{,ue}.rb"] if patterns.empty?
data/bin/james CHANGED
@@ -7,6 +7,11 @@
7
7
  # OR
8
8
  # james # Uses all dialogs it can find in this dir and subdirs.
9
9
  #
10
+ # Options:
11
+ # * -s # Silent input and output (same as "-si -so").
12
+ # * -si # Silent input.
13
+ # * -so # Silent output.
14
+ #
10
15
 
11
16
  begin
12
17
  require 'james/cli'
data/lib/james.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  module James; end
2
2
 
3
- # require File.expand_path '../james/timer', __FILE__
4
-
5
3
  require File.expand_path '../james/state_api', __FILE__
6
4
  require File.expand_path '../james/state_internals', __FILE__
7
5
 
@@ -35,18 +33,18 @@ module James
35
33
  dialogs.each { |dialog| controller.add_dialog dialog }
36
34
  end
37
35
 
38
- # Start a new controller and listen.
36
+ # Start listening.
39
37
  #
40
38
  # Will not listen again if already listening.
41
39
  #
42
- def self.listen
43
- controller.listen unless controller.listening?
40
+ def self.listen options
41
+ controller.listen options
44
42
  end
45
43
 
46
44
  # Controller instance.
47
45
  #
48
46
  def self.controller
49
- @controller ||= Controller.new
47
+ Controller.instance
50
48
  end
51
49
 
52
50
  end
@@ -2,21 +2,34 @@ module James
2
2
 
3
3
  class Controller
4
4
 
5
- attr_reader :visitor
5
+ attr_reader :visitor, :listening
6
+
7
+ # Singleton reader.
8
+ #
9
+ def self.instance
10
+ @controller ||= new
11
+ end
6
12
 
7
13
  # This puts together the core dialog and the user
8
14
  # ones that are hooked into it.
9
15
  #
10
16
  # TODO Rewrite this. Design needs some refactoring.
17
+ # Should the user visitor be created dynamically? (Probably yes.)
11
18
  #
12
19
  def initialize
13
- @user_dialogs = Dialogs.new
14
- system_visitor = Visitor.new CoreDialog.new.state_for(:awake)
15
- @visitor = Visitors.new system_visitor, @user_dialogs.visitor
20
+ @user_dialogs = Dialogs.new
21
+ @visitor = Visitors.new system_visitor, user_visitor
22
+ end
23
+ def system_visitor
24
+ Visitor.new CoreDialog.new.state_for(:awake)
25
+ end
26
+ def user_visitor
27
+ @user_dialogs.visitor
16
28
  end
17
29
 
30
+ # MacRuby callback functions.
31
+ #
18
32
  def applicationDidFinishLaunching notification
19
- load_voices
20
33
  start_output
21
34
  start_input
22
35
  end
@@ -24,12 +37,6 @@ module James
24
37
  exit
25
38
  end
26
39
 
27
- # Load voices from yaml.
28
- #
29
- def load_voices
30
- # TODO
31
- end
32
-
33
40
  # Add a dialog to the current system.
34
41
  #
35
42
  def add_dialog dialog
@@ -39,13 +46,13 @@ module James
39
46
  # Start recognizing words.
40
47
  #
41
48
  def start_input
42
- @input = Inputs::Audio.new self
49
+ @input = @input_class.new self
43
50
  @input.listen
44
51
  end
45
52
  # Start speaking.
46
53
  #
47
54
  def start_output
48
- @output = Outputs::Audio.new
55
+ @output = @output_class.new @output_options
49
56
  end
50
57
 
51
58
  # Callback method from dialog.
@@ -62,38 +69,28 @@ module James
62
69
  visitor.expects
63
70
  end
64
71
 
65
- def listen
72
+ # Start listening using the provided options.
73
+ #
74
+ # Options:
75
+ # * input # Inputs::Terminal or Inputs::Audio (default).
76
+ # * output # Outputs::Terminal or Outputs::Audio (default).
77
+ #
78
+ def listen options = {}
79
+ return if listening
80
+
81
+ @input_class = options[:input] || Inputs::Audio
82
+ @output_class = options[:output] || Outputs::Audio
83
+
84
+ @output_options ||= {}
85
+ @output_options[:voice] = options[:voice] || 'com.apple.speech.synthesis.voice.Alex'
86
+
66
87
  app = NSApplication.sharedApplication
67
88
  app.delegate = self
68
89
 
69
- # window = NSWindow.alloc.initWithContentRect([100, 300, 300, 100],
70
- # styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask,
71
- # backing:NSBackingStoreBuffered,
72
- # defer:false)
73
- # window.title = 'James Debug/Info'
74
- # window.level = 3
75
- # window.delegate = app.delegate
76
-
77
- # @button = NSButton.alloc.initWithFrame([10, 10, 400, 10])
78
- # @button.bezelStyle = 4
79
- # @button.title = ''
80
- # @button.target = app.delegate
81
- # @button.action = 'say_hello:'
82
- #
83
- # window.contentView.addSubview(@button)
84
-
85
- # window.display
86
- # window.orderFrontRegardless
87
-
88
90
  @listening = true
89
91
 
90
92
  app.run
91
93
  end
92
- # If listen has been called, it is listening.
93
- #
94
- def listening?
95
- !!@listening
96
- end
97
94
 
98
95
  end
99
96
 
@@ -2,7 +2,7 @@ module James
2
2
 
3
3
  # A dialog can be instantiated in two ways:
4
4
  #
5
- # The simple way, will directly add itself to James.
5
+ # The simple way will directly add itself to James.
6
6
  #
7
7
  # James.use_dialog(optional_args_for_initialize) do
8
8
  # # Your dialog.
@@ -10,12 +10,16 @@ module James
10
10
  # end
11
11
  #
12
12
  # class MyDialog
13
+ #
13
14
  # include James::Dialog
14
15
  #
15
- # # Your dialog.
16
+ # # Your dialog definition.
16
17
  # #
18
+ #
17
19
  # end
18
20
  #
21
+ # # Tell James to use the dialog.
22
+ # #
19
23
  # James.use MyDialog.new
20
24
  #
21
25
  module Dialog; end
@@ -33,7 +33,10 @@ module James
33
33
  end
34
34
  def recognize_new_commands
35
35
  possibilities = controller.expects
36
- puts "Possibilities:\n #{possibilities.join("\n ")}"
36
+ puts "Possibilities:\n"
37
+ possibilities.each_with_index do |possibility, index|
38
+ puts "#{index + 1}) #{possibility}"
39
+ end
37
40
  @recognizer.setCommands possibilities
38
41
  end
39
42
 
@@ -13,11 +13,18 @@ module James
13
13
  # Call this method if you heard something in the subclass.
14
14
  #
15
15
  def heard command
16
- # Call dialog.
17
- #
18
16
  controller.hear command
19
17
  end
20
18
 
19
+ # Shows possible commands in the terminal.
20
+ #
21
+ def show_possibilities possibilities
22
+ puts "Possibilities:\n"
23
+ possibilities.each_with_index do |possibility, index|
24
+ puts "#{index + 1}) #{possibility}"
25
+ end
26
+ end
27
+
21
28
  end
22
29
 
23
30
  end
@@ -6,17 +6,30 @@ module James
6
6
  #
7
7
  class Terminal < Base
8
8
 
9
+ # Start listening to commands by the user.
10
+ #
9
11
  def listen
10
12
  sleep 2
11
13
  loop do
12
14
  possibilities = controller.expects
13
- puts "Possibilities:\n #{possibilities.join("\n ")}"
14
- command = gets.chop
15
+ show_possibilities possibilities
16
+ command = get_command
15
17
  puts "I heard '#{command}'."
18
+ command = possibilities[command.to_i-1] unless command.to_i.zero?
16
19
  heard command if possibilities.include? command
17
20
  end
18
21
  end
19
22
 
23
+ # Get the next command by the user.
24
+ #
25
+ def get_command
26
+ STDIN.gets.chop
27
+ rescue IOError
28
+ puts "Wait a second, please, Sir, I am busy."
29
+ sleep 1
30
+ retry
31
+ end
32
+
20
33
  end
21
34
 
22
35
  end
@@ -4,11 +4,17 @@ module James
4
4
 
5
5
  class Audio
6
6
 
7
-
8
- def initialize voice = nil
9
- @output = NSSpeechSynthesizer.alloc.initWithVoice voice || 'com.apple.speech.synthesis.voice.Alex'
7
+ # Create a new audio output.
8
+ #
9
+ # Options:
10
+ # * voice # Default is 'com.apple.speech.synthesis.voice.Alex'.
11
+ #
12
+ def initialize options = {}
13
+ @output = NSSpeechSynthesizer.alloc.initWithVoice options[:voice] || 'com.apple.speech.synthesis.voice.Alex'
10
14
  end
11
15
 
16
+ # Say the given text out loud.
17
+ #
12
18
  def say text
13
19
  @output.startSpeakingString text
14
20
  end
@@ -6,8 +6,18 @@ module James
6
6
  #
7
7
  class Terminal
8
8
 
9
+ #
10
+ #
11
+ def initialize options = {}
12
+
13
+ end
14
+
15
+ # Say the given text in the terminal.
16
+ #
9
17
  def say text
18
+ puts
10
19
  p text
20
+ puts
11
21
  end
12
22
 
13
23
  end
data/lib/james/visitor.rb CHANGED
@@ -6,10 +6,6 @@ module James
6
6
  # too much time passes without input.
7
7
  #
8
8
  # Note: A visitor should generally be very stupid.
9
- # Note 2: We could call this Hearing, or Ear ;)
10
- #
11
- # TODO Add a timer which resets the state to the
12
- # initial state.
13
9
  #
14
10
  class Visitor
15
11
 
@@ -18,17 +14,15 @@ module James
18
14
 
19
15
  # Pass in an initial state to start from.
20
16
  #
21
- def initialize initial, timer = nil
17
+ def initialize initial
22
18
  @current = initial
23
19
 
24
20
  @initial = initial
25
- # @timer = timer || Timer.new
26
21
  end
27
22
 
28
23
  # Resets the current state back to the initial.
29
24
  #
30
25
  def reset
31
- # timer.stop
32
26
  self.current = initial
33
27
  end
34
28
 
@@ -59,7 +53,6 @@ module James
59
53
  end
60
54
  def hear phrase, &block
61
55
  return unless hears? phrase
62
- # timer.restart
63
56
  exit_text = exit &block
64
57
  transition phrase
65
58
  check &block
@@ -22,10 +22,6 @@ module James
22
22
  @visitors = visitors
23
23
  end
24
24
 
25
- def add_dialog dialog
26
-
27
- end
28
-
29
25
  # Hear tries all visitors in order
30
26
  # until one hears a phrase he knows.
31
27
  #
@@ -38,18 +34,18 @@ module James
38
34
  visitor.hear phrase, &block and break
39
35
  end
40
36
 
41
- while visitor = enumerator.shift
37
+ enumerator.each do |visitor|
42
38
  visitor.reset
43
39
  end
44
40
  end
45
41
 
46
- # Enter enters the first dialog.
42
+ # Enter enters the first visitor.
47
43
  #
48
44
  def enter
49
45
  visitors.first.enter
50
46
  end
51
47
 
52
- # Simply returns the sum of what phrases all dialogs expect.
48
+ # Simply returns the sum of what phrases all dialogs do expect, front-to-back.
53
49
  #
54
50
  # Stops as soon as a visitor is not in a chainable state anymore.
55
51
  #
@@ -7,6 +7,9 @@ require File.expand_path '../../../../lib/james/visitors', __FILE__
7
7
  require File.expand_path '../../../../lib/james/visitor', __FILE__
8
8
  require File.expand_path '../../../../lib/james/state_api', __FILE__
9
9
  require File.expand_path '../../../../lib/james/dialogs', __FILE__
10
+ require File.expand_path '../../../../lib/james/inputs/base', __FILE__
11
+ require File.expand_path '../../../../lib/james/inputs/terminal', __FILE__
12
+ require File.expand_path '../../../../lib/james/inputs/audio', __FILE__
10
13
  require File.expand_path '../../../../lib/james/controller', __FILE__
11
14
 
12
15
  describe James::Controller do
@@ -9,10 +9,6 @@ require File.expand_path '../../../../lib/james/dialogs', __FILE__
9
9
 
10
10
  describe James::Dialog do
11
11
 
12
- it 'can haz merkin spellink' do
13
- James::Dialog.should == James::Dialog
14
- end
15
-
16
12
  context 'units' do
17
13
  let(:dialog) do
18
14
  James.use_dialog do
@@ -89,15 +85,6 @@ describe James::Dialog do
89
85
  end
90
86
  end.to_not raise_error
91
87
  end
92
- it 'can haz merkin spellink' do
93
- expect do
94
- James.dialog do
95
-
96
- hear 'something' => :some_state
97
-
98
- end
99
- end.to_not raise_error
100
- end
101
88
  end
102
89
 
103
90
  end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ #
3
+ require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
4
+ require File.expand_path '../../../../../lib/james/inputs/audio', __FILE__
5
+
6
+ describe James::Inputs::Audio do
7
+
8
+ let(:input) { described_class.new }
9
+
10
+ describe 'speechRecognizer' do
11
+ it 'does something' do
12
+ sender = stub :sender
13
+
14
+ input.speechRecognizer sender
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ #
3
+ require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
4
+ require File.expand_path '../../../../../lib/james/inputs/terminal', __FILE__
5
+
6
+ describe James::Inputs::Terminal do
7
+
8
+ let(:input) { described_class.new }
9
+
10
+
11
+
12
+ end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: james
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.1.1
6
6
  platform: universal-darwin-10
7
7
  authors:
8
8
  - Florian Hanke
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-21 00:00:00 +10:00
12
+ date: 2011-05-29 00:00:00 +10:00
13
13
  default_executable: james
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -49,7 +49,6 @@ files:
49
49
  - lib/james/outputs/terminal.rb
50
50
  - lib/james/state_api.rb
51
51
  - lib/james/state_internals.rb
52
- - lib/james/timer.rb
53
52
  - lib/james/visitor.rb
54
53
  - lib/james/visitors.rb
55
54
  - lib/james.rb
@@ -58,6 +57,8 @@ files:
58
57
  - spec/integration/test_dialogue_spec.rb
59
58
  - spec/lib/james/controller_spec.rb
60
59
  - spec/lib/james/dialog_spec.rb
60
+ - spec/lib/james/inputs/audio_spec.rb
61
+ - spec/lib/james/inputs/terminal_spec.rb
61
62
  - spec/lib/james/state_spec.rb
62
63
  - spec/lib/james/visitor_spec.rb
63
64
  - spec/lib/james/visitors_spec.rb
@@ -92,6 +93,8 @@ test_files:
92
93
  - spec/integration/test_dialogue_spec.rb
93
94
  - spec/lib/james/controller_spec.rb
94
95
  - spec/lib/james/dialog_spec.rb
96
+ - spec/lib/james/inputs/audio_spec.rb
97
+ - spec/lib/james/inputs/terminal_spec.rb
95
98
  - spec/lib/james/state_spec.rb
96
99
  - spec/lib/james/visitor_spec.rb
97
100
  - spec/lib/james/visitors_spec.rb
data/lib/james/timer.rb DELETED
@@ -1,14 +0,0 @@
1
- module James
2
-
3
- class Timer
4
-
5
- def stop
6
-
7
- end
8
- def restart
9
-
10
- end
11
-
12
- end
13
-
14
- end