diff options
-rw-r--r-- | activesupport/CHANGELOG.md | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/string.rb | 1 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/indent.rb | 43 | ||||
-rw-r--r-- | activesupport/test/core_ext/string_ext_test.rb | 56 | ||||
-rw-r--r-- | guides/source/active_support_core_extensions.textile | 35 |
5 files changed, 137 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 5fcea299f8..70bd1bf4d3 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Add String#indent. *fxn & Ace Suares* + * Inflections can now be defined per locale. `singularize` and `pluralize` accept locale as an extra argument. *David Celis* * `Object#try` will now return nil instead of raise a NoMethodError if the receiving object does not implement the method, but you can still get the old behavior by using the new `Object#try!` *DHH* diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index fb36262528..ad864765a3 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -10,3 +10,4 @@ require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/string/exclude' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/inquiry' +require 'active_support/core_ext/string/indent' diff --git a/activesupport/lib/active_support/core_ext/string/indent.rb b/activesupport/lib/active_support/core_ext/string/indent.rb new file mode 100644 index 0000000000..afc3032272 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/string/indent.rb @@ -0,0 +1,43 @@ +class String + # Same as +indent+, except it indents the receiver in-place. + # + # Returns the indented string, or +nil+ if there was nothing to indent. + def indent!(amount, indent_string=nil, indent_empty_lines=false) + indent_string = indent_string || self[/^[ \t]/] || ' ' + re = indent_empty_lines ? /^/ : /^(?!$)/ + gsub!(re, indent_string * amount) + end + + # Indents the lines in the receiver: + # + # <<EOS.indent(2) + # def some_method + # some_code + # end + # EOS + # # => + # def some_method + # some_code + # end + # + # The second argument, +indent_string+, specifies which indent string to + # use. The default is +nil+, which tells the method to make a guess by + # peeking at the first indented line, and fallback to a space if there is + # none. + # + # " foo".indent(2) # => " foo" + # "foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar" + # "foo".indent(2, "\t") # => "\t\tfoo" + # + # While +indent_string+ is tipically one space or tab, it may be any string. + # + # The third argument, +indent_empty_lines+, is a flag that says whether + # empty lines should be indented. Default is false. + # + # "foo\n\nbar".indent(2) # => " foo\n\n bar" + # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar" + # + def indent(amount, indent_string=nil, indent_empty_lines=false) + dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)} + end +end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 3b08ebe35f..dc5ae0eafc 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -9,6 +9,7 @@ require 'active_support/core_ext/string' require 'active_support/time' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/output_safety' +require 'active_support/core_ext/string/indent' module Ace module Base @@ -521,3 +522,58 @@ class StringExcludeTest < ActiveSupport::TestCase assert_equal true, 'foo'.exclude?('p') end end + +class StringIndentTest < ActiveSupport::TestCase + test 'does not indent strings that only contain newlines (edge cases)' do + ['', "\n", "\n" * 7].each do |str| + assert_nil str.indent!(8) + assert_equal str, str.indent(8) + assert_equal str, str.indent(1, "\t") + end + end + + test "by default, indents with spaces if the existing indentation uses them" do + assert_equal " foo\n bar", "foo\n bar".indent(4) + end + + test "by default, indents with tabs if the existing indentation uses them" do + assert_equal "\tfoo\n\t\t\bar", "foo\n\t\bar".indent(1) + end + + test "by default, indents with spaces as a fallback if there is no indentation" do + assert_equal " foo\n bar\n baz", "foo\nbar\nbaz".indent(3) + end + + # Nothing is said about existing indentation that mixes spaces and tabs, so + # there is nothing to test. + + test 'uses the indent char if passed' do + assert_equal <<EXPECTED, <<ACTUAL.indent(4, '.') +.... def some_method(x, y) +.... some_code +.... end +EXPECTED + def some_method(x, y) + some_code + end +ACTUAL + + assert_equal <<EXPECTED, <<ACTUAL.indent(2, ' ') + def some_method(x, y) + some_code + end +EXPECTED + def some_method(x, y) + some_code + end +ACTUAL + end + + test "does not indent blank lines by default" do + assert_equal " foo\n\n bar", "foo\n\nbar".indent(1) + end + + test 'indents blank lines if told so' do + assert_equal " foo\n \n bar", "foo\n\nbar".indent(1, nil, true) + end +end diff --git a/guides/source/active_support_core_extensions.textile b/guides/source/active_support_core_extensions.textile index 66de6fd310..109228f8c7 100644 --- a/guides/source/active_support_core_extensions.textile +++ b/guides/source/active_support_core_extensions.textile @@ -1325,6 +1325,41 @@ that amount of leading whitespace. NOTE: Defined in +active_support/core_ext/string/strip.rb+. +h4. +indent+ + +Indents the lines in the receiver: + +<ruby> +<<EOS.indent(2) +def some_method + some_code +end +EOS +# => + def some_method + some_code + end +</ruby> + +The second argument, +indent_string+, specifies which indent string to use. The default is +nil+, which tells the method to make an educated guess peeking at the first indented line, and fallback to a space if there is none. + +<ruby> +" foo".indent(2) # => " foo" +"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar" +"foo".indent(2, "\t") # => "\t\tfoo" +</ruby> + +While +indent_string+ is tipically one space or tab, it may be any string. + +The third argument, +indent_empty_lines+, is a flag that says whether empty lines should be indented. Default is false. + +<ruby> +"foo\n\nbar".indent(2) # => " foo\n\n bar" +"foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar" +</ruby> + +The +indent!+ method performs indentation in-place. + h4. Access h5. +at(position)+ |