From 01fdf4c2f031b6f7d334f589d515dab266da343a Mon Sep 17 00:00:00 2001 From: Eloy Duran Date: Sun, 31 Oct 2010 22:51:32 +0000 Subject: [PATCH] Add a auto_indent option to IRB::Formatter git-svn-id: http://svn.macosforge.org/repository/ruby/DietRB/trunk@4855 23306eb0-4c56-4727-a40e-e92c0eb68959 --- lib/irb/formatter.rb | 30 ++++++++++++------- spec/formatter_spec.rb | 67 +++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/lib/irb/formatter.rb b/lib/irb/formatter.rb index 1277502..efc9ce6 100644 --- a/lib/irb/formatter.rb +++ b/lib/irb/formatter.rb @@ -14,31 +14,34 @@ class Formatter SIMPLE_PROMPT = ">> " NO_PROMPT = "" RESULT_PREFIX = "=>" + INDENTATION = " " SYNTAX_ERROR = "SyntaxError: compile error\n(irb):%d: %s" 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 = false @filter_from_backtrace = [SOURCE_ROOT] end def indentation(level) - ' ' * level + INDENTATION * level end - def prompt(context, indent = false) + def prompt(context, ignore_auto_indent = false) prompt = case @prompt when :default then DEFAULT_PROMPT % [context.object.inspect, context.line, context.level] when :simple then SIMPLE_PROMPT else NO_PROMPT end - indent ? (prompt + indentation(context.level)) : prompt + @auto_indent && !ignore_auto_indent ? (prompt + indentation(context.level)) : prompt end def inspect_object(object) @@ -58,12 +61,17 @@ def minimal_inspect_object(object) end def reindent_last_line_in_source(source) - old_level = source.level - yield - line = source.buffer[-1] - new_line = indentation(source.level < old_level ? source.level : old_level) - new_line += line.lstrip - source.buffer[-1] = new_line unless new_line == line + unless @auto_indent + yield + nil + else + old_level = source.level + yield + line = source.buffer[-1] + new_line = indentation(source.level < old_level ? source.level : old_level) + new_line += line.lstrip + source.buffer[-1] = new_line unless new_line == line + end end def result(object) diff --git a/spec/formatter_spec.rb b/spec/formatter_spec.rb index 420c04d..1d84ae1 100644 --- a/spec/formatter_spec.rb +++ b/spec/formatter_spec.rb @@ -78,34 +78,53 @@ def object.__id__; 2158110700; end "SyntaxError: compile error\n(irb):2: syntax error, unexpected '}'" end - it "pads the prompt, with indentation whitespace based on the source level, if requested" do - @formatter.prompt(@context, true).should == "irb(main):001:0> " + 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_in_source(@context.source) { @context.source << "def foo" }.should == nil + @context.source.buffer.last.should == "def foo" + end - @context.process_line("class A") - @formatter.prompt(@context, true).should == "irb(main):002:1> " - @formatter.prompt(@context).should == "irb(main):002:1> " + describe "with auto-indentation" do + before do + @formatter.auto_indent = true + end - @context.process_line("def foo") - @formatter.prompt(@context, true).should == "irb(main):003:2> " - @formatter.prompt(@context).should == "irb(main):003:2> " - 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 "reindents the last line in a Source#buffer after execution of the block, and returns the new line" do - source = @context.source - lines = [ - ["\tclass A", "class A"], - ["def foo", " def foo"], - [" end", " end"], - [" end", "end"] - ] - lines.each do |line, expected_new_line| - @formatter.reindent_last_line_in_source(source) { source << line }.should == expected_new_line + 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 - source.to_s.should == lines.map(&:last).join("\n") - end - it "returns nil if the last line was not reindented" do - @context.source << "class A" - @formatter.reindent_last_line_in_source(@context.source) { @context.source << " def foo" }.should == nil + 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 + source = @context.source + lines = [ + ["\tclass A", "class A"], + ["def foo", " def foo"], + [" end", " end"], + [" end", "end"] + ] + lines.each do |line, expected_new_line| + @formatter.reindent_last_line_in_source(source) { source << line }.should == expected_new_line + end + source.to_s.should == lines.map(&:last).join("\n") + end + + it "returns nil if the last line was not reindented" do + @context.source << "class A" + @formatter.reindent_last_line_in_source(@context.source) { @context.source << " def foo" }.should == nil + end end end