I'm fairly new to Ruby and I've been searching Google for a few hours now.
Does anyone know how to format the output of a print to be no more than 40 characters long?
For example:
What I want to print:
This is a simple sentence.
This simple
sentence appears
on four lines.
But I want it formatted as:
This is a simple sentence. This simple
sentence appears on four lines.
I have each line of the original put into an array.
so x = ["This is a simple sentence.", "This simple", "sentence appears", "on three lines."]
I tried x.each { |n| print n[0..40], " " }
but it didn't seem to do anything.
Any help would be fantastic!
The method word_wrap
expects a Strind and makes a kind of pretty print.
Your array is converted to a string with join("\n")
The code:
def word_wrap(text, line_width = 40 )
return text if line_width <= 0
text.gsub(/\n/, ' ').gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
end
x = ["This is a simple sentence.", "This simple", "sentence appears", "on three lines."]
puts word_wrap(x.join("\n"))
x << 'a' * 50 #To show what happens with long words
x << 'end'
puts word_wrap(x.join("\n"))
Code explanation:
x.join("\n"))
build a string, then build one long line with text.gsub(/\n/, ' ')
.
In this special case this two steps could be merged: x.join(" "))
And now the magic happens with
gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n")
(.{1,#{line_width}})
): Take any character up to line_width
characters.
(\s+|$)
: The next character must be a space or line end (in other words: the previous match may be shorter the line_width
if the last character is no space.
"\\1\n"
: Take the up to 40 character long string and finish it with a newline.
gsub
repeat the wrapping until it is finished.
And in the end, I delete leading and trailing spaces with strip
I added also a long word (50 a's). What happens? The gsub does not match, the word keeps as it is.
puts x.join(" ").scan(/(.{1,40})(?:\s|$)/m)
This is a simple sentence. This simple
sentence appears on three lines.
Ruby 1.9 (and not overly efficient):
>> x.join(" ").each_char.each_slice(40).to_a.map(&:join)
=> ["This is a simple sentence. This simple s", "entence appears on three lines."]
The reason your solution doesn't work is that all the individual strings are shorter than 40 characters, so n[0..40]
always is the entire string.