[macruby-changes] [4862] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sun Oct 31 16:03:20 PDT 2010
Revision: 4862
http://trac.macosforge.org/projects/ruby/changeset/4862
Author: eloy.de.enige at gmail.com
Date: 2010-10-31 16:03:17 -0700 (Sun, 31 Oct 2010)
Log Message:
-----------
Update DietRB to r4861, which adds auto-indentation.
Revision Links:
--------------
http://trac.macosforge.org/projects/ruby/changeset/4861
Modified Paths:
--------------
MacRuby/trunk/lib/irb/context.rb
MacRuby/trunk/lib/irb/deprecated.rb
MacRuby/trunk/lib/irb/driver/tty.rb
MacRuby/trunk/lib/irb/ext/colorize.rb
MacRuby/trunk/lib/irb/formatter.rb
MacRuby/trunk/lib/irb/source.rb
MacRuby/trunk/spec/dietrb/context_spec.rb
MacRuby/trunk/spec/dietrb/driver/readline_spec.rb
MacRuby/trunk/spec/dietrb/driver/tty_spec.rb
MacRuby/trunk/spec/dietrb/formatter_spec.rb
Modified: MacRuby/trunk/lib/irb/context.rb
===================================================================
--- MacRuby/trunk/lib/irb/context.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/context.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -11,13 +11,14 @@
class Context
IGNORE_RESULT = :irb_ignore_result
- attr_reader :object, :binding, :line, :source
+ attr_reader :object, :binding, :line, :level, :source
attr_accessor :formatter
def initialize(object, explicit_binding = nil)
@object = object
@binding = explicit_binding || object.instance_eval { binding }
@line = 1
+ @level = 0
clear_buffer
@last_result_assigner = __evaluate__("_ = nil; proc { |val| _ = val }")
@@ -59,10 +60,17 @@
# But at code block indentation level 0, `quit' means exit the runloop:
#
# process_line("quit") # => false
+ #
+ # If re-indenting the line results in a new line, the reformatted line and
+ # prompt are yielded to the optional block. This happens *before* the line
+ # is actually processed, so the caller (driver) has the opportunity to
+ # update the last printed line.
def process_line(line)
- @source << line
+ prompt_and_line = formatter.reindent_last_line(self) { @source << line }
+ yield(*prompt_and_line) if prompt_and_line && block_given?
+
return false if @source.terminate?
-
+
if @source.syntax_error?
output(formatter.syntax_error(@line, @source.syntax_error))
@source.pop
@@ -71,22 +79,27 @@
clear_buffer
end
@line += 1
+ @level = source.level
true
end
+ def driver
+ IRB::Driver.current
+ end
+
# Output is directed to the IRB::Driver.current driver’s output if a
# current driver is available. Otherwise it’s simply printed to $stdout.
def output(string)
- if driver = IRB::Driver.current
+ if driver = self.driver
driver.output.puts(string)
else
puts(string)
end
end
- def prompt
- formatter.prompt(self)
+ def prompt(ignore_auto_indent = false)
+ formatter.prompt(self, ignore_auto_indent)
end
def input_line(line)
Modified: MacRuby/trunk/lib/irb/deprecated.rb
===================================================================
--- MacRuby/trunk/lib/irb/deprecated.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/deprecated.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -1,5 +1,6 @@
module IRB
def self.deprecated(message, caller)
+ return unless $DEBUG
caller = caller.first.split(':')[0..-2].join(':')
warn "[!] Deprecation warning from #{caller}: #{message}"
end
@@ -31,6 +32,9 @@
when :PROMPT_MODE
message = "use `IRB.formatter.prompt = :#{value.downcase}'"
IRB.formatter.prompt = "#{value.to_s.downcase}".to_sym
+ when :AUTO_INDENT
+ message = "use `IRB.formatter.auto_indent = #{value}'"
+ IRB.formatter.auto_indent = value
when :USE_READLINE
message = "for now DietRB only has a readline module"
when :SAVE_HISTORY
@@ -40,4 +44,4 @@
value
end
end
-end
\ No newline at end of file
+end
Modified: MacRuby/trunk/lib/irb/driver/tty.rb
===================================================================
--- MacRuby/trunk/lib/irb/driver/tty.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/driver/tty.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -3,6 +3,11 @@
module IRB
module Driver
class TTY
+ move_one_line_up = "\e[1A"
+ move_to_begin_of_line = "\r"
+ clear_to_end_of_line = "\e[0K"
+ CLEAR_LAST_LINE = move_one_line_up + move_to_begin_of_line + clear_to_end_of_line
+
attr_reader :input, :output, :context_stack
def initialize(input = $stdin, output = $stdout)
@@ -14,7 +19,7 @@
def context
@context_stack.last
end
-
+
def readline
@output.print(context.prompt)
@input.gets
@@ -27,6 +32,17 @@
context.clear_buffer
""
end
+
+ def update_last_line(prompt, reformatted_line)
+ @output.print CLEAR_LAST_LINE
+ @output.puts("#{prompt}#{reformatted_line}")
+ end
+
+ def process_input(line)
+ context.process_line(line) do |prompt, line|
+ update_last_line(prompt, line)
+ end
+ end
# Feeds input into a given context.
#
@@ -35,7 +51,8 @@
def run(context)
@context_stack << context
while line = consume
- break unless context.process_line(line)
+ continue = process_input(line)
+ break unless continue
end
ensure
@context_stack.pop
Modified: MacRuby/trunk/lib/irb/ext/colorize.rb
===================================================================
--- MacRuby/trunk/lib/irb/ext/colorize.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/ext/colorize.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -169,7 +169,7 @@
Ripper.lex(str).map { |_, type, token| colorize_token(type, token) }.join
end
- def prompt(context)
+ def prompt(context, ignore_auto_indent = false, level = nil)
colorize_token(:prompt, super)
end
@@ -183,4 +183,4 @@
end
end
-IRB.formatter = IRB::ColoredFormatter.new
\ No newline at end of file
+IRB.formatter = IRB::ColoredFormatter.new
Modified: MacRuby/trunk/lib/irb/formatter.rb
===================================================================
--- MacRuby/trunk/lib/irb/formatter.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/formatter.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -14,26 +14,35 @@
SIMPLE_PROMPT = ">> "
NO_PROMPT = ""
RESULT_PREFIX = "=>"
+ INDENTATION = " "
SYNTAX_ERROR = "SyntaxError: compile error\n(irb):%d: %s"
- SOURCE_ROOT = /^#{File.expand_path('../../../', __FILE__)}/
+ SOURCE_ROOT = Regexp.new("^#{File.expand_path('../../../', __FILE__)}")
attr_writer :prompt
attr_accessor :inspect
+ attr_accessor :auto_indent
attr_reader :filter_from_backtrace
def initialize
- @prompt = :default
- @inspect = true
+ @prompt = :default
+ @inspect = true
+ @auto_indent = true
@filter_from_backtrace = [SOURCE_ROOT]
end
+
+ def indentation(level)
+ INDENTATION * level
+ end
- def prompt(context)
- case @prompt
- when :default then DEFAULT_PROMPT % [context.object.inspect, context.line, context.source.level]
+ def prompt(context, ignore_auto_indent = false, level = nil)
+ level ||= context.level
+ prompt = case @prompt
+ when :default then DEFAULT_PROMPT % [context.object.inspect, context.line, level]
when :simple then SIMPLE_PROMPT
else
NO_PROMPT
end
+ @auto_indent && !ignore_auto_indent ? "#{prompt}#{indentation(level)}" : prompt
end
def inspect_object(object)
@@ -42,12 +51,37 @@
result.strip!
result
else
- address = object.__id__ * 2
- address += 0x100000000 if address < 0
- "#<#{object.class}:0x%x>" % address
+ minimal_inspect_object(object)
end
end
-
+
+ def minimal_inspect_object(object)
+ address = object.__id__ * 2
+ address += 0x100000000 if address < 0
+ "#<#{object.class}:0x%x>" % address
+ end
+
+ def reindent_last_line(context)
+ unless @auto_indent
+ yield
+ nil
+ else
+ source = context.source
+ old_level = source.level
+ yield
+ if line = source.buffer[-1]
+ # only if the level raises do we use the new value
+ level = source.level < old_level ? source.level : old_level
+ new_line = "#{indentation(level)}#{line.lstrip}"
+ # don't return anything if the new line and level are the same
+ unless line == new_line && level == old_level
+ source.buffer[-1] = new_line
+ [prompt(context, true, level), new_line]
+ end
+ end
+ end
+ end
+
def result(object)
"#{RESULT_PREFIX} #{inspect_object(object)}"
end
@@ -69,4 +103,4 @@
end
end
-IRB.formatter = IRB::Formatter.new
\ No newline at end of file
+IRB.formatter = IRB::Formatter.new
Modified: MacRuby/trunk/lib/irb/source.rb
===================================================================
--- MacRuby/trunk/lib/irb/source.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/lib/irb/source.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -16,7 +16,7 @@
# Adds a source line to the buffer and flushes the cached reflection.
def <<(source)
- source = source.strip
+ source = source.rstrip
unless source.empty?
@reflection = nil
@buffer << source
Modified: MacRuby/trunk/spec/dietrb/context_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/context_spec.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/spec/dietrb/context_spec.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -117,28 +117,43 @@
@output = setup_current_driver.output
@context = IRB::Context.new(main)
@context.extend(InputStubMixin)
+ @context.formatter.auto_indent = true
end
+
+ after do
+ @context.formatter.auto_indent = false
+ end
it "adds the received code to the source buffer" do
@context.process_line("def foo")
@context.process_line("p :ok")
- @context.source.to_s.should == "def foo\np :ok"
+ @context.source.to_s.should == "def foo\n p :ok"
end
- it "clears the source buffer" do
- @context.process_line("def foo")
- @context.clear_buffer
- @context.source.to_s.should == ""
+ it "yields the line if it changed, *after* reindenting" do
+ prompt_and_line = nil
+ @context.process_line("def foo") { |p, l| prompt_and_line = [p, l] }
+ prompt_and_line.should == nil
+ @context.process_line("p :ok") { |p, l| prompt_and_line = [p, l] }
+ prompt_and_line.should == ["irb(main):002:1> ", " p :ok"]
end
-
- it "increases the current line number" do
+
+ it "increases the current line number, *after* yielding the new re-indented line" do
@context.line.should == 1
@context.process_line("def foo")
@context.line.should == 2
- @context.process_line("p :ok")
+ @context.process_line("p :ok")
@context.line.should == 3
end
+ it "increases the current source level, *after* yielding the new re-indented line" do
+ @context.level.should == 0
+ @context.process_line("def foo")
+ @context.level.should == 1
+ @context.process_line("end") { |_| @context.level.should == 1 }
+ @context.level.should == 0
+ end
+
it "evaluates the buffered source once it's a valid code block" do
def @context.evaluate(source); @evaled = source; end
@@ -147,7 +162,7 @@
@context.process_line("end; p foo")
source = @context.instance_variable_get(:@evaled)
- source.to_s.should == "def foo\n:ok\nend; p foo"
+ source.to_s.should == "def foo\n :ok\nend; p foo"
end
it "prints that a syntax error occurred on the last line and reset the buffer to the previous line" do
Modified: MacRuby/trunk/spec/dietrb/driver/readline_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/driver/readline_spec.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/spec/dietrb/driver/readline_spec.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -41,8 +41,13 @@
@driver = IRB::Driver::Readline.new(InputStub.new, OutputStub.new)
@context = IRB::Context.new(Object.new)
@driver.context_stack << @context
+ Readline.clear_printed!
end
+ after do
+ @context.formatter.auto_indent = false
+ end
+
it "is a subclass of IRB::Driver::TTY" do
IRB::Driver::Readline.superclass.should == IRB::Driver::TTY
end
@@ -57,10 +62,25 @@
end
it "reads a line through the Readline module" do
- Readline.stub_input "nom nom nom"
+ Readline.stub_input("nom nom nom")
@driver.readline.should == "nom nom nom"
end
+ it "prints a prompt" do
+ @context.process_line("def foo")
+ Readline.stub_input("nom nom nom")
+ @driver.readline
+ Readline.printed.should == @context.prompt
+ end
+
+ it "prints a prompt with indentation if it's configured" do
+ @context.formatter.auto_indent = true
+ @context.process_line("def foo")
+ Readline.stub_input("nom nom nom")
+ @driver.readline
+ Readline.printed[-2,2].should == " "
+ end
+
it "tells the Readline module to use the history" do
Readline.use_history = false
Readline.stub_input "nom nom nom"
Modified: MacRuby/trunk/spec/dietrb/driver/tty_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/driver/tty_spec.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/spec/dietrb/driver/tty_spec.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -1,21 +1,36 @@
require File.expand_path('../../spec_helper', __FILE__)
require 'irb/driver/tty'
+main = self
+
describe "IRB::Driver::TTY" do
before do
@driver = IRB::Driver::TTY.new(InputStub.new, OutputStub.new)
- @context = IRB::Context.new(Object.new)
+ @context = IRB::Context.new(main)
@driver.context_stack << @context
end
-
+
+ after do
+ @context.formatter.auto_indent = false
+ end
+
it "prints the prompt and reads a line of input" do
- @driver.input.stub_input "calzone"
+ @context.process_line("def foo")
+ @driver.input.stub_input("calzone")
@driver.readline.should == "calzone"
@driver.output.printed.should == @context.prompt
end
+
+ it "prints a prompt with indentation if it's configured" do
+ @context.formatter.auto_indent = true
+ @context.process_line("def foo")
+ @driver.input.stub_input("calzone")
+ @driver.readline
+ @driver.output.printed[-2,2].should == " "
+ end
it "consumes input" do
- @driver.input.stub_input "calzone"
+ @driver.input.stub_input("calzone")
@driver.consume.should == "calzone"
end
@@ -25,6 +40,22 @@
@driver.consume.should == ""
@context.source.to_s.should == ""
end
+
+ it "feeds the input into the context" do
+ @driver.process_input("def foo")
+ @context.source.to_s.should == "def foo"
+ end
+
+ it "updates the previously printed line on the console, if a change to the input occurs (such as re-indenting)" do
+ @context.formatter.auto_indent = true
+ @driver.process_input("def foo")
+ @driver.process_input("p :ok")
+ @driver.process_input(" end")
+ @driver.output.printed.strip.should == [
+ IRB::Driver::TTY::CLEAR_LAST_LINE + "irb(main):002:1> p :ok",
+ IRB::Driver::TTY::CLEAR_LAST_LINE + "irb(main):003:0> end"
+ ].join("\n")
+ end
end
describe "IRB::Driver::TTY, when starting the runloop" do
@@ -36,7 +67,7 @@
it "makes the given context the current one, for this driver, for the duration of the runloop" do
$from_context = nil
- @driver.input.stub_input "$from_context = IRB::Driver.current.context"
+ @driver.input.stub_input("$from_context = IRB::Driver.current.context")
@driver.run(@context)
$from_context.should == @context
IRB::Driver.current.context.should == nil
@@ -44,7 +75,7 @@
it "feeds input into a given context" do
$from_context = false
- @driver.input.stub_input "$from_context = true", "exit"
+ @driver.input.stub_input("$from_context = true", "exit")
@driver.run(@context)
$from_context.should == true
end
@@ -52,7 +83,7 @@
it "makes sure there's a global output redirector while running a context" do
before = $stdout
$from_context = nil
- @driver.input.stub_input "$from_context = $stdout", "exit"
+ @driver.input.stub_input("$from_context = $stdout", "exit")
@driver.run(@context)
$from_context.class == IRB::Driver::OutputRedirector
$stdout.should == before
@@ -67,4 +98,4 @@
# irb(o)
# IRBRan.should == o
# end
-# end
\ No newline at end of file
+# end
Modified: MacRuby/trunk/spec/dietrb/formatter_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/formatter_spec.rb 2010-10-31 22:58:07 UTC (rev 4861)
+++ MacRuby/trunk/spec/dietrb/formatter_spec.rb 2010-10-31 23:03:17 UTC (rev 4862)
@@ -6,14 +6,15 @@
before do
@formatter = IRB::Formatter.new
@context = IRB::Context.new(main)
+ @formatter.auto_indent = false
end
it "returns a prompt string, displaying line number and code indentation level" do
@formatter.prompt(@context).should == "irb(main):001:0> "
@context.instance_variable_set(:@line, 23)
@formatter.prompt(@context).should == "irb(main):023:0> "
- @context.source << "def foo"
- @formatter.prompt(@context).should == "irb(main):023:1> "
+ @context.process_line("def foo")
+ @formatter.prompt(@context).should == "irb(main):024:1> "
end
it "describes the context's object in the prompt" do
@@ -77,4 +78,61 @@
@formatter.syntax_error(2, "syntax error, unexpected '}'").should ==
"SyntaxError: compile error\n(irb):2: syntax error, unexpected '}'"
end
-end
\ No newline at end of file
+
+ it "always skips re-indenting the last line in a Source#buffer if `auto_indent' is turned off" do
+ @context.source << "class A"
+ @formatter.reindent_last_line(@context) { @context.source << "def foo" }.should == nil
+ @context.source.buffer.last.should == "def foo"
+ end
+
+ describe "with auto-indentation" do
+ before do
+ @formatter.auto_indent = true
+ end
+
+ it "returns the whitespace to append to the prompt, based on the given level" do
+ @formatter.indentation(0).should == ""
+ @formatter.indentation(1).should == " "
+ @formatter.indentation(2).should == " "
+ end
+
+ it "pads the prompt, based on the source level" do
+ @formatter.prompt(@context).should == "irb(main):001:0> "
+ @context.process_line("class A")
+ @formatter.prompt(@context).should == "irb(main):002:1> "
+ @context.process_line("def foo")
+ @formatter.prompt(@context).should == "irb(main):003:2> "
+ end
+
+ it "does not pad the prompt if it's explicitely specified" do
+ @context.process_line("class A")
+ @formatter.prompt(@context, true).should == "irb(main):002:1> "
+ end
+
+ it "reindents the last line in a Source#buffer after execution of the block, and returns the new line" do
+ # the line number in the prompt is irrelevant for this test
+ lines = [
+ ["\tclass A", ["irb(main):001:0> ", "class A"]],
+ ["def foo", ["irb(main):001:1> ", " def foo"]],
+ [" end", ["irb(main):001:1> ", " end"]],
+ [" end", ["irb(main):001:0> ", "end"]]
+ ]
+ lines.each do |line, expected_prompt_and_line|
+ @formatter.reindent_last_line(@context) do
+ @context.source << line
+ end.should == expected_prompt_and_line
+ end
+ @context.source.to_s.should == lines.map { |x| x[1][1] }.join("\n")
+ end
+
+ it "returns nil if the last line was not reindented and the level didn't change" do
+ @context.source << "class A"
+ @formatter.reindent_last_line(@context) { @context.source << " def foo" }.should == nil
+ @formatter.reindent_last_line(@context) { @context.source << " end" }.should_not == nil
+ end
+
+ it "returns nil if the source buffer is empty" do
+ @formatter.reindent_last_line(@context) {}.should == nil
+ end
+ end
+end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20101031/2c9f8c39/attachment-0001.html>
More information about the macruby-changes
mailing list