{"id":13410011,"url":"https://github.com/charmbracelet/lipgloss","last_synced_at":"2025-05-12T16:19:55.029Z","repository":{"id":38445558,"uuid":"343533419","full_name":"charmbracelet/lipgloss","owner":"charmbracelet","description":"Style definitions for nice terminal layouts 👄","archived":false,"fork":false,"pushed_at":"2025-05-05T10:00:51.000Z","size":1781,"stargazers_count":8939,"open_issues_count":83,"forks_count":247,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-05-12T16:19:28.359Z","etag":null,"topics":["cli","go","golang","hacktoberfest","layout","style","tui"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/charmbracelet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-03-01T19:31:36.000Z","updated_at":"2025-05-12T14:09:30.000Z","dependencies_parsed_at":"2023-02-04T22:46:30.964Z","dependency_job_id":"7de298f8-6dac-415e-a250-acb40322594c","html_url":"https://github.com/charmbracelet/lipgloss","commit_stats":{"total_commits":225,"total_committers":21,"mean_commits":"10.714285714285714","dds":0.3911111111111111,"last_synced_commit":"da2d04b5347536769af11ef06fbb90b7024ab15f"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Flipgloss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Flipgloss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Flipgloss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Flipgloss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/charmbracelet","download_url":"https://codeload.github.com/charmbracelet/lipgloss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253774593,"owners_count":21962199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","go","golang","hacktoberfest","layout","style","tui"],"created_at":"2024-07-30T20:01:04.488Z","updated_at":"2025-05-12T16:19:54.966Z","avatar_url":"https://github.com/charmbracelet.png","language":"Go","funding_links":[],"categories":["Popular","Go","Command Line","开源类库","Open source library","命令行","Styling \u0026 Output","Tools","Programming","cli","Build Automation","Repositories","TUI Frameworks \u0026 Libraries","Go 🐹"],"sub_categories":["Advanced Console UIs","命令行","Command Line","高级控制台用户界面","Golang"],"readme":"# Lip Gloss\n\n\u003cp\u003e\n    \u003ca href=\"https://stuff.charm.sh/lipgloss/lipgloss-mascot-2k.png\"\u003e\u003cimg width=\"340\" alt=\"Lip Gloss title treatment\" src=\"https://github.com/charmbracelet/lipgloss/assets/25087/147cadb1-4254-43ec-ae6b-8d6ca7b029a1\"\u003e\u003c/a\u003e\u003cbr\u003e\n    \u003ca href=\"https://github.com/charmbracelet/lipgloss/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/release/charmbracelet/lipgloss.svg\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc\"\u003e\u003cimg src=\"https://godoc.org/github.com/golang/gddo?status.svg\" alt=\"GoDoc\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/charmbracelet/lipgloss/actions\"\u003e\u003cimg src=\"https://github.com/charmbracelet/lipgloss/workflows/build/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.phorm.ai/query?projectId=a0e324b6-b706-4546-b951-6671ea60c13f\"\u003e\u003cimg src=\"https://stuff.charm.sh/misc/phorm-badge.svg\" alt=\"phorm.ai\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nStyle definitions for nice terminal layouts. Built with TUIs in mind.\n\n![Lip Gloss example](https://github.com/user-attachments/assets/7950b1c1-e0e3-427e-8e7d-6f7f6ad17ca7)\n\nLip Gloss takes an expressive, declarative approach to terminal rendering.\nUsers familiar with CSS will feel at home with Lip Gloss.\n\n```go\n\nimport \"github.com/charmbracelet/lipgloss\"\n\nvar style = lipgloss.NewStyle().\n    Bold(true).\n    Foreground(lipgloss.Color(\"#FAFAFA\")).\n    Background(lipgloss.Color(\"#7D56F4\")).\n    PaddingTop(2).\n    PaddingLeft(4).\n    Width(22)\n\nfmt.Println(style.Render(\"Hello, kitty\"))\n```\n\n## Colors\n\nLip Gloss supports the following color profiles:\n\n### ANSI 16 colors (4-bit)\n\n```go\nlipgloss.Color(\"5\")  // magenta\nlipgloss.Color(\"9\")  // red\nlipgloss.Color(\"12\") // light blue\n```\n\n### ANSI 256 Colors (8-bit)\n\n```go\nlipgloss.Color(\"86\")  // aqua\nlipgloss.Color(\"201\") // hot pink\nlipgloss.Color(\"202\") // orange\n```\n\n### True Color (16,777,216 colors; 24-bit)\n\n```go\nlipgloss.Color(\"#0000FF\") // good ol' 100% blue\nlipgloss.Color(\"#04B575\") // a green\nlipgloss.Color(\"#3C3C3C\") // a dark gray\n```\n\n...as well as a 1-bit ASCII profile, which is black and white only.\n\nThe terminal's color profile will be automatically detected, and colors outside\nthe gamut of the current palette will be automatically coerced to their closest\navailable value.\n\n### Adaptive Colors\n\nYou can also specify color options for light and dark backgrounds:\n\n```go\nlipgloss.AdaptiveColor{Light: \"236\", Dark: \"248\"}\n```\n\nThe terminal's background color will automatically be detected and the\nappropriate color will be chosen at runtime.\n\n### Complete Colors\n\nCompleteColor specifies exact values for True Color, ANSI256, and ANSI color\nprofiles.\n\n```go\nlipgloss.CompleteColor{TrueColor: \"#0000FF\", ANSI256: \"86\", ANSI: \"5\"}\n```\n\nAutomatic color degradation will not be performed in this case and it will be\nbased on the color specified.\n\n### Complete Adaptive Colors\n\nYou can use `CompleteColor` with `AdaptiveColor` to specify the exact values for\nlight and dark backgrounds without automatic color degradation.\n\n```go\nlipgloss.CompleteAdaptiveColor{\n    Light: CompleteColor{TrueColor: \"#d7ffae\", ANSI256: \"193\", ANSI: \"11\"},\n    Dark:  CompleteColor{TrueColor: \"#d75fee\", ANSI256: \"163\", ANSI: \"5\"},\n}\n```\n\n## Inline Formatting\n\nLip Gloss supports the usual ANSI text formatting options:\n\n```go\nvar style = lipgloss.NewStyle().\n    Bold(true).\n    Italic(true).\n    Faint(true).\n    Blink(true).\n    Strikethrough(true).\n    Underline(true).\n    Reverse(true)\n```\n\n## Block-Level Formatting\n\nLip Gloss also supports rules for block-level formatting:\n\n```go\n// Padding\nvar style = lipgloss.NewStyle().\n    PaddingTop(2).\n    PaddingRight(4).\n    PaddingBottom(2).\n    PaddingLeft(4)\n\n// Margins\nvar style = lipgloss.NewStyle().\n    MarginTop(2).\n    MarginRight(4).\n    MarginBottom(2).\n    MarginLeft(4)\n```\n\nThere is also shorthand syntax for margins and padding, which follows the same\nformat as CSS:\n\n```go\n// 2 cells on all sides\nlipgloss.NewStyle().Padding(2)\n\n// 2 cells on the top and bottom, 4 cells on the left and right\nlipgloss.NewStyle().Margin(2, 4)\n\n// 1 cell on the top, 4 cells on the sides, 2 cells on the bottom\nlipgloss.NewStyle().Padding(1, 4, 2)\n\n// Clockwise, starting from the top: 2 cells on the top, 4 on the right, 3 on\n// the bottom, and 1 on the left\nlipgloss.NewStyle().Margin(2, 4, 3, 1)\n```\n\n## Aligning Text\n\nYou can align paragraphs of text to the left, right, or center.\n\n```go\nvar style = lipgloss.NewStyle().\n    Width(24).\n    Align(lipgloss.Left).  // align it left\n    Align(lipgloss.Right). // no wait, align it right\n    Align(lipgloss.Center) // just kidding, align it in the center\n```\n\n## Width and Height\n\nSetting a minimum width and height is simple and straightforward.\n\n```go\nvar style = lipgloss.NewStyle().\n    SetString(\"What’s for lunch?\").\n    Width(24).\n    Height(32).\n    Foreground(lipgloss.Color(\"63\"))\n```\n\n## Borders\n\nAdding borders is easy:\n\n```go\n// Add a purple, rectangular border\nvar style = lipgloss.NewStyle().\n    BorderStyle(lipgloss.NormalBorder()).\n    BorderForeground(lipgloss.Color(\"63\"))\n\n// Set a rounded, yellow-on-purple border to the top and left\nvar anotherStyle = lipgloss.NewStyle().\n    BorderStyle(lipgloss.RoundedBorder()).\n    BorderForeground(lipgloss.Color(\"228\")).\n    BorderBackground(lipgloss.Color(\"63\")).\n    BorderTop(true).\n    BorderLeft(true)\n\n// Make your own border\nvar myCuteBorder = lipgloss.Border{\n    Top:         \"._.:*:\",\n    Bottom:      \"._.:*:\",\n    Left:        \"|*\",\n    Right:       \"|*\",\n    TopLeft:     \"*\",\n    TopRight:    \"*\",\n    BottomLeft:  \"*\",\n    BottomRight: \"*\",\n}\n```\n\nThere are also shorthand functions for defining borders, which follow a similar\npattern to the margin and padding shorthand functions.\n\n```go\n// Add a thick border to the top and bottom\nlipgloss.NewStyle().\n    Border(lipgloss.ThickBorder(), true, false)\n\n// Add a double border to the top and left sides. Rules are set clockwise\n// from top.\nlipgloss.NewStyle().\n    Border(lipgloss.DoubleBorder(), true, false, false, true)\n```\n\nFor more on borders see [the docs][docs].\n\n## Copying Styles\n\nJust use assignment:\n\n```go\nstyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"219\"))\n\ncopiedStyle := style // this is a true copy\n\nwildStyle := style.Blink(true) // this is also true copy, with blink added\n\n```\n\nSince `Style` data structures contains only primitive types, assigning a style\nto another effectively creates a new copy of the style without mutating the\noriginal.\n\n## Inheritance\n\nStyles can inherit rules from other styles. When inheriting, only unset rules\non the receiver are inherited.\n\n```go\nvar styleA = lipgloss.NewStyle().\n    Foreground(lipgloss.Color(\"229\")).\n    Background(lipgloss.Color(\"63\"))\n\n// Only the background color will be inherited here, because the foreground\n// color will have been already set:\nvar styleB = lipgloss.NewStyle().\n    Foreground(lipgloss.Color(\"201\")).\n    Inherit(styleA)\n```\n\n## Unsetting Rules\n\nAll rules can be unset:\n\n```go\nvar style = lipgloss.NewStyle().\n    Bold(true).                        // make it bold\n    UnsetBold().                       // jk don't make it bold\n    Background(lipgloss.Color(\"227\")). // yellow background\n    UnsetBackground()                  // never mind\n```\n\nWhen a rule is unset, it won't be inherited or copied.\n\n## Enforcing Rules\n\nSometimes, such as when developing a component, you want to make sure style\ndefinitions respect their intended purpose in the UI. This is where `Inline`\nand `MaxWidth`, and `MaxHeight` come in:\n\n```go\n// Force rendering onto a single line, ignoring margins, padding, and borders.\nsomeStyle.Inline(true).Render(\"yadda yadda\")\n\n// Also limit rendering to five cells\nsomeStyle.Inline(true).MaxWidth(5).Render(\"yadda yadda\")\n\n// Limit rendering to a 5x5 cell block\nsomeStyle.MaxWidth(5).MaxHeight(5).Render(\"yadda yadda\")\n```\n\n## Tabs\n\nThe tab character (`\\t`) is rendered differently in different terminals (often\nas 8 spaces, sometimes 4). Because of this inconsistency, Lip Gloss converts\ntabs to 4 spaces at render time. This behavior can be changed on a per-style\nbasis, however:\n\n```go\nstyle := lipgloss.NewStyle() // tabs will render as 4 spaces, the default\nstyle = style.TabWidth(2)    // render tabs as 2 spaces\nstyle = style.TabWidth(0)    // remove tabs entirely\nstyle = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact\n```\n\n## Rendering\n\nGenerally, you just call the `Render(string...)` method on a `lipgloss.Style`:\n\n```go\nstyle := lipgloss.NewStyle().Bold(true).SetString(\"Hello,\")\nfmt.Println(style.Render(\"kitty.\")) // Hello, kitty.\nfmt.Println(style.Render(\"puppy.\")) // Hello, puppy.\n```\n\nBut you could also use the Stringer interface:\n\n```go\nvar style = lipgloss.NewStyle().SetString(\"你好，猫咪。\").Bold(true)\nfmt.Println(style) // 你好，猫咪。\n```\n\n### Custom Renderers\n\nCustom renderers allow you to render to a specific outputs. This is\nparticularly important when you want to render to different outputs and\ncorrectly detect the color profile and dark background status for each, such as\nin a server-client situation.\n\n```go\nfunc myLittleHandler(sess ssh.Session) {\n    // Create a renderer for the client.\n    renderer := lipgloss.NewRenderer(sess)\n\n    // Create a new style on the renderer.\n    style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: \"63\", Dark: \"228\"})\n\n    // Render. The color profile and dark background state will be correctly detected.\n    io.WriteString(sess, style.Render(\"Heyyyyyyy\"))\n}\n```\n\nFor an example on using a custom renderer over SSH with [Wish][wish] see the\n[SSH example][ssh-example].\n\n## Utilities\n\nIn addition to pure styling, Lip Gloss also ships with some utilities to help\nassemble your layouts.\n\n### Joining Paragraphs\n\nHorizontally and vertically joining paragraphs is a cinch.\n\n```go\n// Horizontally join three paragraphs along their bottom edges\nlipgloss.JoinHorizontal(lipgloss.Bottom, paragraphA, paragraphB, paragraphC)\n\n// Vertically join two paragraphs along their center axes\nlipgloss.JoinVertical(lipgloss.Center, paragraphA, paragraphB)\n\n// Horizontally join three paragraphs, with the shorter ones aligning 20%\n// from the top of the tallest\nlipgloss.JoinHorizontal(0.2, paragraphA, paragraphB, paragraphC)\n```\n\n### Measuring Width and Height\n\nSometimes you’ll want to know the width and height of text blocks when building\nyour layouts.\n\n```go\n// Render a block of text.\nvar style = lipgloss.NewStyle().\n    Width(40).\n    Padding(2)\nvar block string = style.Render(someLongString)\n\n// Get the actual, physical dimensions of the text block.\nwidth := lipgloss.Width(block)\nheight := lipgloss.Height(block)\n\n// Here's a shorthand function.\nw, h := lipgloss.Size(block)\n```\n\n### Placing Text in Whitespace\n\nSometimes you’ll simply want to place a block of text in whitespace.\n\n```go\n// Center a paragraph horizontally in a space 80 cells wide. The height of\n// the block returned will be as tall as the input paragraph.\nblock := lipgloss.PlaceHorizontal(80, lipgloss.Center, fancyStyledParagraph)\n\n// Place a paragraph at the bottom of a space 30 cells tall. The width of\n// the text block returned will be as wide as the input paragraph.\nblock := lipgloss.PlaceVertical(30, lipgloss.Bottom, fancyStyledParagraph)\n\n// Place a paragraph in the bottom right corner of a 30x80 cell space.\nblock := lipgloss.Place(30, 80, lipgloss.Right, lipgloss.Bottom, fancyStyledParagraph)\n```\n\nYou can also style the whitespace. For details, see [the docs][docs].\n\n## Rendering Tables\n\nLip Gloss ships with a table rendering sub-package.\n\n```go\nimport \"github.com/charmbracelet/lipgloss/table\"\n```\n\nDefine some rows of data.\n\n```go\nrows := [][]string{\n    {\"Chinese\", \"您好\", \"你好\"},\n    {\"Japanese\", \"こんにちは\", \"やあ\"},\n    {\"Arabic\", \"أهلين\", \"أهلا\"},\n    {\"Russian\", \"Здравствуйте\", \"Привет\"},\n    {\"Spanish\", \"Hola\", \"¿Qué tal?\"},\n}\n```\n\nUse the table package to style and render the table.\n\n```go\nvar (\n    purple    = lipgloss.Color(\"99\")\n    gray      = lipgloss.Color(\"245\")\n    lightGray = lipgloss.Color(\"241\")\n\n    headerStyle  = lipgloss.NewStyle().Foreground(purple).Bold(true).Align(lipgloss.Center)\n    cellStyle    = lipgloss.NewStyle().Padding(0, 1).Width(14)\n    oddRowStyle  = cellStyle.Foreground(gray)\n    evenRowStyle = cellStyle.Foreground(lightGray)\n)\n\nt := table.New().\n    Border(lipgloss.NormalBorder()).\n    BorderStyle(lipgloss.NewStyle().Foreground(purple)).\n    StyleFunc(func(row, col int) lipgloss.Style {\n        switch {\n        case row == table.HeaderRow:\n            return headerStyle\n        case row%2 == 0:\n            return evenRowStyle\n        default:\n            return oddRowStyle\n        }\n    }).\n    Headers(\"LANGUAGE\", \"FORMAL\", \"INFORMAL\").\n    Rows(rows...)\n\n// You can also add tables row-by-row\nt.Row(\"English\", \"You look absolutely fabulous.\", \"How's it going?\")\n```\n\nPrint the table.\n\n```go\nfmt.Println(t)\n```\n\n![Table Example](https://github.com/charmbracelet/lipgloss/assets/42545625/6e4b70c4-f494-45da-a467-bdd27df30d5d)\n\n\u003e [!WARNING]\n\u003e Table `Rows` need to be declared before `Offset` otherwise it does nothing.\n\n### Table Borders\n\nThere are helpers to generate tables in markdown or ASCII style:\n\n#### Markdown Table\n\n```go\ntable.New().Border(lipgloss.MarkdownBorder()).BorderTop(false).BorderBottom(false)\n```\n\n```\n| LANGUAGE |    FORMAL    | INFORMAL  |\n|----------|--------------|-----------|\n| Chinese  | Nǐn hǎo      | Nǐ hǎo    |\n| French   | Bonjour      | Salut     |\n| Russian  | Zdravstvuyte | Privet    |\n| Spanish  | Hola         | ¿Qué tal? |\n```\n\n#### ASCII Table\n\n```go\ntable.New().Border(lipgloss.ASCIIBorder())\n```\n\n```\n+----------+--------------+-----------+\n| LANGUAGE |    FORMAL    | INFORMAL  |\n+----------+--------------+-----------+\n| Chinese  | Nǐn hǎo      | Nǐ hǎo    |\n| French   | Bonjour      | Salut     |\n| Russian  | Zdravstvuyte | Privet    |\n| Spanish  | Hola         | ¿Qué tal? |\n+----------+--------------+-----------+\n```\n\nFor more on tables see [the docs](https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc) and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table).\n\n## Rendering Lists\n\nLip Gloss ships with a list rendering sub-package.\n\n```go\nimport \"github.com/charmbracelet/lipgloss/list\"\n```\n\nDefine a new list.\n\n```go\nl := list.New(\"A\", \"B\", \"C\")\n```\n\nPrint the list.\n\n```go\nfmt.Println(l)\n\n// • A\n// • B\n// • C\n```\n\nLists have the ability to nest.\n\n```go\nl := list.New(\n    \"A\", list.New(\"Artichoke\"),\n    \"B\", list.New(\"Baking Flour\", \"Bananas\", \"Barley\", \"Bean Sprouts\"),\n    \"C\", list.New(\"Cashew Apple\", \"Cashews\", \"Coconut Milk\", \"Curry Paste\", \"Currywurst\"),\n    \"D\", list.New(\"Dill\", \"Dragonfruit\", \"Dried Shrimp\"),\n    \"E\", list.New(\"Eggs\"),\n    \"F\", list.New(\"Fish Cake\", \"Furikake\"),\n    \"J\", list.New(\"Jicama\"),\n    \"K\", list.New(\"Kohlrabi\"),\n    \"L\", list.New(\"Leeks\", \"Lentils\", \"Licorice Root\"),\n)\n```\n\nPrint the list.\n\n```go\nfmt.Println(l)\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"600\" alt=\"image\" src=\"https://github.com/charmbracelet/lipgloss/assets/42545625/0dc9f440-0748-4151-a3b0-7dcf29dfcdb0\"\u003e\n\u003c/p\u003e\n\nLists can be customized via their enumeration function as well as using\n`lipgloss.Style`s.\n\n```go\nenumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"99\")).MarginRight(1)\nitemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"212\")).MarginRight(1)\n\nl := list.New(\n    \"Glossier\",\n    \"Claire’s Boutique\",\n    \"Nyx\",\n    \"Mac\",\n    \"Milk\",\n    ).\n    Enumerator(list.Roman).\n    EnumeratorStyle(enumeratorStyle).\n    ItemStyle(itemStyle)\n```\n\nPrint the list.\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"600\" alt=\"List example\" src=\"https://github.com/charmbracelet/lipgloss/assets/42545625/360494f1-57fb-4e13-bc19-0006efe01561\"\u003e\n\u003c/p\u003e\n\nIn addition to the predefined enumerators (`Arabic`, `Alphabet`, `Roman`, `Bullet`, `Tree`),\nyou may also define your own custom enumerator:\n\n```go\nl := list.New(\"Duck\", \"Duck\", \"Duck\", \"Duck\", \"Goose\", \"Duck\", \"Duck\")\n\nfunc DuckDuckGooseEnumerator(l list.Items, i int) string {\n    if l.At(i).Value() == \"Goose\" {\n        return \"Honk →\"\n    }\n    return \"\"\n}\n\nl = l.Enumerator(DuckDuckGooseEnumerator)\n```\n\nPrint the list:\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"600\" alt=\"image\" src=\"https://github.com/charmbracelet/lipgloss/assets/42545625/157aaf30-140d-4948-9bb4-dfba46e5b87e\"\u003e\n\u003c/p\u003e\n\nIf you need, you can also build lists incrementally:\n\n```go\nl := list.New()\n\nfor i := 0; i \u003c repeat; i++ {\n    l.Item(\"Lip Gloss\")\n}\n```\n\n## Rendering Trees\n\nLip Gloss ships with a tree rendering sub-package.\n\n```go\nimport \"github.com/charmbracelet/lipgloss/tree\"\n```\n\nDefine a new tree.\n\n```go\nt := tree.Root(\".\").\n    Child(\"A\", \"B\", \"C\")\n```\n\nPrint the tree.\n\n```go\nfmt.Println(t)\n\n// .\n// ├── A\n// ├── B\n// └── C\n```\n\nTrees have the ability to nest.\n\n```go\nt := tree.Root(\".\").\n    Child(\"macOS\").\n    Child(\n        tree.New().\n            Root(\"Linux\").\n            Child(\"NixOS\").\n            Child(\"Arch Linux (btw)\").\n            Child(\"Void Linux\"),\n        ).\n    Child(\n        tree.New().\n            Root(\"BSD\").\n            Child(\"FreeBSD\").\n            Child(\"OpenBSD\"),\n    )\n```\n\nPrint the tree.\n\n```go\nfmt.Println(t)\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"663\" alt=\"Tree Example (simple)\" src=\"https://github.com/user-attachments/assets/5ef14eb8-a5d4-4f94-8834-e15d1e714f89\"\u003e\n\u003c/p\u003e\n\nTrees can be customized via their enumeration function as well as using\n`lipgloss.Style`s.\n\n```go\nenumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"63\")).MarginRight(1)\nrootStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"35\"))\nitemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"212\"))\n\nt := tree.\n    Root(\"⁜ Makeup\").\n    Child(\n        \"Glossier\",\n        \"Fenty Beauty\",\n        tree.New().Child(\n            \"Gloss Bomb Universal Lip Luminizer\",\n            \"Hot Cheeks Velour Blushlighter\",\n        ),\n        \"Nyx\",\n        \"Mac\",\n        \"Milk\",\n    ).\n    Enumerator(tree.RoundedEnumerator).\n    EnumeratorStyle(enumeratorStyle).\n    RootStyle(rootStyle).\n    ItemStyle(itemStyle)\n```\n\nPrint the tree.\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"663\" alt=\"Tree Example (makeup)\" src=\"https://github.com/user-attachments/assets/06d12d87-744a-4c89-bd98-45de9094a97e\"\u003e\n\u003c/p\u003e\n\nThe predefined enumerators for trees are `DefaultEnumerator` and `RoundedEnumerator`.\n\nIf you need, you can also build trees incrementally:\n\n```go\nt := tree.New()\n\nfor i := 0; i \u003c repeat; i++ {\n    t.Child(\"Lip Gloss\")\n}\n```\n\n---\n\n## FAQ\n\n\u003cdetails\u003e\n\u003csummary\u003e\nWhy are things misaligning? Why are borders at the wrong widths?\n\u003c/summary\u003e\n\u003cp\u003eThis is most likely due to your locale and encoding, particularly with\nregard to Chinese, Japanese, and Korean (for example, \u003ccode\u003ezh_CN.UTF-8\u003c/code\u003e\nor \u003ccode\u003eja_JP.UTF-8\u003c/code\u003e). The most direct way to fix this is to set\n\u003ccode\u003eRUNEWIDTH_EASTASIAN=0\u003c/code\u003e in your environment.\u003c/p\u003e\n\n\u003cp\u003eFor details see \u003ca href=\"https://github.com/charmbracelet/lipgloss/issues/40\"\u003ehttps://github.com/charmbracelet/lipgloss/issues/40.\u003c/a\u003e\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\nWhy isn't Lip Gloss displaying colors?\n\u003c/summary\u003e\n\u003cp\u003eLip Gloss automatically degrades colors to the best available option in the\ngiven terminal, and if output's not a TTY it will remove color output entirely.\nThis is common when running tests, CI, or when piping output elsewhere.\u003c/p\u003e\n\n\u003cp\u003eIf necessary, you can force a color profile in your tests with\n\u003ca href=\"https://pkg.go.dev/github.com/charmbracelet/lipgloss#SetColorProfile\"\u003e\u003ccode\u003eSetColorProfile\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\n```go\nimport (\n    \"github.com/charmbracelet/lipgloss\"\n    \"github.com/muesli/termenv\"\n)\n\nlipgloss.SetColorProfile(termenv.TrueColor)\n```\n\n_Note:_ this option limits the flexibility of your application and can cause\nANSI escape codes to be output in cases where that might not be desired. Take\ncareful note of your use case and environment before choosing to force a color\nprofile.\n\n\u003c/details\u003e\n\n## What about [Bubble Tea][tea]?\n\nLip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea\ncompanion. It was designed to make assembling terminal user interface views as\nsimple and fun as possible so that you can focus on building your application\ninstead of concerning yourself with low-level layout details.\n\nIn simple terms, you can use Lip Gloss to help build your Bubble Tea views.\n\n[tea]: https://github.com/charmbracelet/tea\n\n## Under the Hood\n\nLip Gloss is built on the excellent [Termenv][termenv] and [Reflow][reflow]\nlibraries which deal with color and ANSI-aware text operations, respectively.\nFor many use cases Termenv and Reflow will be sufficient for your needs.\n\n[termenv]: https://github.com/muesli/termenv\n[reflow]: https://github.com/muesli/reflow\n\n## Rendering Markdown\n\nFor a more document-centric rendering solution with support for things like\nlists, tables, and syntax-highlighted code have a look at [Glamour][glamour],\nthe stylesheet-based Markdown renderer.\n\n[glamour]: https://github.com/charmbracelet/glamour\n\n## Contributing\n\nSee [contributing][contribute].\n\n[contribute]: https://github.com/charmbracelet/lipgloss/contribute\n\n## Feedback\n\nWe’d love to hear your thoughts on this project. Feel free to drop us a note!\n\n- [Twitter](https://twitter.com/charmcli)\n- [The Fediverse](https://mastodon.social/@charmcli)\n- [Discord](https://charm.sh/chat)\n\n## License\n\n[MIT](https://github.com/charmbracelet/lipgloss/raw/master/LICENSE)\n\n---\n\nPart of [Charm](https://charm.sh).\n\n\u003ca href=\"https://charm.sh/\"\u003e\u003cimg alt=\"The Charm logo\" src=\"https://stuff.charm.sh/charm-badge.jpg\" width=\"400\"\u003e\u003c/a\u003e\n\nCharm热爱开源 • Charm loves open source\n\n[docs]: https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc\n[wish]: https://github.com/charmbracelet/wish\n[ssh-example]: examples/ssh\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharmbracelet%2Flipgloss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharmbracelet%2Flipgloss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharmbracelet%2Flipgloss/lists"}