Ugly code - suggestions?

  • Thread starter Gabriele Marrone
  • Start date
G

Gabriele Marrone

Hello!

I'm writing an ANSI color codes parser which gets a string with text
and ANSI color codes and outputs an array with substrings and numbers
of the color codes.
A color code is something like "\e[31m". Generally, I assume (am I
wrong?) they match /\e\[(\d+)(;\d+)*m/.

Here is what I came up with:


module ANSIParser
def self.ansi_to_array(str)
str = str.to_s
ret = []
while ((m = /\e\[(\d+)(;\d+)*m/.match(str)))
ret << m.pre_match if m.pre_match != ""
ret += m[0].scan(/\d+/).map { |c| c.to_i }
str = m.post_match
end
ret << str if str != ""
return ret
end
end

# TEST:
ansistr = "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred
anyway, still bold\e[33;32;31m"

puts ansistr # you should see colors if your terminal supports ANSI
escapes
puts ANSIParser::ansi_to_array(ansistr).inspect


It works, but it doesn't look much elegant. In fact, it looks much
more like perl than ruby to me :p
That while over there is awful. Is there a way to make it more
elegant? Is there some kind of iterator which does what my while
does? If not, would you split it somehow?

I'm looking for suggestions :)
Thanks!
 
G

greg

couple of ideas for you- didn't this out though
nil.to_s #=> ""
no need to re-scan a match if you can use $1, $2, etc

module ANSIParser
ANSI_MATCH = /\e\[(\d+);(\d+)*m/

def self.ansi_to_array(str)
str = str.to_s
ret = []

str.scan(ANSI_MATCH) do |match|
ret << $`.to_s << $1.to_i << $2.to_i
end

ret << $'.to_s
end
end



sorry for using the Perl variables :) if you want you can use
Regexp.last_match.post_match
 
D

dblack

HI --

couple of ideas for you- didn't this out though
nil.to_s #=> ""
no need to re-scan a match if you can use $1, $2, etc

The reason is that you might have more than one ;\d+ sequence, and the
scan operation with captures will only give you the last one:
=> [[";33"]]

I don't know whether the named captures in oniguruma might help
here....


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
R

Robert Klemme

Hello!

I'm writing an ANSI color codes parser which gets a string with text and
ANSI color codes and outputs an array with substrings and numbers of the
color codes.
A color code is something like "\e[31m". Generally, I assume (am I
wrong?) they match /\e\[(\d+)(;\d+)*m/.

Here is what I came up with:


module ANSIParser
def self.ansi_to_array(str)
str = str.to_s
ret = []
while ((m = /\e\[(\d+)(;\d+)*m/.match(str)))
ret << m.pre_match if m.pre_match != ""
ret += m[0].scan(/\d+/).map { |c| c.to_i }
str = m.post_match
end
ret << str if str != ""
return ret
end
end

# TEST:
ansistr = "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred anyway,
still bold\e[33;32;31m"

puts ansistr # you should see colors if your terminal supports ANSI escapes
puts ANSIParser::ansi_to_array(ansistr).inspect
ansistr = "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred
anyway, still bold\e[33;32;31m"
=> "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred anyway, still
bold\e[33;32;31m"
ansistr.split(%r{(\e\[\d+(?:;\d+)*m)}).inject([]) do |arr, s| ?> case s
when ""
arr
when %r{^\e}
arr.concat( s.scan( /\d+/ ).map {|x| x.to_i} )
else ?> arr << s
end
end
=> [31, "red,", 32, 1, 32, 1, "bold green", 33, 32, 31, "red anyway,
still bold", 33, 32, 31]

Kind regards

robert
 
G

Gabriele Marrone

Il giorno 06/nov/06, alle ore 10:35, Robert Klemme ha scritto:
ansistr = "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred
anyway, still bold\e[33;32;31m"
=> "\e[31mred,\e[32;1m\e[32;1mbold green\e[33;32;31mred anyway,
still bold\e[33;32;31m"
ansistr.split(%r{(\e\[\d+(?:;\d+)*m)}).inject([]) do |arr, s| ?> case s
when ""
arr
when %r{^\e}
arr.concat( s.scan( /\d+/ ).map {|x| x.to_i} )
else ?> arr << s
end
end
=> [31, "red,", 32, 1, 32, 1, "bold green", 33, 32, 31, "red
anyway, still bold", 33, 32, 31]

Kind regards

robert

Cool!
Thanks :D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,273
Latest member
DamonShoem

Latest Threads

Top