Module: Commiti::TerminalUI

Defined in:
lib/services/helpers/terminal_ui.rb

Constant Summary collapse

COLORS =
{
  green: 32,
  red: 31,
  yellow: 33,
  blue: 34,
  cyan: 36,
  magenta: 35,
  gray: 90,
  bold: 1
}.freeze
UNICODE_ICONS =
{
  success: '',
  fail: '',
  info: '',
  warn: ''
}.freeze
ASCII_ICONS =
{
  success: '+',
  fail: 'x',
  info: 'i',
  warn: '!'
}.freeze
UNICODE_MARKERS =
{
  prompt: '',
  header: '',
  bullet: '',
  rule: ''
}.freeze
ASCII_MARKERS =
{
  prompt: '>',
  header: '>',
  bullet: '-',
  rule: '-'
}.freeze

Class Method Summary collapse

Class Method Details



139
140
141
142
# File 'lib/services/helpers/terminal_ui.rb', line 139

def self.banner(title:, subtitle: nil, meta: nil)
  body_lines = [subtitle, meta].compact.join("\n")
  panel(title, body_lines)
end

.bullet(text) ⇒ Object



118
119
120
# File 'lib/services/helpers/terminal_ui.rb', line 118

def self.bullet(text)
  "#{marker(:bullet)} #{text}"
end

.bullets(items) ⇒ Object



122
123
124
# File 'lib/services/helpers/terminal_ui.rb', line 122

def self.bullets(items)
  items.map { |item| bullet(item) }.join("\n")
end

.color(text, *styles) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/services/helpers/terminal_ui.rb', line 71

def self.color(text, *styles)
  return text unless supports_ansi?

  codes = styles.filter_map { |style| COLORS[style] }
  return text if codes.empty?

  "\e[#{codes.join(';')}m#{text}\e[0m"
end

.header(text) ⇒ Object



96
97
98
# File 'lib/services/helpers/terminal_ui.rb', line 96

def self.header(text)
  "#{color(marker(:header), :cyan, :bold)} #{color(text, :bold, :cyan)}"
end

.muted(text) ⇒ Object



104
105
106
# File 'lib/services/helpers/terminal_ui.rb', line 104

def self.muted(text)
  color(text, :gray)
end

.pad_right(text, length) ⇒ Object



126
127
128
129
# File 'lib/services/helpers/terminal_ui.rb', line 126

def self.pad_right(text, length)
  padding = [length - visible_length(text), 0].max
  "#{text}#{' ' * padding}"
end

.panel(title, body) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/services/helpers/terminal_ui.rb', line 108

def self.panel(title, body)
  [
    separator,
    header(title),
    separator,
    body.to_s.rstrip,
    separator
  ].join("\n")
end

.prompt(text) ⇒ Object



100
101
102
# File 'lib/services/helpers/terminal_ui.rb', line 100

def self.prompt(text)
  "#{color(marker(:prompt), :cyan, :bold)} #{text}"
end

.separator(length = nil) ⇒ Object



91
92
93
94
# File 'lib/services/helpers/terminal_ui.rb', line 91

def self.separator(length = nil)
  char = marker(:rule)
  color(char * (length || width), :gray)
end

.status(kind, text) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/services/helpers/terminal_ui.rb', line 80

def self.status(kind, text)
  symbol = icon_for(kind)
  color_style = case kind
                when :success then :green
                when :fail then :red
                when :warn then :yellow
                else :blue
                end
  "#{color(symbol, color_style, :bold)} #{text}"
end

.strip_ansi(text) ⇒ Object



135
136
137
# File 'lib/services/helpers/terminal_ui.rb', line 135

def self.strip_ansi(text)
  text.to_s.gsub(/\e\[[0-9;]*m/, '')
end

.supports_ansi?Boolean

Returns:

  • (Boolean)


46
47
48
49
50
51
52
# File 'lib/services/helpers/terminal_ui.rb', line 46

def self.supports_ansi?
  return false unless $stdout.tty?
  return false if ENV.key?('NO_COLOR')

  term = ENV.fetch('TERM', '').downcase
  term != 'dumb'
end

.supports_unicode?Boolean

Returns:

  • (Boolean)


54
55
56
57
58
59
# File 'lib/services/helpers/terminal_ui.rb', line 54

def self.supports_unicode?
  encoding = $stdout.external_encoding || Encoding.default_external
  encoding.name.upcase.include?('UTF-8')
rescue StandardError
  false
end

.visible_length(text) ⇒ Object



131
132
133
# File 'lib/services/helpers/terminal_ui.rb', line 131

def self.visible_length(text)
  strip_ansi(text).length
end

.widthObject



61
62
63
64
65
66
67
68
69
# File 'lib/services/helpers/terminal_ui.rb', line 61

def self.width
  cols = IO.console&.winsize&.last
  cols = ENV.fetch('COLUMNS', nil) if cols.nil? || cols <= 0
  cols = cols.to_i
  cols = 80 if cols <= 0
  [cols, 120].min
rescue StandardError
  80
end