-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfancy_box.rb
163 lines (129 loc) · 4.97 KB
/
fancy_box.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
# typed: true
# frozen_string_literal: true
require 'cli/ui'
include CLI::UI
module FancyBox
extend Frame::FrameStyle
VERTICAL = '║'
HORIZONTAL = '═'
TOP_LEFT = '╔'
DIVIDER = '╠'
BOTTOM_LEFT = '╚'
TOP_RIGHT = '╗'
DIVIDER_END = '╣'
BOTTOM_RIGHT = '╝'
TEXT_PRE = '❱'
TEXT_POST = '❰'
@@box_width = Terminal.width
@@color = Color::WHITE.code
class << self
extend T::Sig
sig { override.params(width: String).returns(Integer) }
def width=(width)
@@box_width = width
end
sig { override.returns(Symbol) }
def style_name
:fancy_box
end
sig { override.returns(String) }
def prefix
VERTICAL
end
sig { override.returns(String) }
def lineterm
print_at_x(@@box_width - 1, @@color + VERTICAL)
end
# ╔══ Open ═══════════════════════════════════════════════════╗
#
sig { override.params(text: String, color: Color).returns(String) }
def start(text, color:)
edge(text, color: color, first: TOP_LEFT, last: TOP_RIGHT)
end
# ╠══ Divider ════════════════════════════════════════════════╣
#
sig { override.params(text: String, color: Color).returns(String) }
def divider(text, color:)
edge(text, color: color, first: DIVIDER, last: DIVIDER_END)
end
# ╚══ Close ══════════════════════════════════════════════════╝
#
sig { override.params(text: String, color: Color, right_text: T.nilable(String)).returns(String) }
def close(text, color:, right_text: nil)
edge(text, color: color, right_text: right_text, first: BOTTOM_LEFT, last: BOTTOM_RIGHT)
end
private
sig do
params(text: String, color: Color, first: String, right_text: T.nilable(String)).returns(String)
end
def edge(text, color:, first:, last:, right_text: nil)
# We save the current color so #lineterm can use it
@@color = color.code
preamble = +''
preamble << color.code if CLI::UI.enable_color?
preamble << first << (HORIZONTAL * 2)
unless text.empty?
preamble << TEXT_PRE << ' '
preamble << CLI::UI.resolve_text("{{#{color.name}:#{text}}}")
preamble << color.code if CLI::UI.enable_color?
preamble << ' ' << TEXT_POST
end
termwidth = @@box_width
suffix = +''
if right_text
suffix << TEXT_PRE << ' ' << right_text << ' ' << TEXT_POST
end
preamble_width = ANSI.printing_width(preamble)
preamble_start = Frame.prefix_width
# If prefix_width is non-zero, we need to subtract the width of
# the final space, since we're going to write over it.
preamble_start -= 1 if preamble_start.nonzero?
preamble_end = preamble_start + preamble_width
suffix_width = ANSI.printing_width(suffix)
suffix_end = termwidth - 2
suffix_start = suffix_end - suffix_width
if preamble_end > suffix_start
suffix = ''
# if preamble_end > termwidth
# we *could* truncate it, but let's just let it overflow to the
# next line and call it poor usage of this API.
end
o = +''
unless CLI::UI.enable_cursor?
linewidth = [0, termwidth - (preamble_end + suffix_width + 1)].max
o << color.code if CLI::UI.enable_color?
o << preamble
o << color.code if CLI::UI.enable_color?
o << (HORIZONTAL * linewidth)
o << color.code if CLI::UI.enable_color?
o << suffix
o << Color::RESET.code if CLI::UI.enable_color?
o << "\n"
return o
end
# Jumping around the line can cause some unwanted flashes
o << ANSI.hide_cursor
# reset to column 1 so that things like ^C don't ruin formatting
o << "\r"
# This code will print out a full line with the given preamble and
# suffix, as exemplified below.
#
# preamble_start suffix_start
# | preamble_end | suffix_end
# | | | | termwidth
# | | | | |
# V V V V V
# |-- Preamble text --------------------- suffix text -|
o << color.code if CLI::UI.enable_color?
o << print_at_x(preamble_start, HORIZONTAL * (termwidth - preamble_start)) # draw a full line
o << print_at_x(termwidth - 1, last)
o << print_at_x(preamble_start, preamble)
o << color.code if CLI::UI.enable_color?
o << print_at_x(suffix_start, suffix)
o << Color::RESET.code if CLI::UI.enable_color?
o << ANSI.show_cursor
o << "\n"
o
end
end
end