Module: MMMD::TextManager

Included in:
Renderers::Plainterm
Defined in:
lib/mmmd/renderers/plainterm.rb

Overview

Module for managing terminal output

Instance Method Summary collapse

Instance Method Details

#_indent(text) ⇒ Object

Indent all lines (inner)



222
223
224
225
226
# File 'lib/mmmd/renderers/plainterm.rb', line 222

def _indent(text)
  text.lines.map do |line|
    "    #{line}"
  end.join("")
end

#bg(text, options) ⇒ String

ANSI SGR escape code for bg color

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/mmmd/renderers/plainterm.rb', line 13

def bg(text, options)
  color = options['bg']
  if color.is_a? Integer
    "\e[48;5;#{color}m#{text}\e[49m"
  elsif color.is_a? String and color.match?(/\A#[A-Fa-f0-9]{6}\Z/)
    vector = color.scan(/[A-Fa-f0-9]{2}/).map { |x| x.to_i(16) }
    "\e[48;2;#{vector[0]};#{vector[1]};#{vector[2]}\e[49m"
  else
    Kernel.warn "WARNING: Invalid color - #{color}"
    text
  end
end

#bold(text, _options) ⇒ String

ANSI SGR escape code for bold text

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


47
48
49
# File 'lib/mmmd/renderers/plainterm.rb', line 47

def bold(text, _options)
  "\e[1m#{text}\e[22m"
end

#box(text, options) ⇒ String

Draw a screen-width box around text

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


156
157
158
159
160
161
162
163
164
165
166
# File 'lib/mmmd/renderers/plainterm.rb', line 156

def box(text, options)
  size = options[:hsize] - 2
  text = wordwrap(text, (size * 0.8).floor).lines.filter_map do |line|
    "#{ljust_cc(line, size)}" unless line.empty?
  end.join("\n")
  <<~TEXT
#{'' * size}    #{text}
#{'' * size}  TEXT
end

#bullet(text, _options) ⇒ Object

Bulletpoints



236
237
238
# File 'lib/mmmd/renderers/plainterm.rb', line 236

def bullet(text, _options)
  "-#{_indent(text)[1..]}"
end

#center(text, options) ⇒ Object

Draw text centered



177
178
179
180
181
182
# File 'lib/mmmd/renderers/plainterm.rb', line 177

def center(text, options)
  size = options[:hsize]
  wordwrap(text, (size * 0.8).floor).lines.filter_map do |line|
    center_cc(line, size) unless line.empty?
  end.join("\n")
end

#center_cc(text, size) ⇒ String

Center-justify a line while ignoring terminal control codes

Parameters:

  • text (String)
  • size (Integer)

Returns:

  • (String)


138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/mmmd/renderers/plainterm.rb', line 138

def center_cc(text, size)
  text.lines.map do |line|
    textlength = smort_length(line)
    if textlength < size
      freelength = size - textlength
      rightlength = freelength / 2
      leftlength = freelength - rightlength
      " " * leftlength + line + " " * rightlength
    else
      line
    end
  end.join("\n")
end

#extra_newlines(text, options) ⇒ Object

Add extra newlines around the text



200
201
202
203
204
205
206
# File 'lib/mmmd/renderers/plainterm.rb', line 200

def extra_newlines(text, options)
  size = options[:hsize]
  textlines = text.lines
  textlines.prepend("#{' ' * size}\n")
  textlines.append("\n#{' ' * size}\n")
  textlines.join("")
end

#fg(text, options) ⇒ String

ANSI SGR escape code for fg color

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/mmmd/renderers/plainterm.rb', line 30

def fg(text, options)
  color = options['fg']
  if color.is_a? Integer
    "\e[38;5;#{color}m#{text}\e[39m"
  elsif color.is_a? String and color.match?(/\A#[A-Fa-f0-9]{6}\Z/)
    vector = color.scan(/[A-Fa-f0-9]{2}/).map { |x| x.to_i(16) }
    "\e[38;2;#{vector[0]};#{vector[1]};#{vector[2]}\e[39m"
  else
    Kernel.warn "WARNING: Invalid color - #{color}"
    text
  end
end

#indent(text, _options) ⇒ Object

Indent all lines



217
218
219
# File 'lib/mmmd/renderers/plainterm.rb', line 217

def indent(text, _options)
  _indent(text)
end

#italics(text, _options) ⇒ String

ANSI SGR escape code for italics text

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


55
56
57
# File 'lib/mmmd/renderers/plainterm.rb', line 55

def italics(text, _options)
  "\e[3m#{text}\e[23m"
end

#leftline(text, _options) ⇒ Object

Left overline all lines



229
230
231
232
233
# File 'lib/mmmd/renderers/plainterm.rb', line 229

def leftline(text, _options)
  text.lines.map do |line|
    "#{line}"
  end.join("")
end

#ljust_cc(text, size) ⇒ String

Left-justify a line while ignoring terminal control codes

Parameters:

  • text (String)
  • size (Integer)

Returns:

  • (String)


116
117
118
119
120
121
# File 'lib/mmmd/renderers/plainterm.rb', line 116

def ljust_cc(text, size)
  text.lines.map do |line|
    textlength = smort_length(line)
    textlength < size ? line + " " * (size - textlength) : line
  end.join("\n")
end

#numbered(text, options) ⇒ Object

Numbers



241
242
243
244
245
246
# File 'lib/mmmd/renderers/plainterm.rb', line 241

def numbered(text, options)
  number = options[:number]
  length = number.to_s.length + 1
  (length / 4 + 1).times { text = _indent(text) }
  "#{number}.#{text[length..]}"
end

#rjust(text, options) ⇒ Object

Draw text right-justified



169
170
171
172
173
174
# File 'lib/mmmd/renderers/plainterm.rb', line 169

def rjust(text, options)
  size = options[:hsize]
  wordwrap(text, (size * 0.8).floor).lines.filter_map do |line|
    rjust_cc(line, size) unless line.empty?
  end.join("\n")
end

#rjust_cc(text, size) ⇒ String

Right-justify a line while ignoring terminal control codes

Parameters:

  • text (String)
  • size (Integer)

Returns:

  • (String)


127
128
129
130
131
132
# File 'lib/mmmd/renderers/plainterm.rb', line 127

def rjust_cc(text, size)
  text.lines.map do |line|
    textlength = smort_length(line)
    textlength < size ? " " * (size - textlength) + line : line
  end.join("\n")
end

#smort_length(text) ⇒ Integer

(TODO: smorter stronger better faster) SmЯt™ word length

Parameters:

  • text (String)

Returns:

  • (Integer)


108
109
110
# File 'lib/mmmd/renderers/plainterm.rb', line 108

def smort_length(text)
  text.gsub(/\e\[[^m]+m/, '').length
end

#strikethrough(text, _options) ⇒ String

ANSI SGR escape code for strikethrough text

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


71
72
73
# File 'lib/mmmd/renderers/plainterm.rb', line 71

def strikethrough(text, _options)
  "\e[9m#{text}\e[29m"
end

#underline(text, _options) ⇒ String

ANSI SGR escape code for underline text

Parameters:

  • text (String)
  • options (Hash)

Returns:

  • (String)


63
64
65
# File 'lib/mmmd/renderers/plainterm.rb', line 63

def underline(text, _options)
  "\e[4m#{text}\e[24m"
end

#underline_block(text, options) ⇒ Object

Underline the last line of the text piece



185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/mmmd/renderers/plainterm.rb', line 185

def underline_block(text, options)
  textlines = text.lines
  last = "".match(/()()()/)
  textlines.each do |x|
    current = x.match(/\A(\s*)(.+?)(\s*)\Z/)
    last = current if smort_length(current[2]) > smort_length(last[2])
  end
  ltxt = last[1]
  ctxt = textlines.last.slice(last.offset(2)[0]..last.offset(2)[1] - 1)
  rtxt = last[3]
  textlines[-1] = [ltxt, underline(ctxt, options), rtxt].join('')
  textlines.join("")
end

#underline_full_block(text, options) ⇒ Object

Underline last line edge to edge



209
210
211
212
213
214
# File 'lib/mmmd/renderers/plainterm.rb', line 209

def underline_full_block(text, options)
  textlines = text.lines
  last_line = textlines.last.match(/^.*$/)[0]
  textlines[-1] = "#{underline(last_line, options)}\n"
  textlines.join("")
end

#wordwrap(text, width) ⇒ String

Word wrapping algorithm

Parameters:

  • text (String)
  • width (Integer)

Returns:

  • (String)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/mmmd/renderers/plainterm.rb', line 79

def wordwrap(text, width)
  words = text.split(/( +)/)
  output = []
  line = ""
  length = 0
  until words.empty?
    word = words.shift
    wordlength = smort_length(word)
    if wordlength > width
      words.prepend(word[width..])
      word = word[..width - 1]
    end
    if length + wordlength + 1 > width
      output.append(line.lstrip)
      line = word
      length = wordlength
      next
    end
    length += wordlength
    line += word
  end
  output.append(line.lstrip)
  output.join("\n")
end