Module: Kramdown::ANSI::Width
- Extended by:
- Term::ANSIColor
- Includes:
- Term::ANSIColor
- Included in:
- Kramdown::ANSI
- Defined in:
- lib/kramdown/ansi/width.rb
Overview
A module that provides functionality for calculating terminal width percentages and wrapping/truncating text accordingly.
The Width module includes methods to determine the available terminal width based on a percentage, and provides text wrapping and truncation capabilities that respect terminal dimensions.
Defined Under Namespace
Classes: Token
Constant Summary collapse
- ANSI_ESCAPES =
/\e\[.*?m|\e\].*?(\e|\a)\\?/
Class Method Summary collapse
-
.display_width(line) ⇒ Integer
Calculates the display width of a string after removing ANSI escape sequences.
-
.remove_ansi_escapes(line) ⇒ String
Removes ANSI escape sequences from the given string.
-
.truncate(text, percentage: nil, length: nil, ellipsis: ?…) ⇒ String
Truncates a given string to a specified length or percentage.
-
.width(percentage: 100.0) ⇒ Integer
Returns the width of the terminal in characters, given a percentage.
-
.wrap(text, percentage: nil, length: nil) ⇒ String
Wraps a string to a given width, either by percentage of terminal width or by an explicit character length.
Instance Method Summary collapse
-
#display_width(line) ⇒ Integer
private
Calculates the display width of a string after removing ANSI escape sequences.
-
#remove_ansi_escapes(line) ⇒ String
private
Removes ANSI escape sequences from the given string.
-
#truncate(text, percentage: nil, length: nil, ellipsis: ?…) ⇒ String
private
Truncates a given string to a specified length or percentage.
-
#width(percentage: 100.0) ⇒ Integer
private
Returns the width of the terminal in characters, given a percentage.
-
#wrap(text, percentage: nil, length: nil) ⇒ String
private
Wraps a string to a given width, either by percentage of terminal width or by an explicit character length.
Class Method Details
.display_width(line) ⇒ Integer
Calculates the display width of a string after removing ANSI escape sequences.
47 48 49 |
# File 'lib/kramdown/ansi/width.rb', line 47 def display_width(line) Unicode::DisplayWidth.of(remove_ansi_escapes(line)) end |
.remove_ansi_escapes(line) ⇒ String
Removes ANSI escape sequences from the given string.
30 31 32 |
# File 'lib/kramdown/ansi/width.rb', line 30 def remove_ansi_escapes(line) line.to_s.gsub(ANSI_ESCAPES, '') end |
.truncate(text, percentage: nil, length: nil, ellipsis: ?…) ⇒ String
Truncates a given string to a specified length or percentage. If the text is longer an ellipsis sequence is added at the end of the generated string, to indicate that a truncation has been performed.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/kramdown/ansi/width.rb', line 130 def truncate(text, percentage: nil, length: nil, ellipsis: ?…) percentage.nil? ^ length.nil? or raise ArgumentError, "either pass percentage or length argument" percentage and length ||= width(percentage:) ellipsis_length = display_width(remove_ansi_escapes(ellipsis)) found_esc = false result = +'' return result if text.empty? return result if length < ellipsis_length current_length = 0 tokens = [] text.scan(/(?<esc>#{ANSI_ESCAPES})|(?<txt>.)/m) do token = Token.new( type: $~[:esc] ? :esc : :txt, value: $&, length: $~[:esc] ? 0 : display_width($&) ) tokens << token end while token = tokens.shift if token.type == :esc found_esc = true result << token.value next end if current_length + token.length == length && tokens.empty? result << token.value current_length += token.length break elsif current_length + token.length + ellipsis_length > length result << ellipsis break elsif current_length + token.length + ellipsis_length == length result << token.value current_length += token.length remaining_text_length = tokens.select { _1.type == :txt }.map(&:length).sum if current_length + remaining_text_length == length next elsif current_length + remaining_text_length > length result << ellipsis break else next end else current_length += token.length result << token.value end end result << reset if found_esc && !result.end_with?(reset) result end |
.width(percentage: 100.0) ⇒ Integer
Returns the width of the terminal in characters, given a percentage.
38 39 40 |
# File 'lib/kramdown/ansi/width.rb', line 38 def width(percentage: 100.0) ((Float(percentage) * Tins::Terminal.columns) / 100).floor end |
.wrap(text, percentage: nil, length: nil) ⇒ String
Wraps a string to a given width, either by percentage of terminal width or by an explicit character length.
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 |
# File 'lib/kramdown/ansi/width.rb', line 62 def wrap(text, percentage: nil, length: nil) percentage.nil? ^ length.nil? or raise ArgumentError, "either pass percentage or length argument" percentage and length ||= width(percentage:) return text if length <= 0 begin length = length.to_i rescue FloatDomainError return text end length = length.clamp(1..) length_without_ansi = 0 result = +'' text.scan(/(?<nws>\S+)|(?<ws>\s)/) do token_value = $& token_length = display_width(token_value) if $~[:nws] if length_without_ansi + token_length > length length_without_ansi = token_length if result[-1] == ' ' result[-1, 1] = "\n#{token_value}" else result << "\n#{token_value}" end else length_without_ansi += token_length result << token_value end else length_without_ansi += token_length result << token_value end end result end |
Instance Method Details
#display_width(line) ⇒ Integer (private)
Calculates the display width of a string after removing ANSI escape sequences.
47 48 49 |
# File 'lib/kramdown/ansi/width.rb', line 47 def display_width(line) Unicode::DisplayWidth.of(remove_ansi_escapes(line)) end |
#remove_ansi_escapes(line) ⇒ String (private)
Removes ANSI escape sequences from the given string.
30 31 32 |
# File 'lib/kramdown/ansi/width.rb', line 30 def remove_ansi_escapes(line) line.to_s.gsub(ANSI_ESCAPES, '') end |
#truncate(text, percentage: nil, length: nil, ellipsis: ?…) ⇒ String (private)
Truncates a given string to a specified length or percentage. If the text is longer an ellipsis sequence is added at the end of the generated string, to indicate that a truncation has been performed.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/kramdown/ansi/width.rb', line 130 def truncate(text, percentage: nil, length: nil, ellipsis: ?…) percentage.nil? ^ length.nil? or raise ArgumentError, "either pass percentage or length argument" percentage and length ||= width(percentage:) ellipsis_length = display_width(remove_ansi_escapes(ellipsis)) found_esc = false result = +'' return result if text.empty? return result if length < ellipsis_length current_length = 0 tokens = [] text.scan(/(?<esc>#{ANSI_ESCAPES})|(?<txt>.)/m) do token = Token.new( type: $~[:esc] ? :esc : :txt, value: $&, length: $~[:esc] ? 0 : display_width($&) ) tokens << token end while token = tokens.shift if token.type == :esc found_esc = true result << token.value next end if current_length + token.length == length && tokens.empty? result << token.value current_length += token.length break elsif current_length + token.length + ellipsis_length > length result << ellipsis break elsif current_length + token.length + ellipsis_length == length result << token.value current_length += token.length remaining_text_length = tokens.select { _1.type == :txt }.map(&:length).sum if current_length + remaining_text_length == length next elsif current_length + remaining_text_length > length result << ellipsis break else next end else current_length += token.length result << token.value end end result << reset if found_esc && !result.end_with?(reset) result end |
#width(percentage: 100.0) ⇒ Integer (private)
Returns the width of the terminal in characters, given a percentage.
38 39 40 |
# File 'lib/kramdown/ansi/width.rb', line 38 def width(percentage: 100.0) ((Float(percentage) * Tins::Terminal.columns) / 100).floor end |
#wrap(text, percentage: nil, length: nil) ⇒ String (private)
Wraps a string to a given width, either by percentage of terminal width or by an explicit character length.
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 |
# File 'lib/kramdown/ansi/width.rb', line 62 def wrap(text, percentage: nil, length: nil) percentage.nil? ^ length.nil? or raise ArgumentError, "either pass percentage or length argument" percentage and length ||= width(percentage:) return text if length <= 0 begin length = length.to_i rescue FloatDomainError return text end length = length.clamp(1..) length_without_ansi = 0 result = +'' text.scan(/(?<nws>\S+)|(?<ws>\s)/) do token_value = $& token_length = display_width(token_value) if $~[:nws] if length_without_ansi + token_length > length length_without_ansi = token_length if result[-1] == ' ' result[-1, 1] = "\n#{token_value}" else result << "\n#{token_value}" end else length_without_ansi += token_length result << token_value end else length_without_ansi += token_length result << token_value end end result end |