Skip to content

Commit

Permalink
feat: missing String.natcmp & Colorize methods
Browse files Browse the repository at this point in the history
  • Loading branch information
sclinede committed Jul 20, 2015
1 parent 29dd2f8 commit 81cb0f1
Showing 1 changed file with 117 additions and 0 deletions.
117 changes: 117 additions & 0 deletions lib/string_tools/core_ext/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,119 @@ def naturalized
scan(/[^\d\.]+|[\d\.]+/).map{|f| f.match(/^\d+(\.\d+)?$/) ? f.to_f : f }
end

def self.natcmp(str1, str2)
str1, str2 = str1.dup, str2.dup
compare_expression = /^(\D*)((?:\d+(?:\.\d+)?)*)(.*)$/

# Remove all whitespace
str1.gsub!(/\s*/, '')
str2.gsub!(/\s*/, '')

while (str1.length > 0) or (str2.length > 0)
# Extract non-digits, digits and rest of string
str1 =~ compare_expression
chars1, num1, str1 = $1.dup, $2.dup, $3.dup

str2 =~ compare_expression
chars2, num2, str2 = $1.dup, $2.dup, $3.dup

# Compare the non-digits
case (chars1 <=> chars2)
when 0 # Non-digits are the same, compare the digits...
# If either number begins with a zero, then compare alphabetically,
# otherwise compare numerically
if !(num1[0] == 48 && num1[1] != 46) and !(num2[0] == 48 && num2[1] != 46)
num1, num2 = num1.to_f, num2.to_f
end

case (num1 <=> num2)
when -1 then return -1
when 1 then return 1
end
when -1 then return -1
when 1 then return 1
end # case

end # while

# Strings are naturally equal
0
end

# Выполняет преобразование строки в punycode.
def to_punycode
Addressable::URI.parse(self).normalize.to_s
end

# Embed in a String to clear all previous ANSI sequences.
ANSI_CLEAR = "\e[0m"
ANSI_BOLD = "\e[1m"
ANSI_UNDERLINE = "\e[4m"

# Colors
BLACK = "\e[30m"
RED = "\e[31m"
GREEN = "\e[32m"
YELLOW = "\e[33m"
BLUE = "\e[34m"
MAGENTA = "\e[35m"
CYAN = "\e[36m"
WHITE = "\e[37m"

# === Synopsys
# Colorize string (for terminals)
# Does not work with sprintf yet
#
# === Usage
# "ln -s".colorize(:red)
#
# === Args
# +color+ - symbol, one of the following (black, white, red, green, yellow, blue, magenta, cyan)
# +bold_or_options+ - True/False or Hash
def colorize(color, bold_or_options = nil)
is_bold = bold_or_options.is_a?(TrueClass)
is_underline = false

if bold_or_options.is_a?(Hash)
is_bold ||= bold_or_options[:bold]
is_underline = bold_or_options[:underline]
end

raise ArgumentError('Color must be a symbol') unless color.is_a?(Symbol)
color_const = color.to_s.upcase.to_sym

raise ArgumentError('Unknown color') unless self.class.const_defined?(color_const)
ascii_color = self.class.const_get(color_const)

s = surround_with_ansi(ascii_color)
s = s.bold if is_bold
s = s.underline if is_underline
s
end

# === Synopsys
# Make text bolder (for ASCII terminals)
def bold
surround_with_ansi(ANSI_BOLD)
end

# === Synopsys
# Make text underlined (for ASCII terminals)
def underline
surround_with_ansi(ANSI_UNDERLINE)
end

# === Synopsys
# remove colors from colorized string
def remove_colors
gsub(/\e\[\d+m/, '')
end

[:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan].each do |color|
define_method color do |*args|
colorize(color, *args)
end
end

# shorthand
def detect_encoding
Expand Down Expand Up @@ -84,4 +191,14 @@ def to_cp1251
def to_cp1251!
self.replace(self.to_cp1251)
end

private

def surround_with_ansi(ascii_seq)
"#{ascii_seq}#{protect_escape_of(ascii_seq)}#{ANSI_CLEAR}"
end

def protect_escape_of(ascii_seq)
gsub(Regexp.new(Regexp.escape(ANSI_CLEAR)), "#{ANSI_CLEAR}#{ascii_seq}")
end
end

0 comments on commit 81cb0f1

Please sign in to comment.