ripl-multi_line 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemspec CHANGED
@@ -11,7 +11,11 @@ Gem::Specification.new do |s|
11
11
  s.summary = "A ripl plugin for multi-line eval."
12
12
  s.description = "This ripl plugin allows you to evaluate multiple lines of Ruby code."
13
13
  s.required_rubygems_version = ">= 1.3.6"
14
- s.add_dependency 'ripl', '>= 0.3.2'
14
+ s.add_dependency 'ripl', '>= 0.3.6'
15
+ s.add_development_dependency 'bacon', '>= 1.1.0'
16
+ s.add_development_dependency 'bacon-bits'
17
+ s.add_development_dependency 'bacon-rr'
18
+ s.add_development_dependency 'rr'
15
19
  s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} **/deps.rip]) + %w{Rakefile .gemspec}
16
20
  s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
17
21
  s.license = 'MIT'
@@ -1,3 +1,13 @@
1
+ == 0.3.0
2
+ * comes with five different multi-line implementations: live_error, error_check, irb, ripper and ruby_parser
3
+ * can be changed with config[:multi_line_engine], default is :live_error
4
+ * add :multi_line_history option (default: compact), based on https://gist.github.com/939846
5
+ * support =begin...=end comments
6
+ * add Shell#multiline? method to check if input should be handled as multi-line input
7
+ * separate Ruby-specific multi-line stuff from general implementation
8
+ * add some basic tests
9
+ * force multi-line with ; after input
10
+
1
11
  == 0.2.4
2
12
  * fix 1.8 warning
3
13
 
@@ -13,7 +23,7 @@
13
23
 
14
24
  == 0.2.0
15
25
  * store buffer in an array instead of a string
16
- * added ctrl+c to remove last line in multi-line situation
26
+ * added ctrl+c to remove last line in multi-line situations
17
27
 
18
28
  == 0.1.4
19
29
  * be compatible with 0.2.4 (undo monkey patch)
@@ -4,25 +4,59 @@ This {ripl}[https://github.com/cldwalker/ripl] plugin allows you to evaluate mul
4
4
  == Install
5
5
  Install the gem with
6
6
 
7
- gem install ripl-multi_line
7
+ gem install ripl-multi_line
8
8
 
9
9
  == Usage
10
-
11
10
  Add the following line to your <tt>~/.riplrc</tt>
12
11
 
13
12
  require 'ripl/multi_line'
14
13
 
14
+ <b>Hint:</b> In multi-line situations, you can press <tt>ctrl+c</tt> and the last line will be removed.
15
+
16
+ == Options
15
17
  You can customize your multi-line prompt with the <tt>:multi_line_prompt</tt> option. For example, put this into your <tt>~/.riplrc</tt>:
16
18
 
17
19
  Ripl.config[:multi_line_prompt] = ' > '
18
20
 
19
- If you are in multi-line situation, you can press <tt>ctrl+c</tt> and the last line will be removed.
21
+ It also takes a proc as value.
22
+
23
+ Then there is the <tt>:multi_line_history</tt> option. The default value is <tt>:compact</tt> which tries to squeeze your last multi-line block into one line (works best in mri, in about 98% of all cases).
24
+
25
+ >> def some_multi_line_block
26
+ | 42
27
+ | end #=> nil
28
+ # Press <UP>
29
+ >> def some_multi_line_block; 42; end
30
+
31
+ Another value is <tt>:block</tt>, which joins the multi-line block with new-lines.
32
+
33
+ To leave the history untouched, set it to <tt>:plain</tt> or a false value.
20
34
 
21
35
  == AutoIndent
22
- There is also an indention plugin available: {ripl-auto_indent}[https://github.com/janlelis/ripl-auto_indent]
36
+ Check out the {ripl-auto_indent}[https://github.com/janlelis/ripl-auto_indent] plugin to get ruby syntax indention.
37
+
38
+ == MultiLine detection
39
+ To use your own multi-line detection engine, implement your version at <tt>lib/ripl/multi_line/your_correct_detection.rb</tt> in which you overwrite <tt>Shell#multiline?</tt> in a <tt>Ripl::MultiLine</tt> sub-module named <tt>YourCorrectDetection</tt> and set <tt>Ripl.config[:multi_line_engine]</tt> to <tt>:your_correct_detection</tt>. See <tt>lib/ripl/multi_line/*.rb</tt> for examples.
40
+
41
+ Currently available engines:
42
+ * <tt>:live_error</tt> (<b>default</b>) - Simply evaluate expression, if it throws a multi-line syntax error, fall back to multi-line input mode. Sounds scary, but works pretty well in practice.
43
+ * <tt>:error_check</tt> - Same principle as :live_error, but don't do it live
44
+ * <tt>:ripper</tt> - Analyze input with Ripper (comes with 1.9, but there is also a 1.8 gem).
45
+ * <tt>:ruby_parser</tt> - Use ruby_parser gem (1.8 only)
46
+ * <tt>:irb</tt> - You left irb, but you are still used to its multi-line behaviour? Use irb's RubyLex!
47
+
48
+ None of the above solutions is perfect, so... maybe it's time to roll your own ;)
49
+
50
+ == Troubleshooting
51
+ <i>Problem:</i> "I've required <tt>ripl-multi_line</tt>, but it doesn't work"
52
+
53
+ <i>Answer:</i> This is probably caused by a plugin, which overwrites <tt>:before_loop</tt>, but does not call <tt>super</tt> (or you are using ripl-profiles older than 0.2.0). You can manually work around this issue with this snippet (but you should fix the general problem):
54
+
55
+ require 'ripl/multi_line/live_error.rb'
56
+ Ripl::MultiLine.engine = Ripl::MultiLine::LiveError
57
+ Ripl::Shell.include Ripl::MultiLine.engine
23
58
 
24
- == Planned for version 0.3.0
25
- * Tests :)
26
- * Replaceable check if syntax is valid (then, the plugin can be used for other languages than Ruby)
59
+ == Credits
60
+ Contributions & influences by cldwalker and godfat.
27
61
 
28
62
  J-_-L
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ def gemspec
6
6
  end
7
7
 
8
8
  desc "Build the gem"
9
- task :gem=>:gemspec do
9
+ task :gem => :gemspec do
10
10
  sh "gem build .gemspec"
11
11
  FileUtils.mkdir_p 'pkg'
12
12
  FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  desc "Install the gem locally"
16
16
  task :install => :gem do
17
- sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
17
+ sh %{gem install pkg/#{gemspec.name}-#{gemspec.version} --no-rdoc --no-ri}
18
18
  end
19
19
 
20
20
  desc "Generate the gemspec"
@@ -2,27 +2,27 @@ require 'ripl'
2
2
 
3
3
  module Ripl
4
4
  module MultiLine
5
- VERSION = '0.2.4'
6
- ERROR_REGEXP = /#{
7
- [ %q%unexpected \$end%,
8
- %q%unterminated [a-z]+ meets end of file%,
9
- # rubinius
10
- %q%expecting '\\n' or ';'%,
11
- %q%missing 'end'%,
12
- %q%expecting '\}'%,
13
- # jruby
14
- %q%syntax error, unexpected end-of-file%,
15
- ]*'|' }/
5
+ VERSION = '0.3.0'
6
+
7
+ class << self
8
+ attr_accessor :engine
9
+ end
16
10
 
17
11
  def before_loop
12
+ @buffer = @buffer_info = nil
13
+ # include CamelCased implementation
14
+ require File.join( 'ripl', 'multi_line', config[:multi_line_engine].to_s )
15
+ Ripl::MultiLine.engine = Ripl::MultiLine.const_get(
16
+ config[:multi_line_engine].to_s.gsub(/(^|_)(\w)/){ $2.capitalize }
17
+ )
18
+ Ripl::Shell.include Ripl::MultiLine.engine
18
19
  super
19
- @buffer = nil
20
20
  end
21
21
 
22
22
  def prompt
23
23
  if @buffer
24
24
  config[:multi_line_prompt].respond_to?(:call) ?
25
- config[:multi_line_prompt].call :
25
+ config[:multi_line_prompt].call( *@buffer_info[-1] ) :
26
26
  config[:multi_line_prompt]
27
27
  else
28
28
  super
@@ -35,49 +35,87 @@ module Ripl
35
35
  def loop_once
36
36
  catch(:multiline) do
37
37
  super
38
- @buffer = nil
38
+ if config[:multi_line_history] && @buffer && @input
39
+ (@buffer.size + 1).times{ history.pop }
40
+
41
+ if config[:multi_line_history] == :compact
42
+ history_entry = ''
43
+ @buffer.zip(@buffer_info){ |str, type|
44
+ history_entry << str
45
+ history_entry << case
46
+ when !type.is_a?(Array)
47
+ "\n" # fallback to :block for unsure
48
+ when type[0] == :statement
49
+ '; '
50
+ when type[0] == :literal && ( type[1] == :string || type[1] == :regexp )
51
+ '\n'
52
+ else
53
+ ''
54
+ end
55
+ }
56
+ history_entry << @input
57
+ history << history_entry
58
+ else # true or :block
59
+ history << (@buffer << @input).join("\n")
60
+ end
61
+ end
62
+
63
+ @buffer = @buffer_info = nil
39
64
  end
40
65
  end
41
66
 
42
- def print_eval_error(e)
43
- if e.is_a?(SyntaxError) && e.message =~ ERROR_REGEXP
44
- @buffer ||= []
45
- @buffer << @input
46
- throw :multiline
47
- else
48
- super
49
- end
67
+ # This method is overwritten by a multi-line implementation in lib/multi_line/*.rb
68
+ # It should return a true value for a string that is unfinished and a false one
69
+ # for complete expressions, which should get evaluated.
70
+ # It's also possible (and encouraged) to return an array of symbols describing
71
+ # what's the reason for continuing the expression (this is used in the :compact
72
+ # history and gets passed to the prompt proc.
73
+ def multiline?(eval_string)
74
+ false
75
+ end
76
+
77
+ def handle_multiline(type = [:statement]) # MAYBE: add second arg for specific information
78
+ @buffer ||= []
79
+ @buffer_info ||= []
80
+ @buffer << @input
81
+ @buffer_info << type
82
+ throw :multiline
50
83
  end
51
84
 
52
85
  def loop_eval(input)
53
- if @buffer
54
- super @buffer*"\n" + "\n" + input
55
- else
56
- super input
86
+ eval_string = if @buffer then @buffer*"\n" + "\n" + input else input end
87
+ if type = multiline?(eval_string)
88
+ handle_multiline(type)
57
89
  end
90
+ super eval_string
58
91
  end
59
92
 
60
93
  # remove last line from buffer
61
- # TODO: nicer interface (rewriting?)
94
+ # MAYBE: terminal rewriting
62
95
  def handle_interrupt
63
96
  if @buffer
64
- @buffer.pop
97
+ @buffer.pop; @buffer_info.pop; history.pop
65
98
  if @buffer.empty?
66
- @buffer = nil
99
+ @buffer = @buffer_info = nil
100
+ print '[buffer empty]'
67
101
  return super
68
102
  else
69
- puts "[previous line removed]"
103
+ puts "[previous line removed|#{@buffer.size}]"
70
104
  throw :multiline
71
105
  end
72
106
  else
73
107
  super
74
108
  end
75
109
  end
110
+
76
111
  end
77
112
  end
78
113
 
79
- Ripl::Shell.include Ripl::MultiLine
80
- Ripl.config[:multi_line_prompt] ||= proc do # you can also use a plain string here
114
+ Ripl::Shell.include Ripl::MultiLine # implementation gets included in before_loop
115
+ Ripl.config[:multi_line_engine] ||= :live_error # not satisfied? try :ripper, :irb or implement your own
116
+ Ripl.config[:multi_line_history] ||= :compact # possible other values: :block, :blank
117
+
118
+ Ripl.config[:multi_line_prompt] ||= proc do # you can also use a plain string here
81
119
  '|' + ' '*(Ripl.shell.instance_variable_get(:@prompt).size-1) # '| '
82
120
  end
83
121
 
@@ -0,0 +1,31 @@
1
+ require 'ripl'
2
+
3
+ Ripl.config[:multi_line_engine] ||= :error_check
4
+ require 'ripl/multi_line'
5
+ require 'ripl/multi_line/live_error'
6
+
7
+ # # # #
8
+ # This multi-line implementation uses IRB's RubyLex parser
9
+ # works on: 1.9 1.8 jruby rbx
10
+ # analyze features: see live_error.rb
11
+ # known issues: see live_error.rb
12
+ module Ripl::MultiLine::ErrorCheck
13
+ VERSION = '0.1.0'
14
+
15
+ ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE.downcase.to_sym
16
+ ruby_engine = :ruby if !Ripl::MultiLine::LiveError::ERROR_MESSAGES.keys.include?(ruby_engine)
17
+
18
+ define_method(:multiline?) do |string|
19
+ break [:forced] if string =~ /;\s*\Z/ # force multi line with ;
20
+
21
+ begin
22
+ eval "if nil; #{string}; end"
23
+ rescue SyntaxError => e
24
+ Ripl::MultiLine::LiveError::ERROR_MESSAGES[ruby_engine].each{ |type, message|
25
+ break type if message === e.message
26
+ }
27
+ end
28
+ end
29
+ end
30
+
31
+ # J-_-L
@@ -0,0 +1,59 @@
1
+ require 'ripl'
2
+ require 'irb/ruby-lex'
3
+ require 'stringio'
4
+
5
+ Ripl.config[:multi_line_engine] ||= :irb
6
+ require 'ripl/multi_line'
7
+
8
+ # # # #
9
+ # This multi-line implementation uses IRB's RubyLex parser
10
+ # works on: 1.9 1.8 jruby rbx
11
+ # analyze features: none
12
+ module Ripl::MultiLine::Irb
13
+ VERSION = '0.1.0'
14
+
15
+ class << self
16
+ attr_reader :scanner
17
+ end
18
+
19
+ # create scanner and patch it to our needs
20
+ @scanner = RubyLex.new
21
+
22
+ def @scanner.multiline?
23
+ initialize_input
24
+ @continue = false
25
+ @found_eof = false
26
+
27
+ while line = lex
28
+ @line << line
29
+ @continue = false
30
+ end
31
+
32
+ !!( !@found_eof or @ltype or @continue or @indent > 0 )
33
+ end
34
+
35
+ def @scanner.lex
36
+ until (((tk = token).kind_of?(RubyLex::TkNL) || tk.kind_of?(RubyLex::TkEND_OF_SCRIPT)) &&
37
+ !@continue or
38
+ tk.nil?)
39
+ #p tk
40
+ #p @lex_state
41
+ #p self
42
+ end
43
+ @found_eof = true if tk.kind_of?(RubyLex::TkEND_OF_SCRIPT)
44
+ line = get_readed
45
+ # print self.inspect
46
+ if line == "" and tk.kind_of?(RubyLex::TkEND_OF_SCRIPT) || tk.nil?
47
+ nil
48
+ else
49
+ line
50
+ end
51
+ end
52
+
53
+ def multiline?(string)
54
+ Ripl::MultiLine::Irb.scanner.set_input StringIO.new(string + "\0")
55
+ Ripl::MultiLine::Irb.scanner.multiline?
56
+ end
57
+ end
58
+
59
+ # J-_-L
@@ -0,0 +1,73 @@
1
+ require 'ripl'
2
+
3
+ Ripl.config[:multi_line_engine] ||= :live_error
4
+ require 'ripl/multi_line'
5
+
6
+ # # # #
7
+ # This multi-line implementation uses IRB's RubyLex parser
8
+ # works on: 1.9 1.8 jruby rbx
9
+ # analyze features: [:literal, :string]
10
+ # [:literal, :regexp]
11
+ # [:literal, :array] (mri only)
12
+ # [:literal, :hash] (mri only)
13
+ # [:statement]
14
+ # [:forced]
15
+ # notes: rbx support buggy (depends on rubinius error messages)
16
+ module Ripl::MultiLine::LiveError
17
+ VERSION = "0.1.0"
18
+
19
+ ERROR_MESSAGES = {
20
+ :ruby => [
21
+ [[:literal, :string], /unterminated string meets end of file/],
22
+ [[:literal, :regexp], /unterminated regexp meets end of file/],
23
+ [[:literal, :array], /syntax error, unexpected \$end, expecting '\]'/],
24
+ [[:literal, :hash], /syntax error, unexpected \$end, expecting '\}'/], # does not work for ranges or {5=>
25
+ [[:statement], /syntax error, unexpected \$end/],
26
+ ],
27
+ :jruby => [
28
+ [[:literal, :string], /unterminated string meets end of file/],
29
+ [[:literal, :regexp], /unterminated regexp meets end of file/], # array or hash cannot be detected
30
+ [[:statement], /syntax error, unexpected end-of-file/],
31
+ ],
32
+ :rbx => [
33
+ [[:literal, :string], /unterminated [a-z]+ meets end of file/], # no extra message for regexes
34
+ [[:literal], /expecting '\\n' or ';'/], # TODO: better rbx regexes or rbx bug report
35
+ [[:literal, :hash], /expecting '\}'/],
36
+ # [:literal, /expecting '\]'/],
37
+ # [:literal, /expecting '\)'/],
38
+ [[:statement], /syntax error, unexpected \$end/],
39
+ [[:statement], /missing 'end'/], # for i in [2,3,4] do;
40
+ ],
41
+ }
42
+ ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE.downcase.to_sym
43
+ ruby_engine = :ruby if !ERROR_MESSAGES.keys.include?(ruby_engine)
44
+
45
+ define_method(:print_eval_error) do |e|
46
+ if e.is_a? SyntaxError
47
+ ERROR_MESSAGES[ruby_engine].each{ |type, message|
48
+ handle_multiline(type) if message === e.message
49
+ }
50
+ end
51
+ super(e)
52
+ end
53
+
54
+ def eval_input(input)
55
+ if input =~ /;\s*\Z/ # force multi line with ;
56
+ handle_multiline(:forced)
57
+ elsif input =~ /^=begin(\s.*)?$/ && !@buffer
58
+ @ignore_mode = true # MAYBE: change prompt
59
+ elsif !@ignore_mode
60
+ super
61
+ end
62
+ end
63
+
64
+ def print_result(result)
65
+ if @ignore_mode && @input == '=end'
66
+ @ignore_mode = false
67
+ elsif !@ignore_mode
68
+ super
69
+ end
70
+ end
71
+ end
72
+
73
+ # J-_-L
@@ -0,0 +1,50 @@
1
+ # see https://github.com/cldwalker/ripl-ripper/blob/master/lib/ripl/ripper.rb for a different (standalone) plugin
2
+ require 'ripl'
3
+ require 'ripper'
4
+
5
+ Ripl.config[:multi_line_engine] ||= :ripper
6
+ require 'ripl/multi_line'
7
+
8
+ # # # #
9
+ # This multi-line implementation uses IRB's RubyLex parser
10
+ # works on: 1.9 1.8(gem)
11
+ # analyze features: [:literal, :string]
12
+ # [:literal, :regexp]
13
+ # [:literal, :array] (mri only)
14
+ # [:literal, :hash] (mri only)
15
+ # [:statement]
16
+ # [:forced]
17
+ # notes: statement could also be [
18
+ module Ripl::MultiLine::Ripper
19
+ VERSION = '0.1.0'
20
+
21
+ def multiline?(string)
22
+ return [:forced] if string =~ /;\s*\Z/
23
+
24
+ expr = ::Ripper::SexpBuilder.new(string).parse
25
+
26
+ return [:statement] if !expr # not always statements...
27
+
28
+ # literals are problematic..
29
+ last_expr = expr[-1][-1]
30
+
31
+ return [:literal, :regexp] if last_expr == [:regexp_literal, [:regexp_new], nil]
32
+
33
+ delimiters = %q_(?:[\[<({][\]>)}]|(.)\1)_
34
+
35
+ return [:literal, :string] if last_expr == [:string_literal, [:string_content]] &&
36
+ string !~ /(?:""|''|%q?#{delimiters})\s*\Z/i # empty literal at $
37
+
38
+ return [:literal, :string] if last_expr == [:xstring_literal, [:xstring_new]] &&
39
+ string !~ /(?:``|%x#{delimiters})\s*\Z/i
40
+
41
+ return [:literal, :string] if last_expr == [:words_new] &&
42
+ string !~ /%W#{delimiters}\s*\Z/
43
+
44
+ return [:literal, :string] if last_expr == [:qwords_new] &&
45
+ string !~ /%w#{delimiters}\s*\Z/
46
+ end
47
+ end
48
+
49
+
50
+ # J-_-L
@@ -0,0 +1,39 @@
1
+ require 'ripl'
2
+ require 'ruby_parser'
3
+
4
+ Ripl.config[:multi_line_engine] ||= :ruby_parser
5
+ require 'ripl/multi_line'
6
+
7
+ # # # #
8
+ # This multi-line implementation uses IRB's RubyLex parser
9
+ # works on: 1.8
10
+ # analyze features: [:literal, :string]
11
+ # [:literal, :hash]
12
+ # [:statement]
13
+ # [:forced]
14
+ # notes: statement could also be [
15
+ module Ripl::MultiLine::RubyParser
16
+ VERSION = '0.1.0'
17
+
18
+ ERROR_MESSAGES = [
19
+ [[:literal, :string], /unterminated string meets end of file/],
20
+ # [[:literal, :regexp], /unterminated regexp meets end of file/], #-> string
21
+ # [[:literal, :array], /syntax error, unexpected \$end, expecting '\]'/], #-> ParseError
22
+ [[:literal, :hash], /syntax error, unexpected \$end, expecting '\}'/], # {45
23
+ ]
24
+
25
+ def multiline?(string)
26
+ return [:forced] if string =~ /;\s*\Z/ # force multi line with ;
27
+ ::RubyParser.new.parse(string)
28
+ false # string was parsable, no multi-line
29
+ rescue ::Racc::ParseError
30
+ [:statement]
31
+ rescue SyntaxError => e
32
+ ERROR_MESSAGES.each{ |type, message|
33
+ return type if message === e.message
34
+ }
35
+ false # syntax error not multi-line relevant
36
+ end
37
+ end
38
+
39
+ # J-_-L
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "Shell" do
4
+ before { reset_ripl }
5
+
6
+ def shell(options={})
7
+ Ripl.shell(options)
8
+ end
9
+
10
+ describe "multi-line behaviour" do
11
+ should_eval %| "m" * 2 |
12
+ should_eval %| "8989" |
13
+ should_eval %| "zzz" |
14
+
15
+ should_not_eval %| "m" * |
16
+
17
+ should_not_eval %| " |
18
+ should_not_eval %| ' |
19
+ should_not_eval %| / |
20
+
21
+ should_not_eval %| [ |
22
+ should_not_eval %| { |
23
+ should_not_eval %| ( |
24
+
25
+ should_not_eval %| def hey |
26
+ should_not_eval %| def hey; 89 |
27
+ should_not_eval %| begin |
28
+ should_eval %| for x in [2,3,4];7;end |
29
+ end
30
+
31
+ # TODO add misc real tests for everything
32
+ end
@@ -0,0 +1,83 @@
1
+ require 'bacon'
2
+ require 'bacon/bits'
3
+ require 'rr'
4
+ require 'bacon/rr'
5
+ require 'stringio'
6
+ require 'ripl'
7
+ require 'ripl/multi_line'
8
+ include Ripl
9
+
10
+ module Helpers
11
+ def ripl(*args)
12
+ options = args[-1].is_a?(Hash) ? args.pop : {}
13
+ mock_riplrc unless options[:riplrc] == false
14
+ mock(Ripl.shell).loop unless options[:loop] == false
15
+ capture_stdout { Ripl::Runner.run(args) }
16
+ end
17
+
18
+ def mock_riplrc(&block)
19
+ mock(Runner).load_rc(Ripl.config[:riplrc], &block)
20
+ end
21
+
22
+ def mock_shell(&block)
23
+ mock(Shell).create(anything) {|e|
24
+ shell = Shell.new(e)
25
+ block ? block.call(shell) : mock(shell).loop
26
+ shell
27
+ }
28
+ end
29
+
30
+ def reset_ripl
31
+ Ripl.instance_eval "@config = @shell = @riplrc = nil"
32
+ end
33
+
34
+ def reset_shell
35
+ Ripl.send(:remove_const, :Shell)
36
+ $".delete $".grep(/shell\.rb/)[0]
37
+ require 'ripl/shell'
38
+ Ripl::Shell.include Ripl::History
39
+ end
40
+
41
+ def reset_config
42
+ Ripl.config.merge! :history => '~/.irb_history', :completion => {}
43
+ end
44
+
45
+ def capture_stdout(&block)
46
+ original_stdout = $stdout
47
+ $stdout = fake = StringIO.new
48
+ begin
49
+ yield
50
+ ensure
51
+ $stdout = original_stdout
52
+ end
53
+ fake.string
54
+ end
55
+
56
+ def capture_stderr(&block)
57
+ original_stderr = $stderr
58
+ $stderr = fake = StringIO.new
59
+ begin
60
+ yield
61
+ ensure
62
+ $stderr = original_stderr
63
+ end
64
+ fake.string
65
+ end
66
+
67
+ # multi_line stuff
68
+ def should_eval(input)
69
+ it "should evaluate " + input do
70
+ mock(shell).get_input { input }
71
+ capture_stderr { capture_stdout { shell.loop_once }.should.not == '' }
72
+ end
73
+ end
74
+
75
+ def should_not_eval(input)
76
+ it "should not evaluate " + input do
77
+ mock(shell).get_input { input }
78
+ capture_stderr { capture_stdout { shell.loop_once }.should == '' }
79
+ end
80
+ end
81
+ end
82
+
83
+ Bacon::Context.send :include, Helpers
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ripl-multi_line
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.4
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jan Lelis
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-10 00:00:00 +01:00
14
- default_executable:
13
+ date: 2011-04-28 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: ripl
@@ -21,9 +20,53 @@ dependencies:
21
20
  requirements:
22
21
  - - ">="
23
22
  - !ruby/object:Gem::Version
24
- version: 0.3.2
23
+ version: 0.3.6
25
24
  type: :runtime
26
25
  version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: bacon
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 1.1.0
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: bacon-bits
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: bacon-rr
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rr
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
27
70
  description: This ripl plugin allows you to evaluate multiple lines of Ruby code.
28
71
  email: mail@janlelis.de
29
72
  executables: []
@@ -35,13 +78,19 @@ extra_rdoc_files:
35
78
  - LICENSE.txt
36
79
  files:
37
80
  - lib/ripl/multi_line.rb
81
+ - lib/ripl/multi_line/live_error.rb
82
+ - lib/ripl/multi_line/error_check.rb
83
+ - lib/ripl/multi_line/ripper.rb
84
+ - lib/ripl/multi_line/ruby_parser.rb
85
+ - lib/ripl/multi_line/irb.rb
86
+ - test/test_helper.rb
87
+ - test/shell_test.rb
38
88
  - LICENSE.txt
39
89
  - README.rdoc
40
90
  - CHANGELOG.rdoc
41
91
  - deps.rip
42
92
  - Rakefile
43
93
  - .gemspec
44
- has_rdoc: true
45
94
  homepage: http://github.com/janlelis/ripl-multi_line
46
95
  licenses:
47
96
  - MIT
@@ -65,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
114
  requirements: []
66
115
 
67
116
  rubyforge_project:
68
- rubygems_version: 1.5.2
117
+ rubygems_version: 1.7.2
69
118
  signing_key:
70
119
  specification_version: 3
71
120
  summary: A ripl plugin for multi-line eval.