get.go 16 KB

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