align.go

 1package lipgloss
 2
 3import (
 4	"strings"
 5
 6	"github.com/charmbracelet/x/ansi"
 7)
 8
 9// Perform text alignment. If the string is multi-lined, we also make all lines
10// the same width by padding them with spaces. If a style is passed, use that
11// to style the spaces added.
12func alignTextHorizontal(str string, pos Position, width int, style *ansi.Style) string {
13	lines, widestLine := getLines(str)
14	var b strings.Builder
15
16	for i, l := range lines {
17		lineWidth := ansi.StringWidth(l)
18
19		shortAmount := widestLine - lineWidth                // difference from the widest line
20		shortAmount += max(0, width-(shortAmount+lineWidth)) // difference from the total width, if set
21
22		if shortAmount > 0 {
23			switch pos { //nolint:exhaustive
24			case Right:
25				s := strings.Repeat(" ", shortAmount)
26				if style != nil {
27					s = style.Styled(s)
28				}
29				l = s + l
30			case Center:
31				// Note: remainder goes on the right.
32				left := shortAmount / 2       //nolint:mnd
33				right := left + shortAmount%2 //nolint:mnd
34
35				leftSpaces := strings.Repeat(" ", left)
36				rightSpaces := strings.Repeat(" ", right)
37
38				if style != nil {
39					leftSpaces = style.Styled(leftSpaces)
40					rightSpaces = style.Styled(rightSpaces)
41				}
42				l = leftSpaces + l + rightSpaces
43			default: // Left
44				s := strings.Repeat(" ", shortAmount)
45				if style != nil {
46					s = style.Styled(s)
47				}
48				l += s
49			}
50		}
51
52		b.WriteString(l)
53		if i < len(lines)-1 {
54			b.WriteRune('\n')
55		}
56	}
57
58	return b.String()
59}
60
61func alignTextVertical(str string, pos Position, height int, _ *ansi.Style) string {
62	strHeight := strings.Count(str, "\n") + 1
63	if height < strHeight {
64		return str
65	}
66
67	switch pos {
68	case Top:
69		return str + strings.Repeat("\n", height-strHeight)
70	case Center:
71		topPadding, bottomPadding := (height-strHeight)/2, (height-strHeight)/2 //nolint:mnd
72		if strHeight+topPadding+bottomPadding > height {
73			topPadding--
74		} else if strHeight+topPadding+bottomPadding < height {
75			bottomPadding++
76		}
77		return strings.Repeat("\n", topPadding) + str + strings.Repeat("\n", bottomPadding)
78	case Bottom:
79		return strings.Repeat("\n", height-strHeight) + str
80	}
81	return str
82}