Module: Terminal::Ansi
- Defined in:
- lib/terminal/ansi.rb,
lib/terminal/ansi/named_colors.rb
Overview
Fast ANSI control code and BBCode processing.
Class Attribute Summary collapse
-
.attributes ⇒ Array<Symbol>
readonly
Supported attribute names.
-
.colors ⇒ Array<Symbol>
readonly
Supported 3/4-bit color names.
-
.named_colors ⇒ Array<Symbol>
readonly
Supported basic 24-bit (Kitty compatible) color names.
ANSI control code generator functions collapse
-
.[](*attributes) ⇒ String
Combine given Ansi.attributes, Ansi.colors, Ansi.named_colors and color codes to an ANSI control code sequence.
-
.ansi?(str) ⇒ true, false
Test if given String contains ANSI control codes.
-
.decorate(str, *attributes, reset: true) ⇒ String
Decorate given argument with ANSI attributes and colors.
-
.try_convert(attributes, separator: ' ') ⇒ String?
Try to combine given ANSI attributes and colors.
-
.undecorate(str) ⇒ String
Remove ANSI functions, attributes and colors from given string.
-
.valid?(*attributes) ⇒ true, false
Test if all given attributes are valid.
BBcode related functions collapse
-
.bbcode(str) ⇒ String
Replace embedded BBCode-like attributes with ANSI control codes.
-
.unbbcode(str) ⇒ String
Remove embedded BBCode-like attributes.
Other tool functions collapse
-
.plain(str) ⇒ String
Remove any BBCode-like and/or ANSI attributes.
-
.rainbow(str, frequency: 0.3, spread: 0.8, seed: 1.1) ⇒ String
Create nice colored text.
Cursor manipulation collapse
-
.cursor_back(columns = 1) ⇒ String
Move cursor given columns back.
-
.cursor_column(column = 1) ⇒ String
Move cursor to given column in the current row.
-
.cursor_column_rel(column = 1) ⇒ String
Move cursor to given column in the current row relative to the current position.
-
.cursor_down(lines = 1) ⇒ String
Move cursor given lines down.
-
.cursor_forward(columns = 1) ⇒ String
Move cursor given columns forward.
-
.cursor_hide ⇒ String
Hide cursor.
-
.cursor_next_line(lines = 1) ⇒ String
Move cursor to the beginning of the given next line.
-
.cursor_pos(row, column = nil) ⇒ String
Move to given row and column.
-
.cursor_prev_line(lines = 1) ⇒ String
Move cursor to the beginning of the given previous line.
-
.cursor_restore_pos ⇒ String
Restore saved cursor position.
-
.cursor_row_rel(row = 1) ⇒ String
Move cursor to given row relative to the current position.
-
.cursor_save_pos ⇒ String
Save current cursor position.
-
.cursor_show ⇒ String
Show cursor.
-
.cursor_up(lines = 1) ⇒ String
Move cursor given lines up.
Screen manipulation collapse
-
.screen_alternate ⇒ String
Use alternative screen buffer.
-
.screen_alternate_off ⇒ String
Do not longer use alternative screen buffer.
-
.screen_erase(part = :all) ⇒ String
Erase screen part.
-
.screen_restore ⇒ String
Restore current screen.
-
.screen_save ⇒ String
Safe current screen.
-
.screen_scroll_down(lines = 1) ⇒ String
Scroll window given lines down.
-
.screen_scroll_up(lines = 1) ⇒ String
Scroll window given lines up.
Other ANSI control functions collapse
-
.char_repeat(count = 1) ⇒ String
Repeat last char.
-
.line_erase(part = :all) ⇒ String
Erase part of line.
-
.link(url, text) ⇒ String
Create a hyperlink.
-
.notify(text) ⇒ String
Show a simple notification.
-
.progress(state, percent = 0) ⇒ String
Set task progress state.
-
.scale(text, scale: nil, width: nil, fracn: nil, fracd: nil, vertical: nil, horizontal: nil) ⇒ String
Create scaled text.
-
.title(title) ⇒ String
Set (tab) title.
Class Attribute Details
.attributes ⇒ Array<Symbol> (readonly)
Supported attribute names.
15 |
# File 'lib/terminal/ansi.rb', line 15 def attributes = @attributes.dup |
.colors ⇒ Array<Symbol> (readonly)
Supported 3/4-bit color names.
23 |
# File 'lib/terminal/ansi.rb', line 23 def colors = @colors.dup |
.named_colors ⇒ Array<Symbol> (readonly)
Supported basic 24-bit (Kitty compatible) color names.
31 |
# File 'lib/terminal/ansi.rb', line 31 def named_colors = NAMED_COLORS.keys.map!(&:to_sym) |
Class Method Details
.[](*attributes) ⇒ String
Combine given attributes, colors, named_colors and color codes to an ANSI control code sequence.
Colors can specified by their name for ANSI 3-bit and 4-bit colors.
For 8-bit ANSI colors use 2-digit hexadecimal values 00...ff.
To use RGB ANSI colors (24-bit colors) specify 3-digit or 6-digit
hexadecimal values 000...fff or 000000...ffffff.
This represent the RRGGBB values (or RGB for short version) like you
may known from CSS color notation.
To use a color as background color prefix the color attribute with bg_
or on_.
To use a color as underline color prefix the color attribute with ul_.
To clarify that a color attribute have to be used as foreground
color use the prefix fg_.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/terminal/ansi.rb', line 95 def [](*attributes) return +'' if attributes.empty? "\e[#{ attributes .map! do |arg| case arg when String @attr_map[arg] || _invalid(arg) when Symbol @attrs_map[arg] || _invalid(arg) when (0..255) "38;5;#{arg}" when (256..511) "48;5;#{arg - 256}" when (512..767) "58;5;#{arg - 512}" else _invalid(arg) end end .join(';') }m" end |
.ansi?(str) ⇒ true, false
Test if given String contains ANSI control codes.
123 |
# File 'lib/terminal/ansi.rb', line 123 def ansi?(str) = @re_test.match?(str.to_s) |
.bbcode(str) ⇒ String
Replace embedded BBCode-like attributes with ANSI control codes.
219 220 221 222 223 224 225 226 227 |
# File 'lib/terminal/ansi.rb', line 219 def bbcode(str) str = str.to_s return str.dup unless str.index('[') str.gsub(@re_bbcode) do |match_str| match = Regexp.last_match(1) or next match_str next "[#{match[1..]}]" if match[0] == '\\' try_convert(match) || match_str end end |
.char_repeat(count = 1) ⇒ String
Repeat last char.
447 |
# File 'lib/terminal/ansi.rb', line 447 def char_repeat(count = 1) = "\e[#{count}b" |
.cursor_back(columns = 1) ⇒ String
Move cursor given columns back.
328 |
# File 'lib/terminal/ansi.rb', line 328 def cursor_back(columns = 1) = "\e[#{columns}D" |
.cursor_column(column = 1) ⇒ String
Move cursor to given column in the current row.
346 |
# File 'lib/terminal/ansi.rb', line 346 def cursor_column(column = 1) = "\e[#{column}G" |
.cursor_column_rel(column = 1) ⇒ String
Move cursor to given column in the current row relative to the current position. (Skip some columns.)
354 |
# File 'lib/terminal/ansi.rb', line 354 def cursor_column_rel(column = 1) = "\e[#{column}a" |
.cursor_down(lines = 1) ⇒ String
Move cursor given lines down.
316 |
# File 'lib/terminal/ansi.rb', line 316 def cursor_down(lines = 1) = "\e[#{lines}B" |
.cursor_forward(columns = 1) ⇒ String
Move cursor given columns forward.
322 |
# File 'lib/terminal/ansi.rb', line 322 def cursor_forward(columns = 1) = "\e[#{columns}C" |
.cursor_hide ⇒ String
Hide cursor.
381 |
# File 'lib/terminal/ansi.rb', line 381 def cursor_hide = +CURSOR_HIDE |
.cursor_next_line(lines = 1) ⇒ String
Move cursor to the beginning of the given next line.
334 |
# File 'lib/terminal/ansi.rb', line 334 def cursor_next_line(lines = 1) = "\e[#{lines}E" |
.cursor_pos(row, column = nil) ⇒ String
Move to given row and column.
368 369 370 371 |
# File 'lib/terminal/ansi.rb', line 368 def cursor_pos(row, column = nil) return column ? "\e[;#{column}H" : "\e[H" unless row column ? "\e[#{row};#{column}H" : "\e[#{row}H" end |
.cursor_prev_line(lines = 1) ⇒ String
Move cursor to the beginning of the given previous line.
340 |
# File 'lib/terminal/ansi.rb', line 340 def cursor_prev_line(lines = 1) = "\e[#{lines}F" |
.cursor_restore_pos ⇒ String
Restore saved cursor position.
391 |
# File 'lib/terminal/ansi.rb', line 391 def cursor_restore_pos = +CURSOR_POS_RESTORE |
.cursor_row_rel(row = 1) ⇒ String
Move cursor to given row relative to the current position. (Skip some rows.)
361 |
# File 'lib/terminal/ansi.rb', line 361 def cursor_row_rel(row = 1) = "\e[#{row}e" |
.cursor_save_pos ⇒ String
Save current cursor position.
386 |
# File 'lib/terminal/ansi.rb', line 386 def cursor_save_pos = +CURSOR_POS_SAVE |
.cursor_show ⇒ String
Show cursor.
376 |
# File 'lib/terminal/ansi.rb', line 376 def cursor_show = +CURSOR_SHOW |
.cursor_up(lines = 1) ⇒ String
Move cursor given lines up.
310 |
# File 'lib/terminal/ansi.rb', line 310 def cursor_up(lines = 1) = "\e[#{lines}A" |
.decorate(str, *attributes, reset: true) ⇒ String
Decorate given argument with ANSI attributes and colors.
141 142 143 144 |
# File 'lib/terminal/ansi.rb', line 141 def decorate(str, *attributes, reset: true) attributes = self[*attributes] attributes.empty? ? "#{str}" : "#{attributes}#{str}#{"\e[m" if reset}" end |
.line_erase(part = :all) ⇒ String
Erase part of line.
453 |
# File 'lib/terminal/ansi.rb', line 453 def line_erase(part = :all) = "\e[#{@line_erase[part]}K" |
.link(url, text) ⇒ String
Create a hyperlink. This is not widely supported; works for Ghostty, iTerm2, Kitty, Rio, Tabby, WezTerm.
480 |
# File 'lib/terminal/ansi.rb', line 480 def link(url, text) = "\e]8;;#{url}\a#{text}\e]8;;\a" |
.notify(text) ⇒ String
Show a simple notification. This is not widely supported; works for Ghostty, iTerm2, Kitty, WezTerm.
491 |
# File 'lib/terminal/ansi.rb', line 491 def notify(text) = "\e]9;#{text}\a" |
.plain(str) ⇒ String
Remove any BBCode-like and/or ANSI attributes.
264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/terminal/ansi.rb', line 264 def plain(str) unless (str = str.to_s).index('[') return str.index("\e") ? str.gsub(@re_test, '') : str.dup end str = str.gsub(@re_bbcode) do |match_str| match = Regexp.last_match(1) or next match_str next "[#{match[1..]}]" if match[0] == '\\' next match_str if (match = match.split).empty? next if match.all? { @attr_map[_1] } match_str end str.index("\e") ? str.gsub!(@re_test, '') : str end |
.progress(state, percent = 0) ⇒ String
Set task progress state. This is not widely supported; works for Ghostty, iTerm2, Kitty.
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
# File 'lib/terminal/ansi.rb', line 511 def progress(state, percent = 0) case state when :show, true state = 1 when :err, :error state = 2 when :warn, :warning state = 4 when Numeric percent, state = state, 1 when :indeterminate return +PROGRESS_SHOW_INDETERMINATE else return +PROGRESS_HIDE end "\e]9;4;#{state};#{percent.to_i.clamp(0, 100)}\a" end |
.rainbow(str, frequency: 0.3, spread: 0.8, seed: 1.1) ⇒ String
Create nice colored text.
286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/terminal/ansi.rb', line 286 def rainbow(str, frequency: 0.3, spread: 0.8, seed: 1.1) pos = -1 @pi2_third ||= 2.0 * Math::PI / 3.0 @pi4_third ||= 4.0 * Math::PI / 3.0 ( str.to_s.chars.map! do |char| i = (seed + ((pos += 1) / spread)) * frequency "\e[38;2;#{(Math.sin(i) * 255).to_i.abs};" \ "#{(Math.sin(i + @pi2_third) * 255).to_i.abs};" \ "#{(Math.sin(i + @pi4_third) * 255).to_i.abs}m#{char}" end << RESET ).join end |
.scale(text, scale: nil, width: nil, fracn: nil, fracd: nil, vertical: nil, horizontal: nil) ⇒ String
Create scaled text. It uses the text sizing protocol. This is not widely supported; works for Kitty.
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 |
# File 'lib/terminal/ansi.rb', line 555 def scale( text, scale: nil, width: nil, fracn: nil, fracd: nil, vertical: nil, horizontal: nil ) opts = scale ? ["s=#{scale.clamp(1, 7)}"] : [] opts << "w=#{width.clamp(0, 7)}" if width if fracn opts << "n=#{fracn = fracn.clamp(0, 15)}" opts << "d=#{fracd.clamp(fracn + 1, 15)}" if fracd case vertical when 0, :top opts << 'v=0' when 1, :bottom opts << 'v=1' when 2, :centered opts << 'v=2' end case horizontal when 0, :left opts << 'h=0' when 1, :right opts << 'h=1' when 2, :centered opts << 'h=2' end end "\e]66;#{opts.join(':')};#{text}\a" end |
.screen_alternate ⇒ String
Use alternative screen buffer.
418 |
# File 'lib/terminal/ansi.rb', line 418 def screen_alternate = +SCREEN_ALTERNATE |
.screen_alternate_off ⇒ String
Do not longer use alternative screen buffer.
423 |
# File 'lib/terminal/ansi.rb', line 423 def screen_alternate_off = +SCREEN_ALTERNATE_OFF |
.screen_erase(part = :all) ⇒ String
Erase screen part.
403 |
# File 'lib/terminal/ansi.rb', line 403 def screen_erase(part = :all) = "\e[#{@screen_erase[part]}J" |
.screen_restore ⇒ String
Restore current screen.
413 |
# File 'lib/terminal/ansi.rb', line 413 def screen_restore = +SCREEN_RESTORE |
.screen_save ⇒ String
Safe current screen.
408 |
# File 'lib/terminal/ansi.rb', line 408 def screen_save = +SCREEN_SAVE |
.screen_scroll_down(lines = 1) ⇒ String
Scroll window given lines down.
435 |
# File 'lib/terminal/ansi.rb', line 435 def screen_scroll_down(lines = 1) = "\e[#{lines}T" |
.screen_scroll_up(lines = 1) ⇒ String
Scroll window given lines up.
429 |
# File 'lib/terminal/ansi.rb', line 429 def screen_scroll_up(lines = 1) = "\e[#{lines}S" |
.title(title) ⇒ String
Set (tab) title. This is not widely supported; works for Hyper, iTerm2, Kitty, MacOS Terminal, Tabby, WezTerm.
466 |
# File 'lib/terminal/ansi.rb', line 466 def title(title) = "\e]0;#{title}\a" |
.try_convert(attributes, separator: ' ') ⇒ String?
Try to combine given ANSI attributes and colors.
The attributes and colors have to be separated by given separator`.
177 178 179 180 181 |
# File 'lib/terminal/ansi.rb', line 177 def try_convert(attributes, separator: ' ') return unless attributes return if (attributes = attributes.to_s.split(separator)).empty? "\e[#{attributes.map! { @attr_map[_1] || return }.join(';')}m" end |
.unbbcode(str) ⇒ String
Remove embedded BBCode-like attributes.
239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/terminal/ansi.rb', line 239 def unbbcode(str) str = str.to_s return str.dup unless str.index('[') str.gsub(@re_bbcode) do |match_str| match = Regexp.last_match(1) or next match_str next "[#{match[1..]}]" if match[0] == '\\' next match_str if (match = match.split).empty? next if match.all? { @attr_map[_1] } match_str end end |
.undecorate(str) ⇒ String
Remove ANSI functions, attributes and colors from given string.
156 157 158 |
# File 'lib/terminal/ansi.rb', line 156 def undecorate(str) (str = str.to_s).index("\e") ? str.gsub(@re_test, '') : str.dup end |
.valid?(*attributes) ⇒ true, false
Test if all given attributes are valid.
189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/terminal/ansi.rb', line 189 def valid?(*attributes) attributes.all? do |arg| case arg when String @attr_map[arg] when Symbol @attrs_map[arg] when (0..767) true end end end |