BRA2KET | = | { '['=>']', '('=>')', '{'=>'}', '<'=>'>' } |
[]= | -> | store |
Alias for []=. |
Interpolate. Provides a means of extenally using Ruby string interpolation mechinism.
try = "hello" str = "\#{try}!!!" String.interpolate{ str } #=> "hello!!!" NOTE: The block neccessary in order to get then binding of the caller.
CREDIT: Trans
# File lib/core/facets/string/interpolate.rb, line 15 15: def self.interpolate(&str) 16: eval "%{#{str.call}}", str.binding 17: end
Removes occurances of a string or regexp.
"HELLO HELLO" - "LL" #=> "HEO HEO"
CREDIT: Benjamin David Oakes
# File lib/core/facets/string/op_sub.rb, line 9 9: def -(pattern) 10: self.gsub(pattern, '') 11: end
Binary XOR of two strings.
puts "\000\000\001\001" ^ "\000\001\000\001" puts "\003\003\003" ^ "\000\001\002"
produces
"\000\001\001\000" "\003\002\001"
# File lib/core/facets/string/xor.rb, line 13 13: def ^(aString) 14: a = self.unpack('C'*(self.length)) 15: b = aString.unpack('C'*(aString.length)) 16: if (b.length < a.length) 17: (a.length - b.length).times { b << 0 } 18: end 19: xor = "" 20: 0.upto(a.length-1) { |pos| 21: x = a[pos] ^ b[pos] 22: xor << x.chr() 23: } 24: return(xor) 25: end
# File lib/core/facets/string/align.rb, line 3 3: def align(direction, n, sep="\n", c=' ') 4: case direction 5: when :right 6: align_right(n, sep="\n", c=' ') 7: when :left 8: align_left(n, sep="\n", c=' ') 9: when :center 10: align_center(n, sep="\n", c=' ') 11: else 12: raise ArgumentError 13: end 14: end
Centers each line of a string.
The default alignment separation is a new line ("\n"). This can be changed as can be the padding string which defaults to a single space (’ ’).
s = <<-EOS This is a test and so on EOS puts s.align_center(14)
produces
This is a test and so on
CREDIT: Trans
# File lib/core/facets/string/align.rb, line 98 98: def align_center(n, sep="\n", c=' ') 99: return center(n.to_i,c.to_s) if sep==nil 100: q = split(sep.to_s).collect { |line| 101: line.center(n.to_i,c.to_s) 102: } 103: q.join(sep.to_s) 104: end
Align a string to the left.
The default alignment separation is a new line ("\n"). This can be changed as can be the padding string which defaults to a single space (’ ’).
s = <<-EOS This is a test and so on EOS puts s.align_left(20, "\n", '.')
produces
This is a test...... and................. so on...............
CREDIT: Trans
# File lib/core/facets/string/align.rb, line 68 68: def align_left(n, sep="\n", c=' ') 69: return ljust(n.to_i,c.to_s) if sep==nil 70: q = split(sep.to_s).map do |line| 71: line.strip.ljust(n.to_i,c.to_s) 72: end 73: q.join(sep.to_s) 74: end
Align a string to the right.
The default alignment separation is a new line ("\n"). This can be changed as can be the padding string which defaults to a single space (’ ’).
s = <<-EOS This is a test and so on EOS puts s.align_right(14)
produces
This is a test and so on
CREDIT: Trans
# File lib/core/facets/string/align.rb, line 38 38: def align_right(n, sep="\n", c=' ') 39: return rjust(n.to_i,c.to_s) if sep==nil 40: q = split(sep.to_s).map do |line| 41: line.rjust(n.to_i,c.to_s) 42: end 43: q.join(sep.to_s) 44: end
Is this string just whitespace?
"abc".blank? #=> false " ".blank? #=> true
# File lib/core/facets/blank.rb, line 50 50: def blank? 51: self !~ /\S/ 52: end
Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.
"wrap me".bracket('{') #=> "{wrap me}" "wrap me".bracket('--','!') #=> "--wrap me!"
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 14 14: def bracket(bra, ket=nil) 15: #ket = String.bra2ket[$&] if ! ket && /^[\[({<]$/ =~ bra 16: ket = BRA2KET[bra] unless ket 17: "#{bra}#{self}#{ket ? ket : bra}" 18: end
Inplace version of braket.
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 24 24: def bracket!(bra, ket=nil) 25: self.replace(bracket(bra, ket)) 26: end
Converts a string to camelcase.
By default camelcase leaves the first character of the string as given. If first_letter is set to +:lower+ or false, then +camelcase+ will produce lowerCamelCase. If it is set to +:upper+ or true it will produce UpperCamelCase.
+camelcase+ also converts ’/’ to ’::’ which is useful for converting paths to namespaces.
Examples
"camel_case".camelcase #=> "camelCase" "camel/case".camelcase(true) #=> "Camel::Case" "Camel_case".camelcase(false) #=> "camelCase"
TODO: Is this the best approach? Should lowerCamelCase be default instead?
# File lib/core/facets/string/camelcase.rb, line 19 19: def camelcase(first_letter=nil) 20: case first_letter 21: when :upper, true 22: upper_camelcase 23: when :lower, false 24: lower_camelcase 25: else 26: str = dup 27: str.gsub!(/\/(.?)/){ "::#{$1.upcase}" } # NOT SO SURE ABOUT THIS 28: str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase } 29: #str.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase } 30: str 31: end 32: end
Return true if the string is capitalized, otherwise false.
"THIS".capitalized? #=> true "This".capitalized? #=> true "this".capitalized? #=> false
CREDIT: Phil Tomson
# File lib/core/facets/string/capitalized.rb, line 11 11: def capitalized? 12: self =~ /^[A-Z]/ 13: end
Returns an array of characters.
"abc".chars #=> ["a","b","c"]
# File lib/core/facets/string/chars.rb, line 13 13: def chars 14: split(//) 15: end
Cleave a string. Break a string in two parts at the nearest whitespace.
CREDIT: Trans
# File lib/core/facets/string/cleave.rb, line 8 8: def cleave(threshold=nil, len=nil) 9: l = (len || size / 2) 10: t = threshold || size 11: 12: h1 = self[0...l] 13: h2 = self[l..-1] 14: 15: i1 = h1.rindex(/\s/) || 0 16: d1 = (i1 - l).abs 17: 18: d2 = h2.index(/\s/) || l 19: i2 = d2 + l 20: 21: d1 = (i1-l).abs 22: d2 = (i2-l).abs 23: 24: if [d1, d2].min > t 25: i = t 26: elsif d1 < d2 27: i = i1 28: else 29: i = i2 30: end 31: 32: #dup.insert(l, "\n").gsub(/^\s+|\s+$/, '') 33: return self[0..i].to_s.strip, self[i+1..-1].to_s.strip 34: end
Compare method that takes length into account. Unlike #<=>, this is compatible with succ.
"abc".cmp("abc") #=> 0 "abcd".cmp("abc") #=> 1 "abc".cmp("abcd") #=> -1 "xyz".cmp("abc") #=> 1
CREDIT: Peter Vanbroekhoven
# File lib/core/facets/comparable/cmp.rb, line 31 31: def cmp(other) 32: return -1 if length < other.length 33: return 1 if length > other.length 34: self <=> other # alphabetic compare 35: end
Matches any whitespace (including newline) and replaces with a single space
@example
<<-QUERY.compress_lines SELECT name FROM users QUERY => "SELECT name FROM users"
# File lib/core/facets/string/compress_lines.rb, line 12 12: def compress_lines(spaced = true) 13: split($/).map { |line| line.strip }.join(spaced ? ' ' : '') 14: end
Remove quotes from string.
"'hi'".dequite #=> "hi"
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 88 88: def dequote 89: s = self.dup 90: 91: case self[0,1] 92: when "'", '"', '`' 93: s[0] = '' 94: end 95: 96: case self[-1,1] 97: when "'", '"', '`' 98: s[-1] = '' 99: end 100: 101: return s 102: end
Breaks a string up into an array based on a regular expression. Similar to scan, but includes the matches.
s = "<p>This<b>is</b>a test.</p>" s.divide( /\<.*?\>/ )
produces
["<p>This", "<b>is", "</b>a test.", "</p>"]
CREDIT: Trans
# File lib/core/facets/string/divide.rb, line 15 15: def divide( re ) 16: re2 = /#{re}.*?(?=#{re}|\Z)/ 17: scan(re2) #{re}(?=#{re})/) 18: end
Yields a single-character string for each character in the string. When $KCODE = ‘UTF8’, multi-byte characters are yielded appropriately.
# File lib/core/facets/string/each_char.rb, line 22 22: def each_char 23: scanner, char = StringScanner.new(self), /./mu 24: loop { yield(scanner.scan(char) || break) } 25: end
Iterate through each word of a string.
"a string".each_word { |word| ... }
# File lib/core/facets/string/each_word.rb, line 9 9: def each_word(&block) 10: words.each(&block) 11: end
Does a string end with the given suffix?
"hello".ends_with?("lo") #=> true "hello".ends_with?("to") #=> false
CREDIT: Lucas Carlson, Blaine Cook
# File lib/core/facets/string/start_with.rb, line 27 27: def end_with?(suffix) 28: self.rindex(suffix) == size - suffix.size 29: end
Expands tabs to n spaces. Non-destructive. If n is 0, then tabs are simply removed. Raises an exception if n is negative.
"\t\tHey".expand_tab(2) #=> " Hey"
Thanks to GGaramuno for a more efficient algorithm. Very nice.
CREDIT: Gavin Sinclair, Noah Gibbs, GGaramuno
# File lib/core/facets/string/expand_tab.rb, line 13 13: def expand_tab(n=8) 14: n = n.to_int 15: raise ArgumentError, "n must be >= 0" if n < 0 16: return gsub(/\t/, "") if n == 0 17: return gsub(/\t/, " ") if n == 1 18: str = self.dup 19: while 20: str.gsub!(/^([^\t\n]*)(\t+)/) { |f| 21: val = ( n * $2.size - ($1.size % n) ) 22: $1 << (' ' * val) 23: } 24: end 25: str 26: end
Returns a new string with all new lines removed from adjacent lines of text.
s = "This is\na test.\n\nIt clumps\nlines of text." s.fold
produces
"This is a test.\n\nIt clumps lines of text. "
One arguable flaw with this, that might need a fix: if the given string ends in a newline, it is replaced with a single space.
CREDIT: Trans
# File lib/core/facets/string/fold.rb, line 19 19: def fold(ignore_indented=false) 20: ns = '' 21: i = 0 22: br = self.scan(/(\n\s*\n|\Z)/m) do |m| 23: b = $~.begin(1) 24: e = $~.end(1) 25: nl = $& 26: tx = slice(i...b) 27: if ignore_indented and slice(i...b) =~ /^[ ]+/ 28: ns << tx 29: else 30: ns << tx.gsub(/[ ]*\n+/,' ') 31: end 32: ns << nl 33: i = e 34: end 35: ns 36: end
Like index but returns an array of all index locations. The reuse flag allows the trailing portion of a match to be reused for subsquent matches.
"abcabcabc".index_all('a') #=> [0,3,6] "bbb".index_all('bb', false) #=> [0] "bbb".index_all('bb', true) #=> [0,1]
TODO: Culd probably be defined for Indexable in general too.
# File lib/core/facets/string/range.rb, line 66 66: def index_all(s, reuse=false) 67: s = Regexp.new(Regexp.escape(s)) unless Regexp===s 68: ia = []; i = 0 69: while (i = index(s,i)) 70: ia << i 71: i += (reuse ? 1 : $~[0].size) 72: end 73: ia 74: end
Left chomp.
"help".lchomp("h") #=> "elp" "help".lchomp("k") #=> "help"
CREDIT: Trans
# File lib/core/facets/string/chomp.rb, line 10 10: def lchomp(match) 11: if index(match) == 0 12: self[match.size..-1] 13: else 14: self.dup 15: end 16: end
In-place left chomp.
"help".lchomp("h") #=> "elp" "help".lchomp("k") #=> "help"
CREDIT: Trans
# File lib/core/facets/string/chomp.rb, line 25 25: def lchomp!(match) 26: if index(match) == 0 27: self[0...match.size] = '' 28: self 29: end 30: end
Line wrap at width.
puts "1234567890".line_wrap(5)
produces
12345 67890
CREDIT: Trans
# File lib/core/facets/string/line_wrap.rb, line 14 14: def line_wrap(width, tabs=4) 15: s = gsub(/\t/,' ' * tabs) # tabs default to 4 spaces 16: s = s.gsub(/\n/,' ') 17: r = s.scan( /.{1,#{width}}/ ) 18: r.join("\n") << "\n" 19: end
Returns an array of characters.
"abc\n123".lines #=> ["abc","123"]
Note, this is not 100% compatible with 1.8.7+ which returns an enumerator instead of an array.
# File lib/core/facets/string/lines.rb, line 12 12: def lines(&blk) 13: if block_given? 14: self.split(/\n/).each(&blk) 15: else 16: self.split(/\n/) 17: end 18: end
# File lib/core/facets/string/camelcase.rb, line 42 42: def lower_camelcase 43: str = dup 44: str.gsub!(/\/(.?)/){ "::#{$1.upcase}" } # NOT SO SURE ABOUT THIS 45: str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase } 46: str.gsub!(/(\A|\s)([A-Z])/){ $1 + $2.downcase } 47: str 48: end
Downcase first letter.
# File lib/core/facets/string/uppercase.rb, line 17 17: def lowercase 18: str = to_s 19: str[0,1].downcase + str[1..-1] 20: end
Provides a margin controlled string.
x = %Q{ | This | is | margin controlled! }.margin
NOTE: This may still need a bit of tweaking.
CREDIT: Trans
# File lib/core/facets/string/margin.rb, line 16 16: def margin(n=0) 17: #d = /\A.*\n\s*(.)/.match( self )[1] 18: #d = /\A\s*(.)/.match( self)[1] unless d 19: d = ((/\A.*\n\s*(.)/.match(self)) || 20: (/\A\s*(.)/.match(self)))[1] 21: return '' unless d 22: if n == 0 23: gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '') 24: else 25: gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, ' ' * n) 26: end 27: end
Translate a (class or module) name to a suitable method name.
My::CoolClass.name.methodize => "my__cool_class"
# File lib/core/facets/string/methodize.rb, line 17 17: def methodize 18: gsub(/([A-Z]+)([A-Z])/,'\1_\2'). 19: gsub(/([a-z])([A-Z])/,'\1_\2'). 20: gsub('/' ,'__'). 21: gsub('::','__'). 22: downcase 23: end
Converts a string to module name representation.
This is essentially camelcase. It also converts ’/’ to ’::’ which is useful for converting paths to namespaces.
Examples
"method_name".modulize #=> "MethodName" "method/name".modulize #=> "Method::Name"
# File lib/core/facets/string/modulize.rb, line 21 21: def modulize 22: gsub('__','/'). 23: gsub(/\/(.?)/){ "::#{$1.upcase}" }. 24: gsub(/(?:_+|-+)([a-z])/){ $1.upcase }. 25: gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase } 26: end
‘Natural order’ comparison of strings, e.g.
"my_prog_v1.1.0" < "my_prog_v1.2.0" < "my_prog_v1.10.0"
which does not follow alphabetically. A secondary parameter, if set to true, makes the comparison case insensitive.
"Hello.10".natcmp("Hello.1") #=> -1 TODO: Invert case flag?
CREDIT: Alan Davies, Martin Pool
# File lib/core/facets/string/natcmp.rb, line 46 46: def natcmp(str2, caseInsensitive=false) 47: str1 = self.dup 48: str2 = str2.dup 49: compareExpression = /^(\D*)(\d*)(.*)$/ 50: 51: if caseInsensitive 52: str1.downcase! 53: str2.downcase! 54: end 55: 56: # remove all whitespace 57: str1.gsub!(/\s*/, '') 58: str2.gsub!(/\s*/, '') 59: 60: while (str1.length > 0) or (str2.length > 0) do 61: # Extract non-digits, digits and rest of string 62: str1 =~ compareExpression 63: chars1, num1, str1 = $1.dup, $2.dup, $3.dup 64: str2 =~ compareExpression 65: chars2, num2, str2 = $1.dup, $2.dup, $3.dup 66: # Compare the non-digits 67: case (chars1 <=> chars2) 68: when 0 # Non-digits are the same, compare the digits... 69: # If either number begins with a zero, then compare alphabetically, 70: # otherwise compare numerically 71: if (num1[0] != 48) and (num2[0] != 48) 72: num1, num2 = num1.to_i, num2.to_i 73: end 74: case (num1 <=> num2) 75: when -1 then return -1 76: when 1 then return 1 77: end 78: when -1 then return -1 79: when 1 then return 1 80: end # case 81: end # while 82: 83: # strings are naturally equal. 84: return 0 85: end 86: 87: end
Returns n characters of the string. If n is positive the characters are from the beginning of the string. If n is negative from the end of the string.
Alternatively a replacement string can be given, which will replace the n characters.
str = "this is text" str.nchar(4) #=> "this" str.nchar(4, 'that') #=> "that" str #=> "that is text"
# File lib/core/facets/string/nchar.rb, line 15 15: def nchar(n, replacement=nil) 16: if replacement 17: s = self.dup 18: n > 0 ? (s[0...n] = replacement) : (s[n..-1] = replacement) 19: return s 20: else 21: n > 0 ? self[0...n] : self[n..-1] 22: end 23: end
# File lib/core/facets/kernel/object_state.rb, line 35 35: def object_state(data=nil) 36: data ? replace(data) : dup 37: end
Outdent just indents a negative number of spaces.
CREDIT: Noah Gibbs
# File lib/core/facets/string/indent.rb, line 20 20: def outdent(n) 21: indent(-n) 22: end
Converts a (class or module) name to a unix path.
My::CoolClass.name.pathize #=> "my/cool_class"
# File lib/core/facets/string/pathize.rb, line 17 17: def pathize 18: gsub(/([A-Z]+)([A-Z])/,'\1_\2'). 19: gsub(/([a-z])([A-Z])/,'\1_\2'). 20: gsub('__','/'). 21: gsub('::','/'). 22: downcase 23: end
Return a new string embraced by given quotes. If no quotes are specified, then assumes single quotes.
"quote me".quote #=> "'quote me'" "quote me".quote(2) #=> "\"quote me\""
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 69 69: def quote(type=:s) 70: case type.to_s.downcase 71: when 's', 'single' 72: bracket("'") 73: when 'd', 'double' 74: bracket('"') 75: when 'b', 'back' 76: bracket('`') 77: else 78: bracket("'") 79: end 80: end
Like index_all but returns an array of Ranges.
"abc123abc123".range_all('abc') #=> [0..2, 6..8] TODO: Add offset, perhaps ?
CREDIT: Trans
# File lib/core/facets/string/range.rb, line 24 24: def range_all(s, reuse=false) 25: r = []; i = 0 26: while i < self.length 27: rng = range(s, i) 28: if rng 29: r << rng 30: i += reuse ? 1 : rng.end + 1 31: else 32: break 33: end 34: end 35: r.uniq 36: end
Returns an array of ranges mapping the characters per line.
"this\nis\na\ntest".range_of_line #=> [0..4, 5..7, 8..9, 10..13]
CREDIT: Trans
# File lib/core/facets/string/range.rb, line 46 46: def range_of_line 47: offset=0; charmap = [] 48: self.each do |line| 49: charmap << (offset..(offset + line.length - 1)) 50: offset += line.length 51: end 52: charmap 53: end
Apply a set of rules (regular expression matches) to the string.
The rules must be applied in order! So we cannot use a hash because the ordering is not guaranteed! we use an array instead.
The array containing rule-pairs (match, write).
The rewritten string.
CREDIT: George Moschovitis
# File lib/core/facets/string/rewrite.rb, line 18 18: def rewrite(rules) 19: raise ArgumentError.new('The rules parameter is nil') unless rules 20: rewritten_string = dup 21: rules.each do |match,write| 22: rewritten_string.gsub!(match,write) 23: end 24: return rewritten_string 25: end
Breaks a string up into an array based on a regular expression. Similar to scan, but includes the matches.
s = "<p>This<b>is</b>a test.</p>" s.shatter( /\<.*?\>/ )
produces
["<p>", "This", "<b>", "is", "</b>", "a test.", "</p>"]
CREDIT: Trans
# File lib/core/facets/string/shatter.rb, line 15 15: def shatter( re ) 16: r = self.gsub( re ){ |s| "\1" + s + "\1" } 17: while r[0,1] == "\1" ; r[0] = '' ; end 18: while r[-1,1] == "\1" ; r[-1] = '' ; end 19: r.split("\1") 20: end
The reverse of camelcase. Makes an underscored of a camelcase string.
Changes ’::’ to ’/’ to convert namespaces to paths.
Examples
"SnakeCase".snakecase #=> "snake_case" "Snake-Case".snakecase #=> "snake_case" "SnakeCase::Errors".snakecase #=> "snake_case/errors"
# File lib/core/facets/string/snakecase.rb, line 12 12: def snakecase 13: gsub(/::/, '/'). # NOT SO SURE ABOUT THIS 14: gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 15: gsub(/([a-z\d])([A-Z])/,'\1_\2'). 16: tr("-", "_"). 17: downcase 18: end
This is basically the same as store, but it acts like slice! when given only one argument.
Essentlay slice, but writes rather than reads.
a = "HELLO" a.splice("X", 1) a #=> "HXLLO" a = "HELLO" a.splice(1) #=> "E" a #=> "HLLO"
CREDIT: Trans
# File lib/core/facets/string/splice.rb, line 20 20: def splice(idx, sub=nil) 21: if sub 22: store(idx, sub) 23: else 24: case idx 25: when Range 26: slice!(idx) 27: else 28: slice!(idx,1) 29: end 30: end 31: end
Does a string start with the given prefix.
"hello".starts_with?("he") #=> true "hello".starts_with?("to") #=> false
CREDIT: Lucas Carlson, Blaine Cook
# File lib/core/facets/string/start_with.rb, line 12 12: def start_with?(prefix) 13: self.index(prefix) == 0 14: end
Aligns each line n spaces.
CREDIT: Gavin Sinclair
# File lib/core/facets/string/tab.rb, line 12 12: def tab(n) 13: gsub(/^ */, ' ' * n) 14: end
Preserves relative tabbing. The first non-empty line ends up with n spaces before nonspace.
CREDIT: Gavin Sinclair
# File lib/core/facets/string/tabto.rb, line 10 10: def tabto(n) 11: if self =~ /^( *)\S/ 12: indent(n - $1.length) 13: else 14: self 15: end 16: end
Title case.
"this is a string".titlecase => "This Is A String"
CREDIT: Eliazar Parra
# File lib/core/facets/string/titlecase.rb, line 10 10: def titlecase 11: gsub(/\b\w/){$&.upcase} 12: end
Interpret common affirmative string meanings as true, otherwise false. Balnk sapce and case are ignored. The following strings that will return true:
<tt>true</tt>,<tt>yes</tt>,<tt>on</tt>,<tt>t</tt>,<tt>1</tt>,<tt>y</tt>,<tt>==</tt>
Examples:
"true".to_b #=> true "yes".to_b #=> true "no".to_b #=> false "123".to_b #=> false
# File lib/core/facets/boolean.rb, line 43 43: def to_b 44: case self.downcase.strip 45: when 'true', 'yes', 'on', 't', '1', 'y', '==' 46: return true 47: when 'nil', 'null' 48: return nil 49: else 50: return false 51: end 52: end
Turns a string into a regular expression.
"a?".to_re #=> /a?/
CREDIT: Trans
# File lib/core/facets/string/to_re.rb, line 9 9: def to_re(esc=false) 10: Regexp.new((esc ? Regexp.escape(self) : self)) 11: end
Turns a string into a regular expression. By default it will escape all characters. Use false argument to turn off escaping.
"[".to_rx #=> /\[/
CREDIT: Trans
# File lib/core/facets/string/to_re.rb, line 21 21: def to_rx(esc=true) 22: Regexp.new((esc ? Regexp.escape(self) : self)) 23: end
Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.
"{unwrap me}".debracket('{') #=> "unwrap me" "--unwrap me!".debracket('--','!') #=> "unwrap me!"
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 37 37: def unbracket(bra=nil, ket=nil) 38: if bra 39: ket = BRA2KET[bra] unless ket 40: ket = ket ? ket : bra 41: s = self.dup 42: s.gsub!(%r[^#{Regexp.escape(bra)}], '') 43: s.gsub!(%r[#{Regexp.escape(ket)}$], '') 44: return s 45: else 46: if m = BRA2KET[ self[0,1] ] 47: return self.slice(1...-1) if self[-1,1] == m 48: end 49: end 50: return self.dup # if nothing else 51: end
Inplace version of debraket.
CREDIT: Trans
# File lib/core/facets/string/bracket.rb, line 57 57: def unbracket!(bra=nil, ket=nil) 58: self.replace( unbracket(bra, ket) ) 59: end
The reverse of camelcase. Makes an underscored of a camelcase string.
Changes ’::’ to ’/’ to convert namespaces to paths.
Examples
"SnakeCase".underscore #=> "snake_case" "Snake-Case".underscore #=> "snake_case" "SnakeCase::Errors".underscore #=> "snake_case/errors"
# File lib/core/facets/string/underscore.rb, line 12 12: def underscore 13: gsub(/::/, '/'). 14: gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 15: gsub(/([a-z\d])([A-Z])/,'\1_\2'). 16: tr("-", "_"). 17: downcase 18: end
Unfold paragrpahs.
FIXME: Sometimes adds one too many blank lines. TEST!!!
# File lib/core/facets/string/unfold.rb, line 7 7: def unfold 8: blank = false 9: text = '' 10: split(/\n/).each do |line| 11: if /\S/ !~ line 12: text << "\n\n" 13: blank = true 14: else 15: if /^(\s+|[*])/ =~ line 16: text << (line.rstrip + "\n") 17: else 18: text << (line.rstrip + " ") 19: end 20: blank = false 21: end 22: end 23: text = text.gsub(/(\n){3,}/,"\n\n") 24: text.rstrip 25: end
Is the string upcase/uppercase?
"THIS".upcase? #=> true "This".upcase? #=> false "this".upcase? #=> false
CREDIT: Phil Tomson
# File lib/core/facets/string/capitalized.rb, line 38 38: def upcase? 39: upcase == self 40: end
# File lib/core/facets/string/camelcase.rb, line 34 34: def upper_camelcase 35: str = dup 36: str.gsub!(/\/(.?)/){ "::#{$1.upcase}" } # NOT SO SURE ABOUT THIS 37: str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase } 38: str.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase } 39: str 40: end
Upcase first letter.
NOTE: One might argue that this method should behave the same as +upcase+ and rather this behavior should be in place of +captialize+. Probably so, but since Matz has already defined +captialize+ the way it is, this name seems most fitting to the missing behavior.
# File lib/core/facets/string/uppercase.rb, line 10 10: def uppercase 11: str = to_s 12: str[0,1].upcase + str[1..-1] 13: end
Prepend an "@" to the beginning of a string to make a instance variable name. This also replaces non-valid characters with underscores.
# File lib/core/facets/string/variablize.rb, line 7 7: def variablize 8: v = gsub(/\W/, '_') 9: "@#{v}" 10: end
Word wrap a string not exceeding max width.
puts "this is a test".word_wrap(4)
produces
this is a test
This is basic implementation of word wrap, but smart enough to suffice for most use cases.
CREDIT: Gavin Kistner, Dayne Broderson
# File lib/core/facets/string/word_wrap.rb, line 18 18: def word_wrap( col_width=80 ) 19: self.dup.word_wrap!( col_width ) 20: end
As with word_wrap, but modifies the string in place.
CREDIT: Gavin Kistner, Dayne Broderson
# File lib/core/facets/string/word_wrap.rb, line 26 26: def word_wrap!( col_width=80 ) 27: self.gsub!( /(\S{#{col_width}})(?=\S)/, '\1 ' ) 28: self.gsub!( /(.{1,#{col_width}})(?:\s+|$)/, "\\1\n" ) 29: self 30: end