<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>Support/lib/rbeautify/config/ruby.rb</filename>
    </added>
    <added>
      <filename>Support/lib/rbeautify/language.rb</filename>
    </added>
    <added>
      <filename>Support/spec/fixtures/ruby.yml</filename>
    </added>
    <added>
      <filename>Support/spec/rbeautify/config/ruby_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -15,7 +15,7 @@ begin
   require File.join(ENV['TM_BUNDLE_SUPPORT'], 'lib', 'rbeautify')
 
   source = STDIN.read
-  dest = RBeautify.beautify_string(source)
+  dest = RBeautify.beautify_string(:ruby, source)
   unless dest == source
     STDOUT.write(dest)
   end</diff>
      <filename>Commands/Beautify Ruby.tmCommand</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@
 
 =begin
 /***************************************************************************
- *   Copyright (C) 2008, Paul Lutus, Joel Chippindale                      *
+ *   Copyright (C) 2008, Joel Chippindale, Paul Lutus                      *
  *                                                                         *
  *   This program is free software: you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -22,25 +22,26 @@
 
 require File.dirname(__FILE__) + '/rbeautify/block.rb'
 require File.dirname(__FILE__) + '/rbeautify/block_matcher.rb'
+require File.dirname(__FILE__) + '/rbeautify/language.rb'
+require File.dirname(__FILE__) + '/rbeautify/config/ruby.rb'
 require File.dirname(__FILE__) + '/rbeautify/line.rb'
 
 module RBeautify
 
-  def RBeautify.beautify_string(source)
+  def RBeautify.beautify_string(language, source)
     dest = &quot;&quot;
     stack = []
 
+    unless language.is_a? RBeautify::Language
+      language = RBeautify::Language.language(language)
+    end
+
     source.split(&quot;\n&quot;).each do |line_content|
-      line = RBeautify::Line.new(line_content, stack)
+      line = RBeautify::Line.new(language, line_content, stack)
       dest += line.format + &quot;\n&quot;
       stack = line.stack
     end
 
-    # TODO: Decide how to inform users of indentation error
-    # if(!stack.empty?)
-    #   raise &quot;#{path}: Indentation error&quot;
-    # end
-
     return dest
   end
 </diff>
      <filename>Support/lib/rbeautify.rb</filename>
    </modified>
    <modified>
      <diff>@@ -32,11 +32,8 @@ module RBeautify
       block_matcher.end_is_implicit?
     end
 
-    def ==(other)
-      self.block_matcher == other.block_matcher &amp;&amp;
-        self.after_start_match == other.after_start_match &amp;&amp;
-        self.start_offset == other.start_offset &amp;&amp;
-        self.end_offset == other.end_offset
+    def name
+      block_matcher.name
     end
   end
 </diff>
      <filename>Support/lib/rbeautify/block.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,77 +2,18 @@ module RBeautify
 
   class BlockMatcher
 
-    attr_accessor :starts, :ends, :options
+    attr_accessor :language, :name, :starts, :ends, :options
 
-    def initialize(starts, ends, options = {})
+    def initialize(language, name, starts, ends, options = {})
+      self.language = language
+      self.name = name
       self.starts = starts
       self.ends = ends.nil? ? starts : ends
-
-      if options[:nest_except]
-        options[:nest_except] = options[:nest_except].map{ |m| m == :self ? self : m }
-      end
-
       self.options = options
     end
 
-    MATCHERS = [
-      PROGRAM_END_MATCHER         = BlockMatcher.new(/^__END__$/, false, :format =&gt; false),
-      MULTILINE_COMMENT_MATCHER   = BlockMatcher.new(/^=begin/, /^=end/, :format =&gt; false),
-
-      STANDARD_MATCHER            = BlockMatcher.new(/((^(module|class|def|else))|\bdo)\b/,
-                                                     /(^|;\s*)(end|rescue|ensure)\b/),
-
-      IMPLICIT_END_MATCHER        = BlockMatcher.new(/^(public|protected|private)$/,
-                                                     /^(public|protected|private)(\s*)?(#.*)?$/,
-                                                     :end =&gt; :implicit),
-
-      MORE_MATCHERS               = BlockMatcher.new(/(=\s+|^)(until|for|while)\b/, /(^|;\s*)end\b/),
-
-      BEGIN_MATCHERS              = BlockMatcher.new(/((=\s+|^)begin)|(^(ensure|rescue))\b/,
-                                                     /(^|;\s*)(end|rescue|ensure)\b/),
-
-      IF_AND_CASE_MATCHER         = BlockMatcher.new(/(((^|;\s*)(if|elsif|case|unless))|(\b(when|then)))\b/,
-                                                     /((^|;\s*)(elsif|else|end)|\b(when|then))\b/),
-
-      CURLY_BRACKET_MATCHER       = BlockMatcher.new(/\{\s*/, /\}/,
-                                                     :indent_end_line =&gt; Proc.new { |block| block.end_offset != 0 },
-                                                     :indent_size =&gt; Proc.new { |block| block.start_offset + block.start_match.length unless block.after_start_match.empty? }),
-
-      ROUND_BRACKET_MATCHER       = BlockMatcher.new(/\(\s*/, /\)/,
-                                                     :indent_end_line =&gt; Proc.new { |block| block.end_offset != 0 },
-                                                     :indent_size =&gt; Proc.new { |block| block.start_offset + block.start_match.length unless block.after_start_match.empty? }),
-
-      SQUARE_BRACKET_MATCHER      = BlockMatcher.new(/\[\s*/, /\]/,
-                                                     :indent_end_line =&gt; Proc.new { |block| block.end_offset != 0 },
-                                                     :indent_size =&gt; Proc.new { |block| block.start_offset + block.start_match.length unless block.after_start_match.empty? }),
-
-      DOUBLE_QUOTE_STRING_MATCHER = BlockMatcher.new(/&quot;/, /&quot;/, :format =&gt; false, :escape_character =&gt; true),
-      SINGLE_QUOTE_STRING_MATCHER = BlockMatcher.new(/'/, /'/, :format =&gt; false, :escape_character =&gt; true),
-
-      REGEX_MATCHER               = BlockMatcher.new(/(^|(.*,\s*))\//, /\//,
-                                                     :format =&gt; false,
-                                                     :escape_character =&gt; true),
-
-      BACK_TICK_MATCHER           = BlockMatcher.new(/`/, /`/, :format =&gt; false, :escape_character =&gt; true),
-
-      COMMENT_MATCHER             = BlockMatcher.new(
-        /(\s*)?#/,
-        /$/,
-        :format =&gt; false,
-        :nest_except =&gt; [DOUBLE_QUOTE_STRING_MATCHER, SINGLE_QUOTE_STRING_MATCHER, REGEX_MATCHER, BACK_TICK_MATCHER]
-      ),
-
-      CONTINUING_LINE_MATCHER     = BlockMatcher.new(
-        /(,|\.|\+|-|=\&gt;|&amp;&amp;|\|\||\\|==|\s\?|:)(\s*)?(#.*)?$/,
-        /(^|(,|\.|\+|-|=\&gt;|&amp;&amp;|\|\||\\|==|\s\?|:)(\s*)?)(#.*)?$/,
-        :indent_end_line =&gt; true,
-        :negate_ends_match =&gt; true,
-        :nest_except =&gt; [:self, CURLY_BRACKET_MATCHER, ROUND_BRACKET_MATCHER, SQUARE_BRACKET_MATCHER]
-      )
-    ]
-
     class &lt;&lt; self
-      def calculate_stack(string, stack = [], index = 0)
+      def calculate_stack(language, string, stack = [], index = 0)
         stack = stack.dup
         current_block = stack.last
         new_block = nil
@@ -88,7 +29,7 @@ module RBeautify
           after_match = nil
         end
 
-        MATCHERS.each do |matcher|
+        language.matchers.each do |matcher|
           if matcher.can_nest?(current_block)
             started_block_candidate = matcher.block(string, index)
             if started_block_candidate &amp;&amp;
@@ -105,12 +46,17 @@ module RBeautify
         if after_match
           new_index = string.length - after_match.length
           if block_ended
-            while ((block = stack.pop) &amp;&amp; block.end_is_implicit? &amp;&amp; !block.block_matcher.explicit_end_match?(string)); end
+            while (
+                (block = stack.pop) &amp;&amp;
+                block.end_is_implicit? &amp;&amp;
+                !block.block_matcher.explicit_end_match?(string)
+              )
+            end
           end
           if new_block
             stack &lt;&lt; new_block
           end
-          stack = calculate_stack(after_match, stack, new_index)
+          stack = calculate_stack(language, after_match, stack, new_index)
         end
 
         stack
@@ -122,7 +68,7 @@ module RBeautify
     end
 
     def indent_size(block)
-      evaluate_option_for_block(:indent_size, block) || 2
+      evaluate_option_for_block(:indent_size, block) || language.indent_size
     end
 
     def format?
@@ -131,7 +77,7 @@ module RBeautify
 
     def can_nest?(parent_block)
       parent_block.nil? ||
-        (parent_block.format? &amp;&amp; (options[:nest_except].nil? || !options[:nest_except].include?(parent_block.block_matcher)))
+        (parent_block.format? &amp;&amp; (options[:nest_except].nil? || !options[:nest_except].include?(parent_block.name)))
     end
 
     def end_is_implicit?</diff>
      <filename>Support/lib/rbeautify/block_matcher.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,9 +5,10 @@ module RBeautify
     # indent_character
     @@indent_character = &quot; &quot;
 
-    attr_accessor :content, :original_stack
+    attr_accessor :content, :original_stack, :language
 
-    def initialize(content, original_stack = [])
+    def initialize(language, content, original_stack = [])
+      self.language = language
       self.content = content
       self.original_stack = original_stack
     end
@@ -29,7 +30,7 @@ module RBeautify
     end
 
     def stack
-      @stack ||= BlockMatcher.calculate_stack(stripped, original_stack)
+      @stack ||= BlockMatcher.calculate_stack(language, stripped, original_stack)
     end
 
     private</diff>
      <filename>Support/lib/rbeautify/line.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,261 +3,73 @@ require File.dirname(__FILE__) + '/../spec_helper.rb'
 describe RBeautify::BlockMatcher do
 
   describe '.calculate_stack' do
+    before(:each) do
+      @ruby = RBeautify::Language.language(:ruby)
+    end
 
     it 'should not match de' do
-      RBeautify::BlockMatcher.calculate_stack('de foo').should be_empty
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'de foo').should be_empty
     end
 
     it 'should match def' do
-      RBeautify::BlockMatcher.calculate_stack('def foo').size.should == 1
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'def foo').size.should == 1
     end
 
     it 'should match nested blocks' do
-      RBeautify::BlockMatcher.calculate_stack('if {').size.should == 2
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'if {').size.should == 2
     end
 
     it 'should match nested blocks (taking into account ends)' do
-      RBeautify::BlockMatcher.calculate_stack('if {}').size.should == 1
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'if {}').size.should == 1
     end
 
     it 'should match nested blocks (taking into account ends)' do
-      RBeautify::BlockMatcher.calculate_stack('def foo(bar = {})').size.should == 1
-      RBeautify::BlockMatcher.calculate_stack('def foo(bar = {})').first.block_matcher.should ==
-        RBeautify::BlockMatcher::STANDARD_MATCHER
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'def foo(bar = {})').size.should == 1
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'def foo(bar = {})').first.block_matcher.should ==
+        @ruby.matcher(:standard)
     end
 
     it 'should not change if no started or ended blocks' do
-      current_stack = [RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'def', ' foo')]
-      RBeautify::BlockMatcher.calculate_stack('a = 3', current_stack).should == current_stack
+      current_stack = [RBeautify::Block.new(@ruby.matcher(:standard), 0, 'def', ' foo')]
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'a = 3', current_stack).should == current_stack
     end
 
     it 'should remove block if top of stack ends' do
+      surrounding_block = RBeautify::Block.new(@ruby.matcher(:standard), 0, 'class', ' Foo')
       current_stack = [
-        RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'class', ' Foo'),
-        RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'def', ' foo')
+        surrounding_block,
+        RBeautify::Block.new(@ruby.matcher(:standard), 0, 'def', ' foo')
       ]
-      RBeautify::BlockMatcher.calculate_stack('end', current_stack).should ==
-        [RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'class', ' Foo')]
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'end', current_stack, 0).should == [surrounding_block]
     end
 
     it 'should remove two blocks if top of stack ends implicitly' do
       current_stack = [
-        RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'class', ' Foo'),
-        RBeautify::Block.new(RBeautify::BlockMatcher::IMPLICIT_END_MATCHER, 0, 'private', '')
+        RBeautify::Block.new(@ruby.matcher(:standard), 0, 'class', ' Foo'),
+        RBeautify::Block.new(@ruby.matcher(:implicit_end), 0, 'private', '')
       ]
-      RBeautify::BlockMatcher.calculate_stack('end', current_stack).should == []
+      RBeautify::BlockMatcher.calculate_stack(@ruby, 'end', current_stack, 0).should == []
     end
   end
 
   describe '#can_nest?' do
-
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/).should be_can_nest(nil) }
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/).should be_can_nest(mock('block', :block_matcher =&gt; mock('matcher'), :format? =&gt; true)) }
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/).should_not be_can_nest(mock('block', :block_matcher =&gt; mock('matcher'), :format? =&gt; false)) }
-
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [RBeautify::BlockMatcher::STANDARD_MATCHER]).should be_can_nest(nil) }
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [RBeautify::BlockMatcher::STANDARD_MATCHER]).should be_can_nest(mock('block', :block_matcher =&gt; mock('matcher'), :format? =&gt; true)) }
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [RBeautify::BlockMatcher::STANDARD_MATCHER]).should_not be_can_nest(mock('block', :block_matcher =&gt; RBeautify::BlockMatcher::STANDARD_MATCHER, :format? =&gt; true)) }
-
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [:self]).should be_can_nest(nil) }
-    it { RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [:self]).should be_can_nest(mock('block', :block_matcher =&gt; RBeautify::BlockMatcher::STANDARD_MATCHER, :format? =&gt; true)) }
-    it 'should not be able to nest self if options do not allow it' do
-      matcher = RBeautify::BlockMatcher.new(/foo/, /bar/, :nest_except =&gt; [:self])
-      matcher.should_not be_can_nest(mock('block', :block_matcher =&gt; matcher, :format? =&gt; true))
-    end
-
-  end
-
-  describe 'class' do
-
-    describe 'STANDARD_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::STANDARD_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '', '')
-      end
-
-      it { @matcher.block('class Foo; end', 0).should == RBeautify::Block.new(@matcher, 0, 'class', ' Foo; end') }
-      it { @matcher.block('module Foo', 0).should == RBeautify::Block.new(@matcher, 0, 'module', ' Foo') }
-      it { @matcher.block('def foo()', 0).should == RBeautify::Block.new(@matcher, 0, 'def', ' foo()') }
-      it { @matcher.block('end Foo', 0).should be_nil }
-
-      it { @matcher.end_match('end', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('; end', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('rescue', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('ensure', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('}', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('foo end', [@current_block], 0).should be_nil }
-
-    end
-
-    describe 'IF_AND_CASE_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::IF_AND_CASE_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, 'if', ' foo')
-      end
-
-      it { @matcher.block('if foo', 0).should == RBeautify::Block.new(@matcher, 0, 'if', ' foo') }
-      it { @matcher.block('case foo', 0).should == RBeautify::Block.new(@matcher, 0, 'case', ' foo') }
-      it { @matcher.block('when foo', 0).should == RBeautify::Block.new(@matcher, 0, 'when', ' foo') }
-      it { @matcher.block('then foo = bar', 0).should == RBeautify::Block.new(@matcher, 0, 'then', ' foo = bar') }
-
-      it { @matcher.end_match('end', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('when', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('then', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('else', [@current_block], 0).should == [0, ''] }
-
-      it { @matcher.end_match('a = 3', [@current_block], 0).should be_nil }
-
-    end
-
-    describe 'CURLY_BRACKET_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::CURLY_BRACKET_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '{', '')
-      end
-
-      it { @matcher.block('{', 0).should == RBeautify::Block.new(@matcher, 0, '{', '') }
-      it { @matcher.block('end', 0).should be_nil }
-
-      it { @matcher.end_match('}', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('end', [@current_block], 0).should be_nil }
-
-    end
-
-    describe 'DOUBLE_QUOTE_STRING_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::DOUBLE_QUOTE_STRING_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '&quot;', 'foo&quot;')
-      end
-
-      it { @matcher.block('a = &quot;foo&quot;', 0).should == RBeautify::Block.new(@matcher, 4, '&quot;', 'foo&quot;') }
-      it { @matcher.block('a = 2', 0).should be_nil }
-
-      it { @matcher.end_match(' bar&quot;', [@current_block], 0).should == [4, ''] }
-      it { @matcher.end_match(' &quot; + bar + &quot;', [@current_block], 0).should == [1, ' + bar + &quot;'] }
-      it { @matcher.end_match('\\\\&quot;', [@current_block], 0).should == [2, ''] }
-      it { @matcher.end_match('\\&quot; still within string&quot;', [@current_block], 0).should == [20, ''] }
-      it { @matcher.end_match('a = 2', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('\\&quot;', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('\\\\\\&quot;', [@current_block], 0).should be_nil }
-
+    before(:each) do
+      @language = mock(RBeautify::Language)
     end
 
-    describe 'SINGLE_QUOTE_STRING_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::SINGLE_QUOTE_STRING_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, &quot;'&quot;, &quot;foo'&quot;)
-      end
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/).should be_can_nest(nil) }
 
-      it { @matcher.block(&quot;describe '#foo?' do&quot;, 0).should == RBeautify::Block.new(@matcher, 9, &quot;'&quot;, &quot;#foo?' do&quot;) }
-      it { @matcher.block('a = 2', 0).should be_nil }
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/).should be_can_nest(mock('block', :format? =&gt; true)) }
 
-      it { @matcher.end_match(&quot;#foo?' do&quot;, [@current_block], 9).should == [14, ' do'] }
-      it { @matcher.end_match('a = 2', [@current_block], 0).should be_nil }
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/).should_not be_can_nest(mock('block', :format? =&gt; false)) }
 
-    end
-
-    describe 'CONTINUING_LINE_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::CONTINUING_LINE_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 8, ',', '')
-      end
-
-      it { @matcher.block('foo :bar,', 0).should == RBeautify::Block.new(@matcher, 8, ',', '') }
-      it { @matcher.block('a = 3 &amp;&amp;', 0).should == RBeautify::Block.new(@matcher, 6, '&amp;&amp;', '') }
-      it { @matcher.block('a = 3 ||', 0).should == RBeautify::Block.new(@matcher, 6, '&amp;&amp;', '') }
-      it { @matcher.block('a = 3 +', 0).should == RBeautify::Block.new(@matcher, 6, '&amp;&amp;', '') }
-      it { @matcher.block('a = 3 -', 0).should == RBeautify::Block.new(@matcher, 6, '&amp;&amp;', '') }
-      it { @matcher.block(&quot;a \\&quot;, 0).should == RBeautify::Block.new(@matcher, 2, '\\', '') }
-      it { @matcher.block('a ?', 0).should == RBeautify::Block.new(@matcher, 1, ' ?', '')  }
-      it { @matcher.block('a ? # some comment', 0).should == RBeautify::Block.new(@matcher, 1, ' ? # some comment', '') }
-      it { @matcher.block('a = 3', 0).should be_nil }
-      it { @matcher.block('a = foo.bar?', 0).should be_nil }
-      it { @matcher.block('# just a comment', 0).should be_nil }
-
-      it { @matcher.end_match('a = 3', [@current_block], 0).should == [0, 'a = 3'] }
-      it { @matcher.end_match('foo :bar,', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('a = 3 &amp;&amp;', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('a = 3 +', [@current_block], 0).should be_nil }
-      it { @matcher.end_match(&quot;a \\&quot;, [@current_block], 0).should be_nil }
-      it { @matcher.end_match('# just a comment', [@current_block], 0).should be_nil }
-      it { @matcher.end_match('#', [@current_block], 0).should be_nil }
-
-    end
-
-    describe 'IMPLICIT_END_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::IMPLICIT_END_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '', '')
-      end
-
-      it { @matcher.block('private', 0).should == RBeautify::Block.new(@matcher, 0, 'private', '') }
-      it { @matcher.block('protected', 0).should == RBeautify::Block.new(@matcher, 0, 'protected', '') }
-      it { @matcher.block('a = 3', 0).should be_nil }
-
-      it { @matcher.end_match('protected', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('protected # some comment', [@current_block], 0).should == [0, ''] }
-      it { @matcher.end_match('a = 3', [@current_block], 0).should be_nil }
-
-      it 'should return both if implicit end from next block in stack' do
-        surrounding_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'def', ' foo')
-        @matcher.end_match('end', [surrounding_block, @current_block], 0).should == [0, '']
-      end
-
-      it 'should return none if no implicit end from next block in stack' do
-        surrounding_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, 'def', ' foo')
-        @matcher.end_match('a = 3', [surrounding_block, @current_block], 0).should be_nil
-      end
-
-    end
-
-    describe 'ROUND_BRACKET_MATCHER' do
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::ROUND_BRACKET_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '(', '')
-      end
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/, :nest_except =&gt; [:bar]).should be_can_nest(nil) }
 
-      it { @matcher.block('a = (foo,', 0).should == RBeautify::Block.new(@matcher, 4, 'a = (', 'foo,') }
-      it { @matcher.block('anything else', 0).should be_nil }
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/, :nest_except =&gt; [:foo]).should be_can_nest(mock('block', :name =&gt; :bar, :format? =&gt; true)) }
 
-      it { @matcher.end_match('foo)', [@current_block], 0).should == [3, ''] }
-      it { @matcher.end_match('a = 3', [@current_block], 0).should be_nil }
-
-    end
-
-    describe 'COMMENT_MATCHER' do
-
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::COMMENT_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 8, '#', ' comment')
-      end
-
-      it { @matcher.block('anything # comment', 0).should == RBeautify::Block.new(@matcher, 8, '#', ' comment') }
-      it { @matcher.block('#', 0).should == RBeautify::Block.new(@matcher, 0, '#', '') }
-      it { @matcher.block('anything else', 0).should be_nil }
-
-      it { @matcher.end_match('anything', [@current_block], 0).should == [8, ''] }
-      it { @matcher.end_match('', [@current_block], 0).should == [0, ''] }
-
-    end
-
-    describe 'REGEX_MATCHER' do
-
-      before(:each) do
-        @matcher = RBeautify::BlockMatcher::REGEX_MATCHER
-        @current_block = RBeautify::Block.new(@matcher, 0, '/', 'foo/')
-      end
-
-      it { @matcher.block('/foo/', 0).should == RBeautify::Block.new(@matcher, 0, '/', 'foo/') }
-      it { @matcher.block(', /foo/', 0).should == RBeautify::Block.new(@matcher, 0, ', /', 'foo/') }
-      it { @matcher.block('1/2', 0).should be_nil }
-      it { @matcher.block('anything else', 0).should be_nil }
-
-      it { @matcher.end_match('foo/', [@current_block], 0).should == [3, ''] }
-      it { @matcher.end_match('', [@current_block], 0).should be_nil }
-
-    end
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/, :nest_except =&gt; [:foo]).should_not be_can_nest(mock('block', :name =&gt; :bar, :format? =&gt; false)) }
 
+    it { RBeautify::BlockMatcher.new(@language, :foo, /foo/, /bar/, :nest_except =&gt; [:bar]).should_not be_can_nest(mock('block', :name =&gt; :bar, :format? =&gt; true)) }
   end
 
 end</diff>
      <filename>Support/spec/rbeautify/block_matcher_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,112 +4,72 @@ describe RBeautify::Line do
 
   describe '#format' do
 
+    before(:each) do
+      @language = mock(RBeautify::Language)
+    end
+
     it 'should just strip with empty stack' do
-      RBeautify::Line.new(' a = 3 ').format.should == &quot;a = 3&quot;
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [])
+      RBeautify::Line.new(@language, ' a = 3 ').format.should == &quot;a = 3&quot;
     end
 
     it 'should indent with existing indent' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new(' a = 3 ', [current_block]).format.should == '  a = 3'
+      current_block = mock(RBeautify::Block, :indent_size =&gt; 2, :format? =&gt; true)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [current_block])
+      RBeautify::Line.new(@language, ' a = 3 ', [current_block]).format.should == '  a = 3'
     end
 
     it 'leave empty lines blank' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new('    ', [current_block]).format.should == ''
+      current_block = mock(RBeautify::Block, :format? =&gt; true)
+      RBeautify::Line.new(@language, '    ', [current_block]).format.should == ''
     end
 
     it 'should remove indent with match to end of block' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new('  end ', [current_block]).format.should == 'end'
-    end
-
-    it 'should remove double indent with match to end of block when end is implicit' do
-      surrounding_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::IMPLICIT_END_MATCHER, 0, '','')
-      RBeautify::Line.new('  end ', [surrounding_block, current_block]).format.should == 'end'
+      current_block = mock(RBeautify::Block, :indent_size =&gt; 2, :format? =&gt; true, :indent_end_line? =&gt; false)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [])
+      RBeautify::Line.new(@language, '  end ', [current_block]).format.should == 'end'
     end
 
-    it 'should leave indent with match to end of block (and indent last line)' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::CONTINUING_LINE_MATCHER, 0, '','')
-      RBeautify::Line.new('  foo ', [current_block]).format.should == '  foo'
+    it 'should not remove indent with match to end of block if indent_end_line? is true' do
+      current_block = mock(RBeautify::Block, :indent_size =&gt; 2, :format? =&gt; true, :indent_end_line? =&gt; true)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [])
+      RBeautify::Line.new(@language, '  foo ', [current_block]).format.should == '  foo'
     end
 
     it 'should leave indent with match to end of block (but no format)' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::DOUBLE_QUOTE_STRING_MATCHER, 0, '','')
-      RBeautify::Line.new('  &quot;', [current_block]).format.should == '  &quot;'
+      current_block = mock(RBeautify::Block, :format? =&gt; false)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [])
+      RBeautify::Line.new(@language, '  &quot;', [current_block]).format.should == '  &quot;'
     end
 
     it 'should leave indent at old stack level with match of new block' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new('class Foo', [current_block]).format.should == '  class Foo'
+      current_block = mock(RBeautify::Block, :indent_size =&gt; 2, :format? =&gt; true)
+      new_block = mock(RBeautify::Block, :format? =&gt; true)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [current_block, new_block])
+      RBeautify::Line.new(@language, 'class Foo', [current_block]).format.should == '  class Foo'
     end
 
     it 'should not change when format is false' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::PROGRAM_END_MATCHER, 0, '','')
-      RBeautify::Line.new(' some content after program has finished. ', [current_block]).format.should ==
+      current_block = mock(RBeautify::Block, :format? =&gt; false)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [current_block])
+      RBeautify::Line.new(@language, ' some content after program has finished. ', [current_block]).format.should ==
         &quot; some content after program has finished. &quot;
     end
 
     it 'should remove indent if a block ends and starts' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::IF_AND_CASE_MATCHER, 0, '','')
-      RBeautify::Line.new(' else ', [current_block]).format.should == 'else'
+      current_block = mock(RBeautify::Block, :format? =&gt; true)
+      new_block = mock(RBeautify::Block, :indent_size =&gt; 2, :format? =&gt; true)
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [new_block])
+      RBeautify::Line.new(@language, ' else ', [current_block]).format.should == 'else'
     end
 
   end
 
   describe '#stack' do
 
-    it 'should keep empty stack if no new block starts' do
-      RBeautify::Line.new(' a = 3 ').stack.should == []
-    end
-
-    it 'should keep stack if no new block starts or ends' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new(' a = 3 ', [current_block]).stack.should == [current_block]
-    end
-
-    it 'should pop block from stack with match to end of block' do
-      current_block= RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      RBeautify::Line.new('  end ', [current_block]).stack.should == []
-    end
-
-    it 'should pop block from stack with match to end of block when format is false' do
-      current_block= RBeautify::Block.new(RBeautify::BlockMatcher::DOUBLE_QUOTE_STRING_MATCHER, 0, '','')
-      RBeautify::Line.new('  foo&quot; ', [current_block]).stack.should == []
-    end
-
-    it 'should pop two blocks from stack with match to end of block when end is implicit' do
-      surrounding_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::IMPLICIT_END_MATCHER, 0, '','')
-      RBeautify::Line.new('  end ', [surrounding_block, current_block]).stack.should == []
-    end
-
-    describe 'add one to stack' do
-
-      it 'should add for &quot;class Foo&quot;' do
-        current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-        RBeautify::Line.new('class Foo', [current_block]).stack.size.should == 2
-        RBeautify::Line.new('class Foo', [current_block]).stack.first.should == current_block
-        RBeautify::Line.new('class Foo', [current_block]).stack.last.block_matcher.should == RBeautify::BlockMatcher::STANDARD_MATCHER
-      end
-
-      it 'should add for &quot;def foo(bar = {})&quot;' do
-        current_block = RBeautify::Block.new(RBeautify::BlockMatcher::STANDARD_MATCHER, 0, '','')
-        RBeautify::Line.new('def foo(bar = {})', [current_block]).stack.size.should == 2
-        RBeautify::Line.new('def foo(bar = {})', [current_block]).stack.first.should == current_block
-        RBeautify::Line.new('def foo(bar = {})', [current_block]).stack.last.block_matcher.should == RBeautify::BlockMatcher::STANDARD_MATCHER
-      end
-
-    end
-
-    it 'should add and remove if a block ends and starts' do
-      current_block = RBeautify::Block.new(RBeautify::BlockMatcher::IF_AND_CASE_MATCHER, 0, '','')
-      RBeautify::Line.new(' else ', [current_block]).stack.size.should == 1
-      RBeautify::Line.new(' else ', [current_block]).stack.last.block_matcher.should == RBeautify::BlockMatcher::STANDARD_MATCHER
-    end
-
-    it 'should keep stack the same if block ends and starts on same line' do
-      RBeautify::Line.new('while (foo = bar); end ', []).stack.should be_empty
+    it 'should return calculated stack' do
+      RBeautify::BlockMatcher.stub!(:calculate_stack =&gt; [])
+      RBeautify::Line.new(@language, ' a = 3 ', []).stack.should == []
     end
 
   end
@@ -117,8 +77,8 @@ describe RBeautify::Line do
   describe 'private methods' do
 
     describe '#stripped' do
-      it { RBeautify::Line.new('     def foo # some comment     ').send(:stripped).should == 'def foo # some comment' }
-      it { RBeautify::Line.new('     &quot;some string&quot;     ').send(:stripped).should == '&quot;some string&quot;' }
+      it { RBeautify::Line.new(@language, '     def foo # some comment     ').send(:stripped).should == 'def foo # some comment' }
+      it { RBeautify::Line.new(@language, '     &quot;some string&quot;     ').send(:stripped).should == '&quot;some string&quot;' }
     end
 
   end</diff>
      <filename>Support/spec/rbeautify/line_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,16 +1 @@
 require 'spec_helper.rb'
-
-fixtures = YAML.load_file(File.dirname(__FILE__) + '/fixtures.yml')
-
-describe RBeautify do
-  fixtures.each do |fixture|
-    it &quot;should #{fixture['name']}&quot; do
-      if fixture['pending']
-        pending fixture['pending']
-      end
-      input = fixture['input']
-      output = fixture['output'] || input
-      RBeautify.beautify_string(input).should == output
-    end
-  end
-end</diff>
      <filename>Support/spec/rbeautify_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,3 +2,70 @@ require 'rubygems'
 require 'spec'
 require 'ruby-debug'
 require File.dirname(__FILE__) + '/../lib/rbeautify.rb'
+
+module RBeautifyMatchers
+  # Adds more descriptive failure messages to the dynamic be_valid matcher
+  class BeBlockLike #:nodoc:
+    def initialize(block_matcher_name, start_offset, start_match, after_start_match)
+      # triggers the standard Spec::Matchers::Be magic, as if the original Spec::Matchers#method_missing had fired
+      @block_matcher_name = block_matcher_name
+      @start_offset = start_offset
+      @start_match = start_match
+      @after_start_match = after_start_match
+    end
+
+    def matches?(target_block)
+      @target_block = target_block
+      return !target_block.nil? &amp;&amp;
+        (expected_string == got_string)
+    end
+
+    def failure_message
+      &quot;expected\n#{expected_string} but got\n#{got_string}&quot;
+    end
+
+    def negative_failure_message
+      &quot;expected to be different from #{expected_string}&quot;
+    end
+
+    def expected_string
+      &quot;name: #{@block_matcher_name}, start_offset: #{@start_offset}, start_match: '#{@start_match}', after_start_match: '#{@after_start_match}'&quot;
+    end
+
+    def got_string
+      &quot;name: #{@target_block.block_matcher.name}, start_offset: #{@target_block.start_offset}, start_match: '#{@target_block.start_match}', after_start_match: '#{@target_block.after_start_match}'&quot;
+    end
+
+    def description
+      &quot;block with&quot;
+    end
+
+  end
+
+  def be_block_like(block_matcher, start_offset, start_match, after_start_match)
+    BeBlockLike.new(block_matcher, start_offset, start_match, after_start_match)
+  end
+end
+
+Spec::Runner.configure do |config|
+  config.include(RBeautifyMatchers)
+end
+
+def run_fixtures_for_language(language)
+
+  fixtures = YAML.load_file(File.dirname(__FILE__) + &quot;/fixtures/#{language}.yml&quot;)
+
+  describe language do
+    fixtures.each do |fixture|
+      it &quot;should #{fixture['name']}&quot; do
+        if fixture['pending']
+          pending fixture['pending']
+        end
+        input = fixture['input']
+        output = fixture['output'] || input
+        RBeautify.beautify_string(language, input).should == output
+      end
+    end
+  end
+
+end</diff>
      <filename>Support/spec/spec_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>Support/spec/fixtures.yml</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>40cdaf23c959b48ca2bbe5967c4dd3d67587bc20</id>
    </parent>
  </parents>
  <author>
    <name>Joel Chippindale</name>
    <email>joel.chippindale@gmail.com</email>
  </author>
  <url>http://github.com/mocoso/code-beautifier.tmbundle/commit/0b796f6e0e3b82ce9cfa8deed2f3204b2f12c565</url>
  <id>0b796f6e0e3b82ce9cfa8deed2f3204b2f12c565</id>
  <committed-date>2009-05-13T21:17:49-07:00</committed-date>
  <authored-date>2009-05-13T21:17:49-07:00</authored-date>
  <message>Separated out definition of ruby formatting</message>
  <tree>66ccc85f60f0e6a15d3f0654c7ba81d8b71c67b7</tree>
  <committer>
    <name>Joel Chippindale</name>
    <email>joel.chippindale@gmail.com</email>
  </committer>
</commit>
