Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add simple `#gets` based interactor.

This extracts the Readline support into a separate class and keeps only the
generic behavior in the main interactor class, thus enabling the return of
the previous simple `#gets` based interactor.

Guard auto detects if Readline support is suitable on your environment, but
you can also use the new `interactor` DSL method to force a specific
implementation. (Fixes #197 and #200)
  • Loading branch information...
commit 4d2415e332b9a28b01a1969a56884d1458702f65 1 parent 408717d
@netzpirat netzpirat authored
View
17 CHANGELOG.md
@@ -1,3 +1,17 @@
+## Master
+
+### Improvements
+
+- Add `interactor` to DSL to allow switching Guard interaction implementation. ([@netzpirat][])
+- Add quit action to the interactor. ([@Maher4Ever][])
+
+## 0.9.1 - December 19, 2011
+
+### Bug fix
+
+- Fix wrong `--no-vendor` option. ([@netzpirat][])
+- [#195](https://github.com/guard/guard/issues/195): Empty watch directory prohibit Guard from running. (reported by [@madtrick][], fixed by [@netzpirat][]
+
## 0.9.0 - December 19, 2011
### Bug fix
@@ -383,3 +397,6 @@
[@wereHamster]: https://github.com/wereHamster
[@yannlugrin]: https://github.com/yannlugrin
[@zonque]: https://github.com/zonque
+
+[@Maher4Ever]: https://github.com/Maher4Ever
+[@madtrick]: https://github.com/madtrick
View
47 README.md
@@ -34,10 +34,6 @@ Add Guard to your `Gemfile`:
```ruby
group :development do
gem 'guard'
-
- platforms :ruby do
- gem 'rb-readline'
- end
end
```
@@ -361,11 +357,7 @@ read more about these files in the shared configuration section below.
Interactions
------------
-You can interact with Guard and enter commands when Guard has nothing to do. You'll see a command prompt `>` when Guard
-is ready to accept a command. The command line supports history navigation with the `↑` and `↓` arrow keys, and
-command auto-completion with the `⇥` key.
-
-You can execute the following commands:
+You can interact with Guard and enter commands when Guard has nothing to do. Guard understands the following commands:
* `↩`: Run all Guards.
* `h`, `help`: Show a help of the available interactor commands.
@@ -399,6 +391,23 @@ This will reload only the Ronn Guard. You can also reload all Guards within a gr
> backend reload
```
+### Readline support
+
+With Readline enabled, you'll see a command prompt `>` when Guard is ready to accept a command. The command line
+supports history navigation with the `↑` and `↓` arrow keys, and command auto-completion with the `⇥` key.
+
+Unfortunately Readline [does not work on MRI](http://bugs.ruby-lang.org/issues/5539) on Mac OS X by default. You can
+work around the issue by installing a pure Ruby implementation:
+
+```ruby
+platforms :ruby do
+ gem 'rb-readline'
+end
+```
+
+Guard will automatically enable Readline support if your environment supports it, but you can disable Readline with the
+`interactor` DSL method or turn off completely with the `--no-interactions` option.
+
Guardfile DSL
-------------
@@ -529,6 +538,26 @@ or using the cli switch `-n`:
notification :off
```
+### interactor
+
+You can disable the interactor auto detection and for a specific implementation:
+
+```ruby
+interactor :readline
+```
+
+will select Readline interactor. You can also force the simple interactor without Readline support with:
+
+```ruby
+interactor :simple
+```
+
+If you do not need the keyboard interactions with Guard at all, you can turn them off:
+
+```ruby
+interactor :off
+```
+
### callback
The `callback` method allows you to execute arbitrary code before or after any of the `start`, `stop`, `reload`,
View
7 lib/guard.rb
@@ -62,7 +62,6 @@ def setup(options = {})
@options = options
@guards = []
self.reset_groups
- @interactor = Interactor.new unless options[:no_interactions]
@listener = Listener.select_and_init(options)
UI.clear if @options[:clear]
@@ -177,7 +176,11 @@ def start(options = {})
run_supervised_task(guard, :start)
end
- interactor.start if interactor
+ unless options[:no_interactions]
+ @interactor = Interactor.fabricate
+ @interactor.start if @interactor
+ end
+
listener.start
end
View
15 lib/guard/dsl.rb
@@ -276,6 +276,21 @@ def notification(notifier, options = {})
::Guard::Notifier.add_notification(notifier.to_sym, options, false)
end
+ # Sets the interactor to use.
+ #
+ # @example Use the readline interactor
+ # interactor :readline
+ #
+ # @example Use the gets interactor
+ # interactor :gets
+ #
+ # @example Turn off interactions
+ # interactor :off
+ #
+ def interactor(interactor)
+ ::Guard::Interactor.interactor = interactor.to_sym
+ end
+
# Declares a group of guards to be run with `guard start --group group_name`.
#
# @example Declare two groups of Guards
View
106 lib/guard/interactor.rb
@@ -1,12 +1,10 @@
-require 'readline'
-
module Guard
- # The interactor reads user input and triggers
- # specific action upon them unless its locked.
- #
- # It used the readline library for history and
- # completion support.
+ autoload :ReadlineInteractor, 'guard/interactors/readline'
+ autoload :SimpleInteractor, 'guard/interactors/simple'
+
+ # The interactor triggers specific action from input
+ # read by a interactor implementation.
#
# Currently the following actions are implemented:
#
@@ -29,6 +27,8 @@ module Guard
# @example Run all jasmine specs
# jasmine
#
+ # @abstract
+ #
class Interactor
HELP_ENTRIES = %w[help h]
@@ -37,21 +37,52 @@ class Interactor
PAUSE_ENTRIES = %w[pause p]
NOTIFICATION_ENTRIES = %w[notification n]
- COMPLETION_ACTIONS = %w[help reload exit pause notification]
+ # Set the interactor implementation
+ #
+ # @param [Symbol] interactor the name of the interactor
+ #
+ def self.interactor=(interactor)
+ @interactor = interactor
+ end
- # Initialize the interactor.
+ # Get an instance of the currently configured
+ # interactor implementation.
#
- def initialize
- unless defined?(RbReadline) || defined?(JRUBY_VERSION)
- ::Guard::UI.info 'Please add rb-readline for proper Readline support.'
+ # @return [Interactor] an interactor implementation
+ #
+ def self.fabricate
+ case @interactor
+ when :readline
+ ReadlineInteractor.new
+ when :simple
+ SimpleInteractor.new
+ when :off
+ nil
+ else
+ auto_detect
end
+ end
- Readline.completion_proc = proc { |word| auto_complete(word) }
+ # Tries to detect an optimal interactor for the
+ # current environment.
+ #
+ # It returns the Readline implementation when:
+ #
+ # * rb-readline is installed
+ # * The Ruby implementation is JRuby
+ # * The current OS is not Mac OS X
+ #
+ # Otherwise the plain gets interactor is returned.
+ #
+ # @return [Interactor] an interactor implementation
+ #
+ def self.auto_detect
+ require 'readline'
- begin
- Readline.completion_append_character = ' '
- rescue NotImplementedError
- # Ignore, we just don't support it then
+ if defined?(RbReadline) || defined?(JRUBY_VERSION) || !RbConfig::CONFIG['target_os'] =~ /darwin/i
+ ReadlineInteractor.new
+ else
+ SimpleInteractor.new
end
end
@@ -70,40 +101,13 @@ def stop
end
end
- # Read a line from stdin with Readline.
+ # Read the user input. This method must be implemented
+ # by each interactor implementation.
#
- def read_line
- while line = Readline.readline(prompt, true)
- process_input(line)
- end
- end
-
- # Auto complete the given word.
- #
- # @param [String] word the partial word
- # @return [Array<String>] the matching words
- #
- def auto_complete(word)
- completion_list.grep(/^#{ Regexp.escape(word) }/)
- end
-
- # Get the auto completion list.
- #
- # @return [Array<String>] the list of words
+ # @abstract
#
- def completion_list
- groups = ::Guard.groups.map { |group| group.name.to_s }
- guards = ::Guard.guards.map { |guard| guard.class.to_s.downcase.sub('guard::', '') }
-
- COMPLETION_ACTIONS + groups + guards - ['default']
- end
-
- # The current interactor prompt
- #
- # @return [String] the prompt to show
- #
- def prompt
- ::Guard.listener.paused? ? 'p> ' : '> '
+ def read_line
+ raise NotImplementedError
end
# Process the input from readline.
@@ -111,10 +115,6 @@ def prompt
# @param [String] line the input line
#
def process_input(line)
- if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
- Readline::HISTORY.pop
- end
-
scopes, action = extract_scopes_and_action(line)
case action
View
72 lib/guard/interactors/readline.rb
@@ -0,0 +1,72 @@
+module Guard
+
+ # Interactor that used readline for getting the user input.
+ # This enables history support and auto-completion, but is
+ # broken on OS X without installing `rb-readline` or using JRuby.
+ #
+ # @see http://bugs.ruby-lang.org/issues/5539
+ #
+ class ReadlineInteractor < Interactor
+
+ COMPLETION_ACTIONS = %w[help reload exit pause notification]
+
+ # Initialize the interactor.
+ #
+ def initialize
+ require 'readline'
+
+ unless defined?(RbReadline) || defined?(JRUBY_VERSION)
+ ::Guard::UI.info 'Please add rb-readline for proper Readline support.'
+ end
+
+ Readline.completion_proc = proc { |word| auto_complete(word) }
+
+ begin
+ Readline.completion_append_character = ' '
+ rescue NotImplementedError
+ # Ignore, we just don't support it then
+ end
+ end
+
+ # Read a line from stdin with Readline.
+ #
+ def read_line
+ while line = Readline.readline(prompt, true)
+ if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
+ Readline::HISTORY.pop
+ end
+
+ process_input(line)
+ end
+ end
+
+ # Auto complete the given word.
+ #
+ # @param [String] word the partial word
+ # @return [Array<String>] the matching words
+ #
+ def auto_complete(word)
+ completion_list.grep(/^#{ Regexp.escape(word) }/)
+ end
+
+ # Get the auto completion list.
+ #
+ # @return [Array<String>] the list of words
+ #
+ def completion_list
+ groups = ::Guard.groups.map { |group| group.name.to_s }
+ guards = ::Guard.guards.map { |guard| guard.class.to_s.downcase.sub('guard::', '') }
+
+ COMPLETION_ACTIONS + groups + guards - ['default']
+ end
+
+ # The current interactor prompt
+ #
+ # @return [String] the prompt to show
+ #
+ def prompt
+ ::Guard.listener.paused? ? 'p> ' : '> '
+ end
+
+ end
+end
View
17 lib/guard/interactors/simple.rb
@@ -0,0 +1,17 @@
+module Guard
+
+ # Simple interactor that that reads user
+ # input from standard input.
+ #
+ class SimpleInteractor < Interactor
+
+ # Read a line from stdin with Readline.
+ #
+ def read_line
+ while line = $stdin.gets
+ process_input(line.chomp)
+ end
+ end
+
+ end
+end
View
6 man/guard.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "GUARD" "1" "October 2011" "" ""
+.TH "GUARD" "1" "December 2011" "" ""
.
.SH "NAME"
\fBguard\fR \- Guard keeps an eye on your file modifications\.
@@ -27,7 +27,7 @@ The following options are available:
\fB\-n\fR, \fB\-\-notify\fR \fIFLAG\fR Disable notifications (Growl or Libnotify depending on your system)\. Notifications can be disabled globally by setting a GUARD_NOTIFY environment variable to false\. FLAG can be \fBtrue\fR/\fBfalse\fR or \fBt\fR/\fBf\fR\.
.
.P
-\fB\-d\fR, \fB\-\-debug\fR Runs Guard in debug mode\.
+\fB\-v\fR, \fB\-\-verbose\fR Runs Guard in verbose mode\.
.
.P
\fB\-g\fR, \fB\-\-group\fR \fIGROUP1\fR \fIGROUP2\fR\.\.\. Runs only the groups specified by GROUP1, GROUP2 etc\. Groups name should be separated by spaces\. Guards that don\'t belong to a group are considered global and are always run\.
@@ -44,7 +44,7 @@ The following options are available:
.P
\fB\-i\fR, \fB\-\-no\-interactions\fR Turn off completely any Guard terminal interactions\.
.
-.SS "init <a href=\"guard\.html\">GUARD</a>"
+.SS "init [GUARD]"
If no Guardfile is present in the current directory, creates an empty Guardfile\.
.
.P
View
8 man/guard.1.html
@@ -97,8 +97,8 @@ <h3 id="start">start</h3>
Notifications can be disabled globally by setting a GUARD_NOTIFY environment variable to false.
FLAG can be <code>true</code>/<code>false</code> or <code>t</code>/<code>f</code>.</p>
-<p><code>-d</code>, <code>--debug</code>
- Runs Guard in debug mode.</p>
+<p><code>-v</code>, <code>--verbose</code>
+ Runs Guard in verbose mode.</p>
<p><code>-g</code>, <code>--group</code> <var>GROUP1</var> <var>GROUP2</var>...
Runs only the groups specified by GROUP1, GROUP2 etc.
@@ -117,7 +117,7 @@ <h3 id="start">start</h3>
<p><code>-i</code>, <code>--no-interactions</code>
Turn off completely any Guard terminal interactions.</p>
-<h3 id="init-GUARD">init <a href="guard.html">GUARD</a></h3>
+<h3 id="init-GUARD-">init [GUARD]</h3>
<p>If no Guardfile is present in the current directory, creates an empty Guardfile.</p>
@@ -172,7 +172,7 @@ <h2 id="WWW">WWW</h2>
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
- <li class='tc'>October 2011</li>
+ <li class='tc'>December 2011</li>
<li class='tr'>guard(1)</li>
</ol>
View
14 spec/guard/dsl_spec.rb
@@ -276,6 +276,20 @@ def self.disable_user_config
end
end
+ describe "#interactor" do
+ disable_user_config
+
+ it 'sets the interactor implementation' do
+ ::Guard::Interactor.should_receive(:interactor=).with(:readline)
+ described_class.evaluate_guardfile(:guardfile_contents => 'interactor :readline')
+ end
+
+ it 'converts the interactor to a symbol' do
+ ::Guard::Interactor.should_receive(:interactor=).with(:readline)
+ described_class.evaluate_guardfile(:guardfile_contents => 'interactor "readline"')
+ end
+ end
+
describe "#group" do
disable_user_config
View
111 spec/guard/interactor_spec.rb
@@ -4,79 +4,36 @@
describe Guard::Interactor do
subject { Guard::Interactor.new }
- describe "#initialize" do
- # completion_proc getter is not implemented in JRuby
- # see https://github.com/jruby/jruby/blob/master/src/org/jruby/ext/Readline.java#L349
- if RUBY_PLATFORM != 'java'
- it 'sets the Readline completion proc' do
- subject
- Readline.completion_proc.should be_a Proc
- end
- end
- end
-
describe '#readline' do
- before do
- Guard.listener = mock('listener')
- Guard.listener.stub(:paused?).and_return false
- end
-
- it 'reads all lines for processing' do
- Readline.should_receive(:readline).and_return 'First line'
- Readline.should_receive(:readline).and_return 'Second line'
- Readline.should_receive(:readline).and_return nil
- subject.should_receive(:process_input).with 'First line'
- subject.should_receive(:process_input).with 'Second line'
- subject.read_line
- end
- end
-
- describe '#auto_complete' do
- it 'returns the matching list of words' do
- subject.should_receive(:completion_list).any_number_of_times.and_return %w[help reload exit pause notification backend frontend foo foobar]
- subject.auto_complete('f').should =~ ['frontend', 'foo', 'foobar']
- subject.auto_complete('foo').should =~ ['foo', 'foobar']
- subject.auto_complete('he').should =~ ['help']
- subject.auto_complete('re').should =~ ['reload']
+ it 'must be implemented by a subclass' do
+ expect { subject.read_line }.to raise_error(NotImplementedError)
end
end
- describe "#completion_list" do
- class Guard::Foo < Guard::Guard;
- end
- class Guard::FooBar < Guard::Guard;
- end
-
- before(:each) do
- guard = ::Guard.setup
- @backend_group = guard.add_group(:backend)
- @frontend_group = guard.add_group(:frontend)
- @foo_guard = guard.add_guard(:foo, [], [], { :group => :backend })
- @foo_bar_guard = guard.add_guard('foo-bar', [], [], { :group => :frontend })
- end
-
- it 'creates the list of string to auto complete' do
- subject.completion_list.should =~ %w[help reload exit pause notification backend frontend foo foobar]
+ describe '.fabricate' do
+ it 'returns the Readline interactor for a :readline symbol' do
+ Guard::Interactor.interactor = :readline
+ Guard::Interactor.fabricate.should be_an_instance_of(Guard::ReadlineInteractor)
end
- it 'does not include the default scope' do
- subject.completion_list.should_not include('default')
+ it 'returns the Gets interactor for a :simple symbol' do
+ Guard::Interactor.interactor = :simple
+ Guard::Interactor.fabricate.should be_an_instance_of(Guard::SimpleInteractor)
end
- end
- describe "#prompt" do
- it 'returns > when listener is active' do
- ::Guard.listener.should_receive(:paused?).and_return false
- subject.prompt.should eql '> '
+ it 'returns nil for an :off symbol' do
+ Guard::Interactor.interactor = :off
+ Guard::Interactor.fabricate.should be_nil
end
- it 'returns p> when listener is paused' do
- ::Guard.listener.should_receive(:paused?).and_return true
- subject.prompt.should eql 'p> '
+ it 'auto detects the interactor when unspecified' do
+ Guard::Interactor.interactor = nil
+ Guard::Interactor.should_receive(:auto_detect)
+ Guard::Interactor.fabricate
end
end
- describe "#process_input" do
+ describe '#process_input' do
it 'shows the help on help action' do
subject.should_receive(:extract_scopes_and_action).with('help').and_return [{ }, :help]
subject.should_receive(:help)
@@ -120,7 +77,7 @@ class Guard::FooBar < Guard::Guard;
end
end
- describe "#reload" do
+ describe '#reload' do
before do
::Guard.stub(:reload)
::Guard::Dsl.stub(:reevaluate_guardfile)
@@ -152,7 +109,7 @@ class Guard::FooBar < Guard::Guard;
end
end
- describe "toggle_notification" do
+ describe 'toggle_notification' do
before { ::Guard::UI.stub(:info) }
it 'disables the notifications when enabled' do
@@ -168,7 +125,7 @@ class Guard::FooBar < Guard::Guard;
end
end
- describe "#extract_scopes_and_action" do
+ describe '#extract_scopes_and_action' do
class Guard::Foo < Guard::Guard;
end
@@ -183,68 +140,68 @@ class Guard::FooBar < Guard::Guard;
@foo_bar_guard = guard.add_guard('foo-bar', [], [], { :group => :frontend })
end
- it "returns :run_all action if entry is blank" do
+ it 'returns :run_all action if entry is blank' do
subject.extract_scopes_and_action('').should eql([{ }, :run_all])
end
- it "returns action if entry is only a action" do
+ it 'returns action if entry is only a action' do
subject.extract_scopes_and_action('exit').should eql([{ }, :stop])
end
- it "returns guard scope and run_all action if entry is only a guard scope" do
+ it 'returns guard scope and run_all action if entry is only a guard scope' do
subject.extract_scopes_and_action('foo-bar').should eql([{ :guard => @foo_bar_guard }, :run_all])
end
- it "returns group scope and run_all action if entry is only a group scope" do
+ it 'returns group scope and run_all action if entry is only a group scope' do
subject.extract_scopes_and_action('backend').should eql([{ :group => @backend_group }, :run_all])
end
- it "returns no action if entry is not a scope or action" do
+ it 'returns no action if entry is not a scope or action' do
subject.extract_scopes_and_action('x').should eql([{ }, nil])
end
- it "returns guard scope and action if entry is a guard scope and a action" do
+ it 'returns guard scope and action if entry is a guard scope and a action' do
subject.extract_scopes_and_action('foo r').should eql([{ :guard => @foo_guard }, :reload])
end
- it "returns group scope and action if entry is a group scope and a action" do
+ it 'returns group scope and action if entry is a group scope and a action' do
subject.extract_scopes_and_action('frontend r').should eql([{ :group => @frontend_group }, :reload])
end
- it "returns group scope and run_all action if entry is a group scope and not a action" do
+ it 'returns group scope and run_all action if entry is a group scope and not a action' do
subject.extract_scopes_and_action('frontend x').should eql([{ :group => @frontend_group }, :run_all])
end
- it "returns no action if entry is not a scope and not a action" do
+ it 'returns no action if entry is not a scope and not a action' do
subject.extract_scopes_and_action('x x').should eql([{ }, nil])
end
describe 'extracting actions' do
- it "returns :help action for the help entrie and for its shortcut" do
+ it 'returns :help action for the help entry and for its shortcut' do
%w{help h}.each do |e|
subject.extract_scopes_and_action(e).should eql([{ }, :help])
end
end
- it "returns :reload action for the reload entrie and for its shortcut" do
+ it 'returns :reload action for the reload entry and for its shortcut' do
%w{reload r}.each do |e|
subject.extract_scopes_and_action(e).should eql([{ }, :reload])
end
end
- it "returns :stop action for exit or quit entrie and for their shortcuts" do
+ it 'returns :stop action for exit or quit entry and for their shortcuts' do
%w{exit e quit q}.each do |e|
subject.extract_scopes_and_action(e).should eql([{ }, :stop])
end
end
- it "returns :pause action for the pause entrie and for its shortcut" do
+ it 'returns :pause action for the pause entry and for its shortcut' do
%w{pause p}.each do |e|
subject.extract_scopes_and_action(e).should eql([{ }, :pause])
end
end
- it "returns :notification action for the notification entrie and for its shortcut" do
+ it 'returns :notification action for the notification entry and for its shortcut' do
%w{notification n}.each do |e|
subject.extract_scopes_and_action(e).should eql([{ }, :notification])
end
View
79 spec/guard/interactors/readline_spec.rb
@@ -0,0 +1,79 @@
+require 'spec_helper'
+require 'guard/interactors/readline'
+
+describe Guard::ReadlineInteractor do
+ subject { Guard::ReadlineInteractor.new }
+
+ describe "#initialize" do
+ # completion_proc getter is not implemented in JRuby
+ # see https://github.com/jruby/jruby/blob/master/src/org/jruby/ext/Readline.java#L349
+ if RUBY_PLATFORM != 'java'
+ it 'sets the Readline completion proc' do
+ subject
+ Readline.completion_proc.should be_a Proc
+ end
+ end
+ end
+
+ describe '#readline' do
+ before do
+ Guard.listener = mock('listener')
+ Guard.listener.stub(:paused?).and_return false
+ end
+
+ it 'reads all lines for processing' do
+ Readline.should_receive(:readline).and_return 'First line'
+ Readline.should_receive(:readline).and_return 'Second line'
+ Readline.should_receive(:readline).and_return nil
+ subject.should_receive(:process_input).with('First line').and_return
+ subject.should_receive(:process_input).with('Second line').and_return
+ subject.read_line
+ end
+ end
+
+ describe '#auto_complete' do
+ it 'returns the matching list of words' do
+ subject.should_receive(:completion_list).any_number_of_times.and_return %w[help reload exit pause notification backend frontend foo foobar]
+ subject.auto_complete('f').should =~ ['frontend', 'foo', 'foobar']
+ subject.auto_complete('foo').should =~ ['foo', 'foobar']
+ subject.auto_complete('he').should =~ ['help']
+ subject.auto_complete('re').should =~ ['reload']
+ end
+ end
+
+ describe "#completion_list" do
+ class Guard::Foo < Guard::Guard;
+ end
+ class Guard::FooBar < Guard::Guard;
+ end
+
+ before(:each) do
+ guard = ::Guard.setup
+ @backend_group = guard.add_group(:backend)
+ @frontend_group = guard.add_group(:frontend)
+ @foo_guard = guard.add_guard(:foo, [], [], { :group => :backend })
+ @foo_bar_guard = guard.add_guard('foo-bar', [], [], { :group => :frontend })
+ end
+
+ it 'creates the list of string to auto complete' do
+ subject.completion_list.should =~ %w[help reload exit pause notification backend frontend foo foobar]
+ end
+
+ it 'does not include the default scope' do
+ subject.completion_list.should_not include('default')
+ end
+ end
+
+ describe "#prompt" do
+ it 'returns > when listener is active' do
+ ::Guard.listener.should_receive(:paused?).and_return false
+ subject.prompt.should eql '> '
+ end
+
+ it 'returns p> when listener is paused' do
+ ::Guard.listener.should_receive(:paused?).and_return true
+ subject.prompt.should eql 'p> '
+ end
+ end
+
+end
View
22 spec/guard/interactors/simple_spec.rb
@@ -0,0 +1,22 @@
+require 'guard/interactors/simple'
+
+describe Guard::SimpleInteractor do
+ subject { Guard::SimpleInteractor.new }
+
+ describe '#readline' do
+ before do
+ subject.stub(:process_input)
+ end
+
+ it 'reads all lines for processing' do
+ $stdin.should_receive(:gets).and_return "First line\n"
+ $stdin.should_receive(:gets).and_return "Second line\n"
+ $stdin.should_receive(:gets).and_return nil
+
+ subject.should_receive(:process_input).with('First line')
+ subject.should_receive(:process_input).with('Second line')
+ subject.read_line
+ end
+ end
+
+end
View
32 spec/guard_spec.rb
@@ -92,17 +92,6 @@ class Guard::Foo < Guard::Guard
::Guard.should_receive(:debug_command_execution)
::Guard.setup(:verbose => true)
end
-
- it "initializes the interactor" do
- ::Guard.setup
- ::Guard.interactor.should be_kind_of(Guard::Interactor)
- end
-
- it "skips the interactor initalization if no-interactions is true" do
- ::Guard.interactor = nil
- ::Guard.setup(:no_interactions => true)
- ::Guard.interactor.should be_nil
- end
end
describe ".guards" do
@@ -262,6 +251,27 @@ class Guard::FooBaz < Guard::Guard; end
::Guard.start(options)
end
+ context "with interactions enabled" do
+ it "fabricates the interactor" do
+ ::Guard::Interactor.should_receive(:fabricate)
+ ::Guard.start(:no_interactions => false)
+ end
+
+ it "starts the interactor" do
+ interactor = mock('interactor')
+ interactor.should_receive(:start)
+ ::Guard::Interactor.should_receive(:fabricate).and_return interactor
+ ::Guard.start(:no_interactions => false)
+ end
+ end
+
+ context "with interactions disabled" do
+ it "fabricates the interactor" do
+ ::Guard::Interactor.should_not_receive(:fabricate)
+ ::Guard.start(:no_interactions => true)
+ end
+ end
+
context "with the notify option enabled" do
context 'without the environment variable GUARD_NOTIFY set' do
before { ENV["GUARD_NOTIFY"] = nil }

3 comments on commit 4d2415e

@thibaudgg
Owner

That's pure awesomeness!

@rymai
Owner

Too much love right now ! Thanks Michi! :heart:

@netzpirat
Owner

Thanks. It allows us also to easily plug in other implementations. I already did some test with https://github.com/Mon-Ouie/coolline, looks promising but is not ready for prime time now.

Please sign in to comment.
Something went wrong with that request. Please try again.