align.go 2.1 KB

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