Skip to content

Commit

Permalink
Add a auto_indent option to IRB::Formatter
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.macosforge.org/repository/ruby/DietRB/trunk@4855 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
alloy committed Oct 31, 2010
1 parent 7deea95 commit 01fdf4c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 35 deletions.
30 changes: 19 additions & 11 deletions lib/irb/formatter.rb
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
67 changes: 43 additions & 24 deletions spec/formatter_spec.rb
Expand Up @@ -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

0 comments on commit 01fdf4c

Please sign in to comment.