get.go

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