main
Raw Download raw file
  1package lipgloss
  2
  3import (
  4	"strings"
  5
  6	"github.com/charmbracelet/x/ansi"
  7)
  8
  9// GetBold returns the style's bold value. If no value is set false is returned.
 10func (s Style) GetBold() bool {
 11	return s.getAsBool(boldKey, false)
 12}
 13
 14// GetItalic returns the style's italic value. If no value is set false is
 15// returned.
 16func (s Style) GetItalic() bool {
 17	return s.getAsBool(italicKey, false)
 18}
 19
 20// GetUnderline returns the style's underline value. If no value is set false is
 21// returned.
 22func (s Style) GetUnderline() bool {
 23	return s.getAsBool(underlineKey, false)
 24}
 25
 26// GetStrikethrough returns the style's strikethrough value. If no value is set false
 27// is returned.
 28func (s Style) GetStrikethrough() bool {
 29	return s.getAsBool(strikethroughKey, false)
 30}
 31
 32// GetReverse returns the style's reverse value. If no value is set false is
 33// returned.
 34func (s Style) GetReverse() bool {
 35	return s.getAsBool(reverseKey, false)
 36}
 37
 38// GetBlink returns the style's blink value. If no value is set false is
 39// returned.
 40func (s Style) GetBlink() bool {
 41	return s.getAsBool(blinkKey, false)
 42}
 43
 44// GetFaint returns the style's faint value. If no value is set false is
 45// returned.
 46func (s Style) GetFaint() bool {
 47	return s.getAsBool(faintKey, false)
 48}
 49
 50// GetForeground returns the style's foreground color. If no value is set
 51// NoColor{} is returned.
 52func (s Style) GetForeground() TerminalColor {
 53	return s.getAsColor(foregroundKey)
 54}
 55
 56// GetBackground returns the style's background color. If no value is set
 57// NoColor{} is returned.
 58func (s Style) GetBackground() TerminalColor {
 59	return s.getAsColor(backgroundKey)
 60}
 61
 62// GetWidth returns the style's width setting. If no width is set 0 is
 63// returned.
 64func (s Style) GetWidth() int {
 65	return s.getAsInt(widthKey)
 66}
 67
 68// GetHeight returns the style's height setting. If no height is set 0 is
 69// returned.
 70func (s Style) GetHeight() int {
 71	return s.getAsInt(heightKey)
 72}
 73
 74// GetAlign returns the style's implicit horizontal alignment setting.
 75// If no alignment is set Position.Left is returned.
 76func (s Style) GetAlign() Position {
 77	v := s.getAsPosition(alignHorizontalKey)
 78	if v == Position(0) {
 79		return Left
 80	}
 81	return v
 82}
 83
 84// GetAlignHorizontal returns the style's implicit horizontal alignment setting.
 85// If no alignment is set Position.Left is returned.
 86func (s Style) GetAlignHorizontal() Position {
 87	v := s.getAsPosition(alignHorizontalKey)
 88	if v == Position(0) {
 89		return Left
 90	}
 91	return v
 92}
 93
 94// GetAlignVertical returns the style's implicit vertical alignment setting.
 95// If no alignment is set Position.Top is returned.
 96func (s Style) GetAlignVertical() Position {
 97	v := s.getAsPosition(alignVerticalKey)
 98	if v == Position(0) {
 99		return Top
100	}
101	return v
102}
103
104// GetPadding returns the style's top, right, bottom, and left padding values,
105// in that order. 0 is returned for unset values.
106func (s Style) GetPadding() (top, right, bottom, left int) {
107	return s.getAsInt(paddingTopKey),
108		s.getAsInt(paddingRightKey),
109		s.getAsInt(paddingBottomKey),
110		s.getAsInt(paddingLeftKey)
111}
112
113// GetPaddingTop returns the style's top padding. If no value is set 0 is
114// returned.
115func (s Style) GetPaddingTop() int {
116	return s.getAsInt(paddingTopKey)
117}
118
119// GetPaddingRight returns the style's right padding. If no value is set 0 is
120// returned.
121func (s Style) GetPaddingRight() int {
122	return s.getAsInt(paddingRightKey)
123}
124
125// GetPaddingBottom returns the style's bottom padding. If no value is set 0 is
126// returned.
127func (s Style) GetPaddingBottom() int {
128	return s.getAsInt(paddingBottomKey)
129}
130
131// GetPaddingLeft returns the style's left padding. If no value is set 0 is
132// returned.
133func (s Style) GetPaddingLeft() int {
134	return s.getAsInt(paddingLeftKey)
135}
136
137// GetHorizontalPadding returns the style's left and right padding. Unset
138// values are measured as 0.
139func (s Style) GetHorizontalPadding() int {
140	return s.getAsInt(paddingLeftKey) + s.getAsInt(paddingRightKey)
141}
142
143// GetVerticalPadding returns the style's top and bottom padding. Unset values
144// are measured as 0.
145func (s Style) GetVerticalPadding() int {
146	return s.getAsInt(paddingTopKey) + s.getAsInt(paddingBottomKey)
147}
148
149// GetColorWhitespace returns the style's whitespace coloring setting. If no
150// value is set false is returned.
151func (s Style) GetColorWhitespace() bool {
152	return s.getAsBool(colorWhitespaceKey, false)
153}
154
155// GetMargin returns the style's top, right, bottom, and left margins, in that
156// order. 0 is returned for unset values.
157func (s Style) GetMargin() (top, right, bottom, left int) {
158	return s.getAsInt(marginTopKey),
159		s.getAsInt(marginRightKey),
160		s.getAsInt(marginBottomKey),
161		s.getAsInt(marginLeftKey)
162}
163
164// GetMarginTop returns the style's top margin. If no value is set 0 is
165// returned.
166func (s Style) GetMarginTop() int {
167	return s.getAsInt(marginTopKey)
168}
169
170// GetMarginRight returns the style's right margin. If no value is set 0 is
171// returned.
172func (s Style) GetMarginRight() int {
173	return s.getAsInt(marginRightKey)
174}
175
176// GetMarginBottom returns the style's bottom margin. If no value is set 0 is
177// returned.
178func (s Style) GetMarginBottom() int {
179	return s.getAsInt(marginBottomKey)
180}
181
182// GetMarginLeft returns the style's left margin. If no value is set 0 is
183// returned.
184func (s Style) GetMarginLeft() int {
185	return s.getAsInt(marginLeftKey)
186}
187
188// GetHorizontalMargins returns the style's left and right margins. Unset
189// values are measured as 0.
190func (s Style) GetHorizontalMargins() int {
191	return s.getAsInt(marginLeftKey) + s.getAsInt(marginRightKey)
192}
193
194// GetVerticalMargins returns the style's top and bottom margins. Unset values
195// are measured as 0.
196func (s Style) GetVerticalMargins() int {
197	return s.getAsInt(marginTopKey) + s.getAsInt(marginBottomKey)
198}
199
200// GetBorder returns the style's border style (type Border) and value for the
201// top, right, bottom, and left in that order. If no value is set for the
202// border style, Border{} is returned. For all other unset values false is
203// returned.
204func (s Style) GetBorder() (b Border, top, right, bottom, left bool) {
205	return s.getBorderStyle(),
206		s.getAsBool(borderTopKey, false),
207		s.getAsBool(borderRightKey, false),
208		s.getAsBool(borderBottomKey, false),
209		s.getAsBool(borderLeftKey, false)
210}
211
212// GetBorderStyle returns the style's border style (type Border). If no value
213// is set Border{} is returned.
214func (s Style) GetBorderStyle() Border {
215	return s.getBorderStyle()
216}
217
218// GetBorderTop returns the style's top border setting. If no value is set
219// false is returned.
220func (s Style) GetBorderTop() bool {
221	return s.getAsBool(borderTopKey, false)
222}
223
224// GetBorderRight returns the style's right border setting. If no value is set
225// false is returned.
226func (s Style) GetBorderRight() bool {
227	return s.getAsBool(borderRightKey, false)
228}
229
230// GetBorderBottom returns the style's bottom border setting. If no value is
231// set false is returned.
232func (s Style) GetBorderBottom() bool {
233	return s.getAsBool(borderBottomKey, false)
234}
235
236// GetBorderLeft returns the style's left border setting. If no value is
237// set false is returned.
238func (s Style) GetBorderLeft() bool {
239	return s.getAsBool(borderLeftKey, false)
240}
241
242// GetBorderTopForeground returns the style's border top foreground color. If
243// no value is set NoColor{} is returned.
244func (s Style) GetBorderTopForeground() TerminalColor {
245	return s.getAsColor(borderTopForegroundKey)
246}
247
248// GetBorderRightForeground returns the style's border right foreground color.
249// If no value is set NoColor{} is returned.
250func (s Style) GetBorderRightForeground() TerminalColor {
251	return s.getAsColor(borderRightForegroundKey)
252}
253
254// GetBorderBottomForeground returns the style's border bottom foreground
255// color.  If no value is set NoColor{} is returned.
256func (s Style) GetBorderBottomForeground() TerminalColor {
257	return s.getAsColor(borderBottomForegroundKey)
258}
259
260// GetBorderLeftForeground returns the style's border left foreground
261// color.  If no value is set NoColor{} is returned.
262func (s Style) GetBorderLeftForeground() TerminalColor {
263	return s.getAsColor(borderLeftForegroundKey)
264}
265
266// GetBorderTopBackground returns the style's border top background color. If
267// no value is set NoColor{} is returned.
268func (s Style) GetBorderTopBackground() TerminalColor {
269	return s.getAsColor(borderTopBackgroundKey)
270}
271
272// GetBorderRightBackground returns the style's border right background color.
273// If no value is set NoColor{} is returned.
274func (s Style) GetBorderRightBackground() TerminalColor {
275	return s.getAsColor(borderRightBackgroundKey)
276}
277
278// GetBorderBottomBackground returns the style's border bottom background
279// color.  If no value is set NoColor{} is returned.
280func (s Style) GetBorderBottomBackground() TerminalColor {
281	return s.getAsColor(borderBottomBackgroundKey)
282}
283
284// GetBorderLeftBackground returns the style's border left background
285// color.  If no value is set NoColor{} is returned.
286func (s Style) GetBorderLeftBackground() TerminalColor {
287	return s.getAsColor(borderLeftBackgroundKey)
288}
289
290// GetBorderTopWidth returns the width of the top border. If borders contain
291// runes of varying widths, the widest rune is returned. If no border exists on
292// the top edge, 0 is returned.
293//
294// Deprecated: This function simply calls Style.GetBorderTopSize.
295func (s Style) GetBorderTopWidth() int {
296	return s.GetBorderTopSize()
297}
298
299// GetBorderTopSize returns the width of the top border. If borders contain
300// runes of varying widths, the widest rune is returned. If no border exists on
301// the top edge, 0 is returned.
302func (s Style) GetBorderTopSize() int {
303	if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() {
304		return 0
305	}
306	return s.getBorderStyle().GetTopSize()
307}
308
309// GetBorderLeftSize returns the width of the left border. If borders contain
310// runes of varying widths, the widest rune is returned. If no border exists on
311// the left edge, 0 is returned.
312func (s Style) GetBorderLeftSize() int {
313	if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() {
314		return 0
315	}
316	return s.getBorderStyle().GetLeftSize()
317}
318
319// GetBorderBottomSize returns the width of the bottom border. If borders
320// contain runes of varying widths, the widest rune is returned. If no border
321// exists on the left edge, 0 is returned.
322func (s Style) GetBorderBottomSize() int {
323	if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() {
324		return 0
325	}
326	return s.getBorderStyle().GetBottomSize()
327}
328
329// GetBorderRightSize returns the width of the right border. If borders
330// contain runes of varying widths, the widest rune is returned. If no border
331// exists on the right edge, 0 is returned.
332func (s Style) GetBorderRightSize() int {
333	if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() {
334		return 0
335	}
336	return s.getBorderStyle().GetRightSize()
337}
338
339// GetHorizontalBorderSize returns the width of the horizontal borders. If
340// borders contain runes of varying widths, the widest rune is returned. If no
341// border exists on the horizontal edges, 0 is returned.
342func (s Style) GetHorizontalBorderSize() int {
343	return s.GetBorderLeftSize() + s.GetBorderRightSize()
344}
345
346// GetVerticalBorderSize returns the width of the vertical borders. If
347// borders contain runes of varying widths, the widest rune is returned. If no
348// border exists on the vertical edges, 0 is returned.
349func (s Style) GetVerticalBorderSize() int {
350	return s.GetBorderTopSize() + s.GetBorderBottomSize()
351}
352
353// GetInline returns the style's inline setting. If no value is set false is
354// returned.
355func (s Style) GetInline() bool {
356	return s.getAsBool(inlineKey, false)
357}
358
359// GetMaxWidth returns the style's max width setting. If no value is set 0 is
360// returned.
361func (s Style) GetMaxWidth() int {
362	return s.getAsInt(maxWidthKey)
363}
364
365// GetMaxHeight returns the style's max height setting. If no value is set 0 is
366// returned.
367func (s Style) GetMaxHeight() int {
368	return s.getAsInt(maxHeightKey)
369}
370
371// GetTabWidth returns the style's tab width setting. If no value is set 4 is
372// returned which is the implicit default.
373func (s Style) GetTabWidth() int {
374	return s.getAsInt(tabWidthKey)
375}
376
377// GetUnderlineSpaces returns whether or not the style is set to underline
378// spaces. If not value is set false is returned.
379func (s Style) GetUnderlineSpaces() bool {
380	return s.getAsBool(underlineSpacesKey, false)
381}
382
383// GetStrikethroughSpaces returns whether or not the style is set to strikethrough
384// spaces. If not value is set false is returned.
385func (s Style) GetStrikethroughSpaces() bool {
386	return s.getAsBool(strikethroughSpacesKey, false)
387}
388
389// GetHorizontalFrameSize returns the sum of the style's horizontal margins, padding
390// and border widths.
391//
392// Provisional: this method may be renamed.
393func (s Style) GetHorizontalFrameSize() int {
394	return s.GetHorizontalMargins() + s.GetHorizontalPadding() + s.GetHorizontalBorderSize()
395}
396
397// GetVerticalFrameSize returns the sum of the style's vertical margins, padding
398// and border widths.
399//
400// Provisional: this method may be renamed.
401func (s Style) GetVerticalFrameSize() int {
402	return s.GetVerticalMargins() + s.GetVerticalPadding() + s.GetVerticalBorderSize()
403}
404
405// GetFrameSize returns the sum of the margins, padding and border width for
406// both the horizontal and vertical margins.
407func (s Style) GetFrameSize() (x, y int) {
408	return s.GetHorizontalFrameSize(), s.GetVerticalFrameSize()
409}
410
411// GetTransform returns the transform set on the style. If no transform is set
412// nil is returned.
413func (s Style) GetTransform() func(string) string {
414	return s.getAsTransform(transformKey)
415}
416
417// Returns whether or not the given property is set.
418func (s Style) isSet(k propKey) bool {
419	return s.props.has(k)
420}
421
422func (s Style) getAsBool(k propKey, defaultVal bool) bool {
423	if !s.isSet(k) {
424		return defaultVal
425	}
426	return s.attrs&int(k) != 0
427}
428
429func (s Style) getAsColor(k propKey) TerminalColor {
430	if !s.isSet(k) {
431		return noColor
432	}
433
434	var c TerminalColor
435	switch k { //nolint:exhaustive
436	case foregroundKey:
437		c = s.fgColor
438	case backgroundKey:
439		c = s.bgColor
440	case marginBackgroundKey:
441		c = s.marginBgColor
442	case borderTopForegroundKey:
443		c = s.borderTopFgColor
444	case borderRightForegroundKey:
445		c = s.borderRightFgColor
446	case borderBottomForegroundKey:
447		c = s.borderBottomFgColor
448	case borderLeftForegroundKey:
449		c = s.borderLeftFgColor
450	case borderTopBackgroundKey:
451		c = s.borderTopBgColor
452	case borderRightBackgroundKey:
453		c = s.borderRightBgColor
454	case borderBottomBackgroundKey:
455		c = s.borderBottomBgColor
456	case borderLeftBackgroundKey:
457		c = s.borderLeftBgColor
458	}
459
460	if c != nil {
461		return c
462	}
463
464	return noColor
465}
466
467func (s Style) getAsInt(k propKey) int {
468	if !s.isSet(k) {
469		return 0
470	}
471	switch k { //nolint:exhaustive
472	case widthKey:
473		return s.width
474	case heightKey:
475		return s.height
476	case paddingTopKey:
477		return s.paddingTop
478	case paddingRightKey:
479		return s.paddingRight
480	case paddingBottomKey:
481		return s.paddingBottom
482	case paddingLeftKey:
483		return s.paddingLeft
484	case marginTopKey:
485		return s.marginTop
486	case marginRightKey:
487		return s.marginRight
488	case marginBottomKey:
489		return s.marginBottom
490	case marginLeftKey:
491		return s.marginLeft
492	case maxWidthKey:
493		return s.maxWidth
494	case maxHeightKey:
495		return s.maxHeight
496	case tabWidthKey:
497		return s.tabWidth
498	}
499	return 0
500}
501
502func (s Style) getAsPosition(k propKey) Position {
503	if !s.isSet(k) {
504		return Position(0)
505	}
506	switch k { //nolint:exhaustive
507	case alignHorizontalKey:
508		return s.alignHorizontal
509	case alignVerticalKey:
510		return s.alignVertical
511	}
512	return Position(0)
513}
514
515func (s Style) getBorderStyle() Border {
516	if !s.isSet(borderStyleKey) {
517		return noBorder
518	}
519	return s.borderStyle
520}
521
522// Returns whether or not the style has implicit borders. This happens when
523// a border style has been set but no border sides have been explicitly turned
524// on or off.
525func (s Style) implicitBorders() bool {
526	var (
527		borderStyle = s.getBorderStyle()
528		topSet      = s.isSet(borderTopKey)
529		rightSet    = s.isSet(borderRightKey)
530		bottomSet   = s.isSet(borderBottomKey)
531		leftSet     = s.isSet(borderLeftKey)
532	)
533	return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet)
534}
535
536func (s Style) getAsTransform(propKey) func(string) string {
537	if !s.isSet(transformKey) {
538		return nil
539	}
540	return s.transform
541}
542
543// Split a string into lines, additionally returning the size of the widest
544// line.
545func getLines(s string) (lines []string, widest int) {
546	lines = strings.Split(s, "\n")
547
548	for _, l := range lines {
549		w := ansi.StringWidth(l)
550		if widest < w {
551			widest = w
552		}
553	}
554
555	return lines, widest
556}