Module: Architext::Terminal
- Defined in:
- lib/architext/terminal.rb
Constant Summary collapse
- RESET =
"\e[0m"- HIDE_CURSOR =
"\e[?25l"- SHOW_CURSOR =
"\e[?25h"- CLEAR =
"\e[2J"- CLEAR_TO_END =
"\e[J"- CLEAR_LINE =
"\e[2K"- HOME =
"\e[H"- ALT_SCREEN =
"\e[?1049h"- MAIN_SCREEN =
"\e[?1049l"- PALETTE =
{ ink: "\e[38;2;221;231;239m", white: "\e[38;2;255;255;255m", dim: "\e[38;2;126;140;155m", faint: "\e[38;2;83;96;112m", cyan: "\e[38;2;91;220;255m", blue: "\e[38;2;98;151;255m", green: "\e[38;2;91;232;184m", amber: "\e[38;2;245;196;94m", red: "\e[38;2;255;104;112m", violet: "\e[38;2;190;142;255m", bold: "\e[1m", inverse: "\e[7m" }.freeze
- TAGS =
PALETTE.transform_keys(&:to_s).merge('/' => RESET).freeze
Class Method Summary collapse
- .alt_screen_supported?(io = $stdout) ⇒ Boolean
- .char_display_width(char) ⇒ Object
- .combining_mark?(codepoint) ⇒ Boolean
- .display_width(text) ⇒ Object
- .dumb_terminal? ⇒ Boolean
- .enabled?(io = $stdout) ⇒ Boolean
- .paint(text, *styles, enabled: true) ⇒ Object
-
.render(markup, enabled: true) ⇒ Object
Tiny pretext-style renderer: “[cyan]text” keeps visual markup readable.
- .strip_ansi(text) ⇒ Object
- .strip_markup(markup) ⇒ Object
- .truncate(text, width) ⇒ Object
- .truncate_plain(text, width) ⇒ Object
- .visible_length(text) ⇒ Object
- .wide_codepoint?(codepoint) ⇒ Boolean
Class Method Details
.alt_screen_supported?(io = $stdout) ⇒ Boolean
38 39 40 |
# File 'lib/architext/terminal.rb', line 38 def alt_screen_supported?(io = $stdout) enabled?(io) && ENV['ARCHITEXT_NO_ALT_SCREEN'].nil? end |
.char_display_width(char) ⇒ Object
96 97 98 99 100 101 102 103 |
# File 'lib/architext/terminal.rb', line 96 def char_display_width(char) codepoint = char.ord return 0 if codepoint < 32 || codepoint == 0x7F return 0 if combining_mark?(codepoint) return 2 if wide_codepoint?(codepoint) 1 end |
.combining_mark?(codepoint) ⇒ Boolean
105 106 107 108 109 110 111 |
# File 'lib/architext/terminal.rb', line 105 def combining_mark?(codepoint) (0x0300..0x036F).cover?(codepoint) || (0x1AB0..0x1AFF).cover?(codepoint) || (0x1DC0..0x1DFF).cover?(codepoint) || (0x20D0..0x20FF).cover?(codepoint) || (0xFE00..0xFE0F).cover?(codepoint) end |
.display_width(text) ⇒ Object
92 93 94 |
# File 'lib/architext/terminal.rb', line 92 def display_width(text) text.to_s.each_char.sum { |char| char_display_width(char) } end |
.dumb_terminal? ⇒ Boolean
126 127 128 |
# File 'lib/architext/terminal.rb', line 126 def dumb_terminal? ENV.fetch('TERM', '').downcase == 'dumb' end |
.enabled?(io = $stdout) ⇒ Boolean
34 35 36 |
# File 'lib/architext/terminal.rb', line 34 def enabled?(io = $stdout) io.respond_to?(:tty?) && io.tty? && ENV['NO_COLOR'].nil? && !dumb_terminal? end |
.paint(text, *styles, enabled: true) ⇒ Object
42 43 44 45 46 |
# File 'lib/architext/terminal.rb', line 42 def paint(text, *styles, enabled: true) return text.to_s unless enabled styles.map { |style| PALETTE.fetch(style) }.join + text.to_s + RESET end |
.render(markup, enabled: true) ⇒ Object
Tiny pretext-style renderer: “[cyan]text” keeps visual markup readable.
49 50 51 52 53 |
# File 'lib/architext/terminal.rb', line 49 def render(markup, enabled: true) return strip_markup(markup) unless enabled markup.to_s.gsub(%r{\[(/|[a-z_]+)\]}) { TAGS.fetch(Regexp.last_match(1), Regexp.last_match(0)) } end |
.strip_ansi(text) ⇒ Object
71 72 73 |
# File 'lib/architext/terminal.rb', line 71 def strip_ansi(text) text.to_s.gsub(/\e\[[0-9;?]*[A-Za-z]/, '') end |
.strip_markup(markup) ⇒ Object
55 56 57 |
# File 'lib/architext/terminal.rb', line 55 def strip_markup(markup) markup.to_s.gsub(%r{\[(/|[a-z_]+)\]}, '') end |
.truncate(text, width) ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/architext/terminal.rb', line 63 def truncate(text, width) plain = text.to_s return '' if width <= 0 return plain if visible_length(plain) <= width truncate_plain(strip_ansi(plain), width) end |
.truncate_plain(text, width) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/architext/terminal.rb', line 75 def truncate_plain(text, width) return '' if width <= 0 return text.to_s if display_width(text) <= width return text.to_s.each_char.first.to_s if width <= 1 out = +'' used = 0 text.to_s.each_char do |char| char_width = char_display_width(char) break if used + char_width > width - 3 out << char used += char_width end "#{out}..." end |
.visible_length(text) ⇒ Object
59 60 61 |
# File 'lib/architext/terminal.rb', line 59 def visible_length(text) display_width(strip_ansi(text)) end |
.wide_codepoint?(codepoint) ⇒ Boolean
113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/architext/terminal.rb', line 113 def wide_codepoint?(codepoint) (0x1100..0x115F).cover?(codepoint) || (0x2329..0x232A).cover?(codepoint) || (0x2E80..0xA4CF).cover?(codepoint) || (0xAC00..0xD7A3).cover?(codepoint) || (0xF900..0xFAFF).cover?(codepoint) || (0xFE10..0xFE19).cover?(codepoint) || (0xFE30..0xFE6F).cover?(codepoint) || (0xFF00..0xFF60).cover?(codepoint) || (0xFFE0..0xFFE6).cover?(codepoint) || (0x1F000..0x1FAFF).cover?(codepoint) end |