[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ugly code - suggestions?

Gabriele Marrone

11/5/2006 9:14:00 PM

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!


4 Answers

greg

11/6/2006 1:28:00 AM

0

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


dblack

11/6/2006 1:49:00 AM

0

Robert Klemme

11/6/2006 9:33:00 AM

0

On 05.11.2006 22:13, Gabriele Marrone wrote:
> 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

Gabriele Marrone

11/6/2006 11:25:00 AM

0


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