1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
# frozen_string_literal: true
module Cri
# Used for formatting strings (e.g. converting to paragraphs, wrapping,
# formatting as title)
#
# @api private
class StringFormatter
# Extracts individual paragraphs (separated by two newlines).
#
# @param [String] str The string to format
#
# @return [Array<String>] A list of paragraphs in the string
def to_paragraphs(str)
lines = str.scan(/([^\n]+\n|[^\n]*$)/).map { |l| l[0].strip }
paragraphs = [[]]
lines.each do |line|
if line.empty?
paragraphs << []
else
paragraphs.last << line
end
end
paragraphs.reject(&:empty?).map { |p| p.join(' ') }
end
# Word-wraps and indents the string.
#
# @param [String] str The string to format
#
# @param [Number] width The maximal width of each line. This also includes
# indentation, i.e. the actual maximal width of the text is
# `width`-`indentation`.
#
# @param [Number] indentation The number of spaces to indent each line.
#
# @param [Boolean] first_line_already_indented Whether or not the first
# line is already indented
#
# @return [String] The word-wrapped and indented string
def wrap_and_indent(str, width, indentation, first_line_already_indented = false)
indented_width = width - indentation
indent = ' ' * indentation
# Split into paragraphs
paragraphs = to_paragraphs(str)
# Wrap and indent each paragraph
text = paragraphs.map do |paragraph|
# Initialize
lines = []
line = ''
# Split into words
paragraph.split(/\s/).each do |word|
# Begin new line if it's too long
if (line + ' ' + word).length >= indented_width
lines << line
line = ''
end
# Add word to line
line += (line == '' ? '' : ' ') + word
end
lines << line
# Join lines
lines.map { |l| indent + l }.join("\n")
end.join("\n\n")
if first_line_already_indented
text[indentation..-1]
else
text
end
end
# @param [String] str The string to format
#
# @return [String] The string, formatted to be used as a title in a section
# in the help
def format_as_title(str, io)
if Cri::Platform.color?(io)
bold(red(str.upcase))
else
str.upcase
end
end
# @param [String] str The string to format
#
# @return [String] The string, formatted to be used as the name of a command
# in the help
def format_as_command(str, io)
if Cri::Platform.color?(io)
green(str)
else
str
end
end
# @param [String] str The string to format
#
# @return [String] The string, formatted to be used as an option definition
# of a command in the help
def format_as_option(str, io)
if Cri::Platform.color?(io)
yellow(str)
else
str
end
end
def red(str)
"\e[31m#{str}\e[0m"
end
def green(str)
"\e[32m#{str}\e[0m"
end
def yellow(str)
"\e[33m#{str}\e[0m"
end
def bold(str)
"\e[1m#{str}\e[0m"
end
end
end
|