main
1package lipgloss
2
3// Set a value on the underlying rules map.
4func (s *Style) set(key propKey, value interface{}) {
5 // We don't allow negative integers on any of our other values, so just keep
6 // them at zero or above. We could use uints instead, but the
7 // conversions are a little tedious, so we're sticking with ints for
8 // sake of usability.
9 switch key { //nolint:exhaustive
10 case foregroundKey:
11 s.fgColor = colorOrNil(value)
12 case backgroundKey:
13 s.bgColor = colorOrNil(value)
14 case widthKey:
15 s.width = max(0, value.(int))
16 case heightKey:
17 s.height = max(0, value.(int))
18 case alignHorizontalKey:
19 s.alignHorizontal = value.(Position)
20 case alignVerticalKey:
21 s.alignVertical = value.(Position)
22 case paddingTopKey:
23 s.paddingTop = max(0, value.(int))
24 case paddingRightKey:
25 s.paddingRight = max(0, value.(int))
26 case paddingBottomKey:
27 s.paddingBottom = max(0, value.(int))
28 case paddingLeftKey:
29 s.paddingLeft = max(0, value.(int))
30 case marginTopKey:
31 s.marginTop = max(0, value.(int))
32 case marginRightKey:
33 s.marginRight = max(0, value.(int))
34 case marginBottomKey:
35 s.marginBottom = max(0, value.(int))
36 case marginLeftKey:
37 s.marginLeft = max(0, value.(int))
38 case marginBackgroundKey:
39 s.marginBgColor = colorOrNil(value)
40 case borderStyleKey:
41 s.borderStyle = value.(Border)
42 case borderTopForegroundKey:
43 s.borderTopFgColor = colorOrNil(value)
44 case borderRightForegroundKey:
45 s.borderRightFgColor = colorOrNil(value)
46 case borderBottomForegroundKey:
47 s.borderBottomFgColor = colorOrNil(value)
48 case borderLeftForegroundKey:
49 s.borderLeftFgColor = colorOrNil(value)
50 case borderTopBackgroundKey:
51 s.borderTopBgColor = colorOrNil(value)
52 case borderRightBackgroundKey:
53 s.borderRightBgColor = colorOrNil(value)
54 case borderBottomBackgroundKey:
55 s.borderBottomBgColor = colorOrNil(value)
56 case borderLeftBackgroundKey:
57 s.borderLeftBgColor = colorOrNil(value)
58 case maxWidthKey:
59 s.maxWidth = max(0, value.(int))
60 case maxHeightKey:
61 s.maxHeight = max(0, value.(int))
62 case tabWidthKey:
63 // TabWidth is the only property that may have a negative value (and
64 // that negative value can be no less than -1).
65 s.tabWidth = value.(int)
66 case transformKey:
67 s.transform = value.(func(string) string)
68 default:
69 if v, ok := value.(bool); ok { //nolint:nestif
70 if v {
71 s.attrs |= int(key)
72 } else {
73 s.attrs &^= int(key)
74 }
75 } else if attrs, ok := value.(int); ok {
76 // bool attrs
77 if attrs&int(key) != 0 {
78 s.attrs |= int(key)
79 } else {
80 s.attrs &^= int(key)
81 }
82 }
83 }
84
85 // Set the prop on
86 s.props = s.props.set(key)
87}
88
89// setFrom sets the property from another style.
90func (s *Style) setFrom(key propKey, i Style) {
91 switch key { //nolint:exhaustive
92 case foregroundKey:
93 s.set(foregroundKey, i.fgColor)
94 case backgroundKey:
95 s.set(backgroundKey, i.bgColor)
96 case widthKey:
97 s.set(widthKey, i.width)
98 case heightKey:
99 s.set(heightKey, i.height)
100 case alignHorizontalKey:
101 s.set(alignHorizontalKey, i.alignHorizontal)
102 case alignVerticalKey:
103 s.set(alignVerticalKey, i.alignVertical)
104 case paddingTopKey:
105 s.set(paddingTopKey, i.paddingTop)
106 case paddingRightKey:
107 s.set(paddingRightKey, i.paddingRight)
108 case paddingBottomKey:
109 s.set(paddingBottomKey, i.paddingBottom)
110 case paddingLeftKey:
111 s.set(paddingLeftKey, i.paddingLeft)
112 case marginTopKey:
113 s.set(marginTopKey, i.marginTop)
114 case marginRightKey:
115 s.set(marginRightKey, i.marginRight)
116 case marginBottomKey:
117 s.set(marginBottomKey, i.marginBottom)
118 case marginLeftKey:
119 s.set(marginLeftKey, i.marginLeft)
120 case marginBackgroundKey:
121 s.set(marginBackgroundKey, i.marginBgColor)
122 case borderStyleKey:
123 s.set(borderStyleKey, i.borderStyle)
124 case borderTopForegroundKey:
125 s.set(borderTopForegroundKey, i.borderTopFgColor)
126 case borderRightForegroundKey:
127 s.set(borderRightForegroundKey, i.borderRightFgColor)
128 case borderBottomForegroundKey:
129 s.set(borderBottomForegroundKey, i.borderBottomFgColor)
130 case borderLeftForegroundKey:
131 s.set(borderLeftForegroundKey, i.borderLeftFgColor)
132 case borderTopBackgroundKey:
133 s.set(borderTopBackgroundKey, i.borderTopBgColor)
134 case borderRightBackgroundKey:
135 s.set(borderRightBackgroundKey, i.borderRightBgColor)
136 case borderBottomBackgroundKey:
137 s.set(borderBottomBackgroundKey, i.borderBottomBgColor)
138 case borderLeftBackgroundKey:
139 s.set(borderLeftBackgroundKey, i.borderLeftBgColor)
140 case maxWidthKey:
141 s.set(maxWidthKey, i.maxWidth)
142 case maxHeightKey:
143 s.set(maxHeightKey, i.maxHeight)
144 case tabWidthKey:
145 s.set(tabWidthKey, i.tabWidth)
146 case transformKey:
147 s.set(transformKey, i.transform)
148 default:
149 // Set attributes for set bool properties
150 s.set(key, i.attrs)
151 }
152}
153
154func colorOrNil(c interface{}) TerminalColor {
155 if c, ok := c.(TerminalColor); ok {
156 return c
157 }
158 return nil
159}
160
161// Bold sets a bold formatting rule.
162func (s Style) Bold(v bool) Style {
163 s.set(boldKey, v)
164 return s
165}
166
167// Italic sets an italic formatting rule. In some terminal emulators this will
168// render with "reverse" coloring if not italic font variant is available.
169func (s Style) Italic(v bool) Style {
170 s.set(italicKey, v)
171 return s
172}
173
174// Underline sets an underline rule. By default, underlines will not be drawn on
175// whitespace like margins and padding. To change this behavior set
176// UnderlineSpaces.
177func (s Style) Underline(v bool) Style {
178 s.set(underlineKey, v)
179 return s
180}
181
182// Strikethrough sets a strikethrough rule. By default, strikes will not be
183// drawn on whitespace like margins and padding. To change this behavior set
184// StrikethroughSpaces.
185func (s Style) Strikethrough(v bool) Style {
186 s.set(strikethroughKey, v)
187 return s
188}
189
190// Reverse sets a rule for inverting foreground and background colors.
191func (s Style) Reverse(v bool) Style {
192 s.set(reverseKey, v)
193 return s
194}
195
196// Blink sets a rule for blinking foreground text.
197func (s Style) Blink(v bool) Style {
198 s.set(blinkKey, v)
199 return s
200}
201
202// Faint sets a rule for rendering the foreground color in a dimmer shade.
203func (s Style) Faint(v bool) Style {
204 s.set(faintKey, v)
205 return s
206}
207
208// Foreground sets a foreground color.
209//
210// // Sets the foreground to blue
211// s := lipgloss.NewStyle().Foreground(lipgloss.Color("#0000ff"))
212//
213// // Removes the foreground color
214// s.Foreground(lipgloss.NoColor)
215func (s Style) Foreground(c TerminalColor) Style {
216 s.set(foregroundKey, c)
217 return s
218}
219
220// Background sets a background color.
221func (s Style) Background(c TerminalColor) Style {
222 s.set(backgroundKey, c)
223 return s
224}
225
226// Width sets the width of the block before applying margins. The width, if
227// set, also determines where text will wrap.
228func (s Style) Width(i int) Style {
229 s.set(widthKey, i)
230 return s
231}
232
233// Height sets the height of the block before applying margins. If the height of
234// the text block is less than this value after applying padding (or not), the
235// block will be set to this height.
236func (s Style) Height(i int) Style {
237 s.set(heightKey, i)
238 return s
239}
240
241// Align is a shorthand method for setting horizontal and vertical alignment.
242//
243// With one argument, the position value is applied to the horizontal alignment.
244//
245// With two arguments, the value is applied to the horizontal and vertical
246// alignments, in that order.
247func (s Style) Align(p ...Position) Style {
248 if len(p) > 0 {
249 s.set(alignHorizontalKey, p[0])
250 }
251 if len(p) > 1 {
252 s.set(alignVerticalKey, p[1])
253 }
254 return s
255}
256
257// AlignHorizontal sets a horizontal text alignment rule.
258func (s Style) AlignHorizontal(p Position) Style {
259 s.set(alignHorizontalKey, p)
260 return s
261}
262
263// AlignVertical sets a vertical text alignment rule.
264func (s Style) AlignVertical(p Position) Style {
265 s.set(alignVerticalKey, p)
266 return s
267}
268
269// Padding is a shorthand method for setting padding on all sides at once.
270//
271// With one argument, the value is applied to all sides.
272//
273// With two arguments, the value is applied to the vertical and horizontal
274// sides, in that order.
275//
276// With three arguments, the value is applied to the top side, the horizontal
277// sides, and the bottom side, in that order.
278//
279// With four arguments, the value is applied clockwise starting from the top
280// side, followed by the right side, then the bottom, and finally the left.
281//
282// With more than four arguments no padding will be added.
283func (s Style) Padding(i ...int) Style {
284 top, right, bottom, left, ok := whichSidesInt(i...)
285 if !ok {
286 return s
287 }
288
289 s.set(paddingTopKey, top)
290 s.set(paddingRightKey, right)
291 s.set(paddingBottomKey, bottom)
292 s.set(paddingLeftKey, left)
293 return s
294}
295
296// PaddingLeft adds padding on the left.
297func (s Style) PaddingLeft(i int) Style {
298 s.set(paddingLeftKey, i)
299 return s
300}
301
302// PaddingRight adds padding on the right.
303func (s Style) PaddingRight(i int) Style {
304 s.set(paddingRightKey, i)
305 return s
306}
307
308// PaddingTop adds padding to the top of the block.
309func (s Style) PaddingTop(i int) Style {
310 s.set(paddingTopKey, i)
311 return s
312}
313
314// PaddingBottom adds padding to the bottom of the block.
315func (s Style) PaddingBottom(i int) Style {
316 s.set(paddingBottomKey, i)
317 return s
318}
319
320// ColorWhitespace determines whether or not the background color should be
321// applied to the padding. This is true by default as it's more than likely the
322// desired and expected behavior, but it can be disabled for certain graphic
323// effects.
324//
325// Deprecated: Just use margins and padding.
326func (s Style) ColorWhitespace(v bool) Style {
327 s.set(colorWhitespaceKey, v)
328 return s
329}
330
331// Margin is a shorthand method for setting margins on all sides at once.
332//
333// With one argument, the value is applied to all sides.
334//
335// With two arguments, the value is applied to the vertical and horizontal
336// sides, in that order.
337//
338// With three arguments, the value is applied to the top side, the horizontal
339// sides, and the bottom side, in that order.
340//
341// With four arguments, the value is applied clockwise starting from the top
342// side, followed by the right side, then the bottom, and finally the left.
343//
344// With more than four arguments no margin will be added.
345func (s Style) Margin(i ...int) Style {
346 top, right, bottom, left, ok := whichSidesInt(i...)
347 if !ok {
348 return s
349 }
350
351 s.set(marginTopKey, top)
352 s.set(marginRightKey, right)
353 s.set(marginBottomKey, bottom)
354 s.set(marginLeftKey, left)
355 return s
356}
357
358// MarginLeft sets the value of the left margin.
359func (s Style) MarginLeft(i int) Style {
360 s.set(marginLeftKey, i)
361 return s
362}
363
364// MarginRight sets the value of the right margin.
365func (s Style) MarginRight(i int) Style {
366 s.set(marginRightKey, i)
367 return s
368}
369
370// MarginTop sets the value of the top margin.
371func (s Style) MarginTop(i int) Style {
372 s.set(marginTopKey, i)
373 return s
374}
375
376// MarginBottom sets the value of the bottom margin.
377func (s Style) MarginBottom(i int) Style {
378 s.set(marginBottomKey, i)
379 return s
380}
381
382// MarginBackground sets the background color of the margin. Note that this is
383// also set when inheriting from a style with a background color. In that case
384// the background color on that style will set the margin color on this style.
385func (s Style) MarginBackground(c TerminalColor) Style {
386 s.set(marginBackgroundKey, c)
387 return s
388}
389
390// Border is shorthand for setting the border style and which sides should
391// have a border at once. The variadic argument sides works as follows:
392//
393// With one value, the value is applied to all sides.
394//
395// With two values, the values are applied to the vertical and horizontal
396// sides, in that order.
397//
398// With three values, the values are applied to the top side, the horizontal
399// sides, and the bottom side, in that order.
400//
401// With four values, the values are applied clockwise starting from the top
402// side, followed by the right side, then the bottom, and finally the left.
403//
404// With more than four arguments the border will be applied to all sides.
405//
406// Examples:
407//
408// // Applies borders to the top and bottom only
409// lipgloss.NewStyle().Border(lipgloss.NormalBorder(), true, false)
410//
411// // Applies rounded borders to the right and bottom only
412// lipgloss.NewStyle().Border(lipgloss.RoundedBorder(), false, true, true, false)
413func (s Style) Border(b Border, sides ...bool) Style {
414 s.set(borderStyleKey, b)
415
416 top, right, bottom, left, ok := whichSidesBool(sides...)
417 if !ok {
418 top = true
419 right = true
420 bottom = true
421 left = true
422 }
423
424 s.set(borderTopKey, top)
425 s.set(borderRightKey, right)
426 s.set(borderBottomKey, bottom)
427 s.set(borderLeftKey, left)
428
429 return s
430}
431
432// BorderStyle defines the Border on a style. A Border contains a series of
433// definitions for the sides and corners of a border.
434//
435// Note that if border visibility has not been set for any sides when setting
436// the border style, the border will be enabled for all sides during rendering.
437//
438// You can define border characters as you'd like, though several default
439// styles are included: NormalBorder(), RoundedBorder(), BlockBorder(),
440// OuterHalfBlockBorder(), InnerHalfBlockBorder(), ThickBorder(),
441// and DoubleBorder().
442//
443// Example:
444//
445// lipgloss.NewStyle().BorderStyle(lipgloss.ThickBorder())
446func (s Style) BorderStyle(b Border) Style {
447 s.set(borderStyleKey, b)
448 return s
449}
450
451// BorderTop determines whether or not to draw a top border.
452func (s Style) BorderTop(v bool) Style {
453 s.set(borderTopKey, v)
454 return s
455}
456
457// BorderRight determines whether or not to draw a right border.
458func (s Style) BorderRight(v bool) Style {
459 s.set(borderRightKey, v)
460 return s
461}
462
463// BorderBottom determines whether or not to draw a bottom border.
464func (s Style) BorderBottom(v bool) Style {
465 s.set(borderBottomKey, v)
466 return s
467}
468
469// BorderLeft determines whether or not to draw a left border.
470func (s Style) BorderLeft(v bool) Style {
471 s.set(borderLeftKey, v)
472 return s
473}
474
475// BorderForeground is a shorthand function for setting all of the
476// foreground colors of the borders at once. The arguments work as follows:
477//
478// With one argument, the argument is applied to all sides.
479//
480// With two arguments, the arguments are applied to the vertical and horizontal
481// sides, in that order.
482//
483// With three arguments, the arguments are applied to the top side, the
484// horizontal sides, and the bottom side, in that order.
485//
486// With four arguments, the arguments are applied clockwise starting from the
487// top side, followed by the right side, then the bottom, and finally the left.
488//
489// With more than four arguments nothing will be set.
490func (s Style) BorderForeground(c ...TerminalColor) Style {
491 if len(c) == 0 {
492 return s
493 }
494
495 top, right, bottom, left, ok := whichSidesColor(c...)
496 if !ok {
497 return s
498 }
499
500 s.set(borderTopForegroundKey, top)
501 s.set(borderRightForegroundKey, right)
502 s.set(borderBottomForegroundKey, bottom)
503 s.set(borderLeftForegroundKey, left)
504
505 return s
506}
507
508// BorderTopForeground set the foreground color for the top of the border.
509func (s Style) BorderTopForeground(c TerminalColor) Style {
510 s.set(borderTopForegroundKey, c)
511 return s
512}
513
514// BorderRightForeground sets the foreground color for the right side of the
515// border.
516func (s Style) BorderRightForeground(c TerminalColor) Style {
517 s.set(borderRightForegroundKey, c)
518 return s
519}
520
521// BorderBottomForeground sets the foreground color for the bottom of the
522// border.
523func (s Style) BorderBottomForeground(c TerminalColor) Style {
524 s.set(borderBottomForegroundKey, c)
525 return s
526}
527
528// BorderLeftForeground sets the foreground color for the left side of the
529// border.
530func (s Style) BorderLeftForeground(c TerminalColor) Style {
531 s.set(borderLeftForegroundKey, c)
532 return s
533}
534
535// BorderBackground is a shorthand function for setting all of the
536// background colors of the borders at once. The arguments work as follows:
537//
538// With one argument, the argument is applied to all sides.
539//
540// With two arguments, the arguments are applied to the vertical and horizontal
541// sides, in that order.
542//
543// With three arguments, the arguments are applied to the top side, the
544// horizontal sides, and the bottom side, in that order.
545//
546// With four arguments, the arguments are applied clockwise starting from the
547// top side, followed by the right side, then the bottom, and finally the left.
548//
549// With more than four arguments nothing will be set.
550func (s Style) BorderBackground(c ...TerminalColor) Style {
551 if len(c) == 0 {
552 return s
553 }
554
555 top, right, bottom, left, ok := whichSidesColor(c...)
556 if !ok {
557 return s
558 }
559
560 s.set(borderTopBackgroundKey, top)
561 s.set(borderRightBackgroundKey, right)
562 s.set(borderBottomBackgroundKey, bottom)
563 s.set(borderLeftBackgroundKey, left)
564
565 return s
566}
567
568// BorderTopBackground sets the background color of the top of the border.
569func (s Style) BorderTopBackground(c TerminalColor) Style {
570 s.set(borderTopBackgroundKey, c)
571 return s
572}
573
574// BorderRightBackground sets the background color of right side the border.
575func (s Style) BorderRightBackground(c TerminalColor) Style {
576 s.set(borderRightBackgroundKey, c)
577 return s
578}
579
580// BorderBottomBackground sets the background color of the bottom of the
581// border.
582func (s Style) BorderBottomBackground(c TerminalColor) Style {
583 s.set(borderBottomBackgroundKey, c)
584 return s
585}
586
587// BorderLeftBackground set the background color of the left side of the
588// border.
589func (s Style) BorderLeftBackground(c TerminalColor) Style {
590 s.set(borderLeftBackgroundKey, c)
591 return s
592}
593
594// Inline makes rendering output one line and disables the rendering of
595// margins, padding and borders. This is useful when you need a style to apply
596// only to font rendering and don't want it to change any physical dimensions.
597// It works well with Style.MaxWidth.
598//
599// Because this in intended to be used at the time of render, this method will
600// not mutate the style and instead return a copy.
601//
602// Example:
603//
604// var userInput string = "..."
605// var userStyle = text.Style{ /* ... */ }
606// fmt.Println(userStyle.Inline(true).Render(userInput))
607func (s Style) Inline(v bool) Style {
608 o := s // copy
609 o.set(inlineKey, v)
610 return o
611}
612
613// MaxWidth applies a max width to a given style. This is useful in enforcing
614// a certain width at render time, particularly with arbitrary strings and
615// styles.
616//
617// Because this in intended to be used at the time of render, this method will
618// not mutate the style and instead return a copy.
619//
620// Example:
621//
622// var userInput string = "..."
623// var userStyle = text.Style{ /* ... */ }
624// fmt.Println(userStyle.MaxWidth(16).Render(userInput))
625func (s Style) MaxWidth(n int) Style {
626 o := s // copy
627 o.set(maxWidthKey, n)
628 return o
629}
630
631// MaxHeight applies a max height to a given style. This is useful in enforcing
632// a certain height at render time, particularly with arbitrary strings and
633// styles.
634//
635// Because this in intended to be used at the time of render, this method will
636// not mutate the style and instead returns a copy.
637func (s Style) MaxHeight(n int) Style {
638 o := s // copy
639 o.set(maxHeightKey, n)
640 return o
641}
642
643// NoTabConversion can be passed to [Style.TabWidth] to disable the replacement
644// of tabs with spaces at render time.
645const NoTabConversion = -1
646
647// TabWidth sets the number of spaces that a tab (/t) should be rendered as.
648// When set to 0, tabs will be removed. To disable the replacement of tabs with
649// spaces entirely, set this to [NoTabConversion].
650//
651// By default, tabs will be replaced with 4 spaces.
652func (s Style) TabWidth(n int) Style {
653 if n <= -1 {
654 n = -1
655 }
656 s.set(tabWidthKey, n)
657 return s
658}
659
660// UnderlineSpaces determines whether to underline spaces between words. By
661// default, this is true. Spaces can also be underlined without underlining the
662// text itself.
663func (s Style) UnderlineSpaces(v bool) Style {
664 s.set(underlineSpacesKey, v)
665 return s
666}
667
668// StrikethroughSpaces determines whether to apply strikethroughs to spaces
669// between words. By default, this is true. Spaces can also be struck without
670// underlining the text itself.
671func (s Style) StrikethroughSpaces(v bool) Style {
672 s.set(strikethroughSpacesKey, v)
673 return s
674}
675
676// Transform applies a given function to a string at render time, allowing for
677// the string being rendered to be manipuated.
678//
679// Example:
680//
681// s := NewStyle().Transform(strings.ToUpper)
682// fmt.Println(s.Render("raow!") // "RAOW!"
683func (s Style) Transform(fn func(string) string) Style {
684 s.set(transformKey, fn)
685 return s
686}
687
688// Renderer sets the renderer for the style. This is useful for changing the
689// renderer for a style that is being used in a different context.
690func (s Style) Renderer(r *Renderer) Style {
691 s.r = r
692 return s
693}
694
695// whichSidesInt is a helper method for setting values on sides of a block based
696// on the number of arguments. It follows the CSS shorthand rules for blocks
697// like margin, padding. and borders. Here are how the rules work:
698//
699// 0 args: do nothing
700// 1 arg: all sides
701// 2 args: top -> bottom
702// 3 args: top -> horizontal -> bottom
703// 4 args: top -> right -> bottom -> left
704// 5+ args: do nothing.
705func whichSidesInt(i ...int) (top, right, bottom, left int, ok bool) {
706 switch len(i) {
707 case 1:
708 top = i[0]
709 bottom = i[0]
710 left = i[0]
711 right = i[0]
712 ok = true
713 case 2: //nolint:mnd
714 top = i[0]
715 bottom = i[0]
716 left = i[1]
717 right = i[1]
718 ok = true
719 case 3: //nolint:mnd
720 top = i[0]
721 left = i[1]
722 right = i[1]
723 bottom = i[2]
724 ok = true
725 case 4: //nolint:mnd
726 top = i[0]
727 right = i[1]
728 bottom = i[2]
729 left = i[3]
730 ok = true
731 }
732 return top, right, bottom, left, ok
733}
734
735// whichSidesBool is like whichSidesInt, except it operates on a series of
736// boolean values. See the comment on whichSidesInt for details on how this
737// works.
738func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) {
739 switch len(i) {
740 case 1:
741 top = i[0]
742 bottom = i[0]
743 left = i[0]
744 right = i[0]
745 ok = true
746 case 2: //nolint:mnd
747 top = i[0]
748 bottom = i[0]
749 left = i[1]
750 right = i[1]
751 ok = true
752 case 3: //nolint:mnd
753 top = i[0]
754 left = i[1]
755 right = i[1]
756 bottom = i[2]
757 ok = true
758 case 4: //nolint:mnd
759 top = i[0]
760 right = i[1]
761 bottom = i[2]
762 left = i[3]
763 ok = true
764 }
765 return top, right, bottom, left, ok
766}
767
768// whichSidesColor is like whichSides, except it operates on a series of
769// boolean values. See the comment on whichSidesInt for details on how this
770// works.
771func whichSidesColor(i ...TerminalColor) (top, right, bottom, left TerminalColor, ok bool) {
772 switch len(i) {
773 case 1:
774 top = i[0]
775 bottom = i[0]
776 left = i[0]
777 right = i[0]
778 ok = true
779 case 2: //nolint:mnd
780 top = i[0]
781 bottom = i[0]
782 left = i[1]
783 right = i[1]
784 ok = true
785 case 3: //nolint:mnd
786 top = i[0]
787 left = i[1]
788 right = i[1]
789 bottom = i[2]
790 ok = true
791 case 4: //nolint:mnd
792 top = i[0]
793 right = i[1]
794 bottom = i[2]
795 left = i[3]
796 ok = true
797 }
798 return top, right, bottom, left, ok
799}