Word-Wrapping Lines of Text

Problem

You want to turn a string full of miscellaneous whitespace into a string formatted with linebreaks at appropriate intervals, so that the text can be displayed in a window or sent as an email.

Solution

The simplest way to add newlines to a piece of text is to use a regular expression like the following.

	def wrap(s, width=78)
	 s.gsub(/(.{1,#{width}})(s+|)/, "\1
")
	end

	wrap("This text is too short to be wrapped.")
	# => "This text is too short to be wrapped.
"

	puts wrap("This text is not too short to be wrapped.", 20)
	# This text is not too
	# short to be wrapped.

	puts wrap("These ten-character columns are stifling my creativity!", 10)
	# These
	# ten-character
	# columns
	# are
	# stifling
	# my
	# creativity!

 

Discussion

The code given in the Solution preserves the original formatting of the string, inserting additional line breaks where necessary. This works well when you want to preserve the existing formatting while squishing everything into a smaller space:

	poetry = %q{It is an ancient Mariner,
	And he stoppeth one of three.
	"By thy long beard and glittering eye,
	Now wherefore stopp'st thou me?}

	puts wrap(poetry, 20)
	# It is an ancient
	# Mariner,
	# And he stoppeth one
	# of three.
	# "By thy long beard
	# and glittering eye,
	# Now wherefore
	# stopp'st thou me?

But sometimes the existing whitespace isn't important, and preserving it makes the result look bad:

	prose = %q{I find myself alone these days, more often than not,
	watching the rain run down nearby windows. How long has it been
	raining? The newspapers now print the total, but no one reads them
	anymore.}

	puts wrap(prose, 60)
	# I find myself alone these days, more often than not,
	# watching the rain run down nearby windows. How long has it
	# been
	# raining? The newspapers now print the total, but no one
	# reads them
	# anymore.

Looks pretty ragged. In this case, we want to get replace the original newlines with new ones. The simplest way to do this is to preprocess the string with another regular expression:

	def reformat_wrapped(s, width=78)
	 s.gsub(/s+/, " ").gsub(/(.{1,#{width}})( |)/, "\1
")
	end

But regular expressions are relatively slow; it's much more efficient to tear the string apart into words and rebuild it:

	def reformat_wrapped(s, width=78)
	 lines = []
	 line = ""
	 s.split(/s+/).each do |word|
	 if line.size + word.size >= width
	 lines << line
	 line = word
	 elsif line.empty?
	 line = word
	 else
	 line << " " << word
	 end
	 end
	 lines << line if line
	 return lines.join "
"
	end

	puts reformat_wrapped(prose, 60)
	# I find myself alone these days, more often than not,
	# watching the rain run down nearby windows. How long has it
	# been raining? The newspapers now print the total, but no one
	# reads them anymore.

 

See Also

  • The Facets Core library defines String#word_wrap and String#word_wrap! methods


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net