Skip to content

Instantly share code, notes, and snippets.

@RoUS
Created January 15, 2015 18:14
Show Gist options
  • Save RoUS/da894705ec30cf6f5d4c to your computer and use it in GitHub Desktop.
Save RoUS/da894705ec30cf6f5d4c to your computer and use it in GitHub Desktop.
OptionParser helper to wrap long option descriptions
#
# Long OptionParser descriptions don't get nicely wrapped by it, so
# this method does the appropriate fill, wrap, and indent.
#
# @license Apache 2.0
#
# @overload wrap(*args)
# @param [Array<Hash,String>] args
# The argument list can include multiple strings and hashes.
#
# Any hashes get merged and checked for options. See the nearby
# documentation for the +wrap(opts)+ overload description. (YARD
# [the documentation tool] doesn't provide for describing options in
# anything other than a +@param+ of type +Hash+.)
#
# Each string in the array starts a new line of text, and will be
# wrapped within the constraints.
#
# @overload wrap(opts)
# @param [Hash] opts
# @option opts [Integer] :firstcol (41)
# Left margin for wrapped & indented text.
# @option opts [Integer] :width (38)
# Total width for filled & wrapped text; does *not* include the
# indentation.
#
# @example
# wrap({ :firstcol=>1, :width=>14 }, 'a', 'b', 'c')
# => "a\nb\n\c"
#
# @example
# wrap({ :firstcol=>1, :width=>14 }, 'Some rather longer text to wrap.')
# => "Some rather\nlonger text to\nwrap."
#
# @example
# wrap({ :firstcol=>1, :width=>14 }, 'Some', 'rather longer text to wrap.')
# => "Some\nrather longer\ntext to wrap."
#
# @return [String]
# Returns a string with embedded newlines and indentation suitable to
# pass as description text to an OptionParser option handler.
#
def self.wrap(*args)
defaults = {
:firstcol => 38,
:width => 41,
}
#
# Pull any hashes out of the argument list and merge them with our
# defaults to make up the final settings for this call.
#
(options, args) = args.partition { |elt| elt.kind_of?(Hash) }
options = [ defaults, options ].flatten.reduce(:merge)
firstcol = options[:firstcol].to_i
width = options[:width].to_i
#
# We accumulate the lines of text into an array, which we'll convert
# to a string for the return value.
#
result = []
(lines, other) = args.partition { |elt| elt.kind_of?(String) }
lines.each do |line|
if (line.length <= width)
result << line
else
#
# Break out the words so we can wrap them as needed, since the
# total string is longer than the allowed width.
#
words = line.strip.split(%r!\s+!)
newline = ''
while (! words.empty?)
while ((newline.length + words[0].length + 1) <= width)
newline << ' ' unless (newline.length.zero?)
newline << words.shift
break if (words.empty?)
end
newline = words.shift if (newline == '')
result << newline
newline = ''
end
end
end
interstice = "\n" + (' ' * (firstcol - 1))
#
# We don't indent the beginning of the string; OptionParser's help
# mode will do that automatically.
#
return result.join(interstice).strip
end # def wrap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment