{"id":35507083,"url":"https://github.com/marcoroth/lipgloss-ruby","last_synced_at":"2026-02-17T03:39:39.341Z","repository":{"id":330809448,"uuid":"1115739781","full_name":"marcoroth/lipgloss-ruby","owner":"marcoroth","description":"Style Definitions for Nice Terminal Layouts for Ruby, based on Charm's lipgloss.","archived":false,"fork":false,"pushed_at":"2025-12-30T14:51:37.000Z","size":90,"stargazers_count":44,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-11T10:42:13.205Z","etag":null,"topics":["charm","charmbracelet","cli","go","lipgloss","native-extension","ruby"],"latest_commit_sha":null,"homepage":"https://charm-ruby.dev","language":"C","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/marcoroth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"marcoroth"}},"created_at":"2025-12-13T13:05:33.000Z","updated_at":"2026-01-09T22:22:11.000Z","dependencies_parsed_at":"2025-12-30T21:03:27.512Z","dependency_job_id":null,"html_url":"https://github.com/marcoroth/lipgloss-ruby","commit_stats":null,"previous_names":["marcoroth/lipgloss-ruby"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/marcoroth/lipgloss-ruby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcoroth%2Flipgloss-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcoroth%2Flipgloss-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcoroth%2Flipgloss-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcoroth%2Flipgloss-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcoroth","download_url":"https://codeload.github.com/marcoroth/lipgloss-ruby/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcoroth%2Flipgloss-ruby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29530144,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T00:57:22.232Z","status":"online","status_checked_at":"2026-02-17T02:00:08.105Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["charm","charmbracelet","cli","go","lipgloss","native-extension","ruby"],"created_at":"2026-01-03T20:00:41.649Z","updated_at":"2026-02-17T03:39:39.336Z","avatar_url":"https://github.com/marcoroth.png","language":"C","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eLipgloss for Ruby\u003c/h1\u003e\n  \u003ch4\u003eStyle Definitions for Nice Terminal Layouts\u003c/h4\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://rubygems.org/gems/lipgloss\"\u003e\u003cimg alt=\"Gem Version\" src=\"https://img.shields.io/gem/v/lipgloss\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/marcoroth/lipgloss-ruby/blob/main/LICENSE.txt\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/marcoroth/lipgloss-ruby\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003eRuby bindings for \u003ca href=\"https://github.com/charmbracelet/lipgloss\"\u003echarmbracelet/lipgloss\u003c/a\u003e.\u003cbr/\u003eStyle definitions for nice terminal layouts. Built with TUIs in mind.\u003c/p\u003e\n\u003c/div\u003e\n\n## Installation\n\n**Add to your Gemfile:**\n\n```ruby\ngem \"lipgloss\"\n```\n\n**Or install directly:**\n\n```bash\ngem install lipgloss\n```\n\n## Usage\n\n### Basic Styling\n\n**Create and render styled text:**\n\n```ruby\nrequire \"lipgloss\"\n\nstyle = Lipgloss::Style.new\n  .bold(true)\n  .foreground(\"#FAFAFA\")\n  .background(\"#7D56F4\")\n  .padding(1, 2)\n\nputs style.render(\"Hello, Lipgloss!\")\n```\n\n**Reusable styles:**\n\n```ruby\nheading = Lipgloss::Style.new\n  .bold(true)\n  .foreground(\"#FF6B6B\")\n  .margin_bottom(1)\n\nbody = Lipgloss::Style.new\n  .width(40)\n  .align(:center)\n\nputs heading.render(\"Welcome\")\nputs body.render(\"Styled terminal output\")\n```\n\n### Borders\n\n**Add borders to your content:**\n\n```ruby\nbox = Lipgloss::Style.new\n  .border(:rounded)\n  .border_foreground(\"#874BFD\")\n  .padding(1, 2)\n\nputs box.render(\"Boxed content\")\n```\n\n**Available border styles:**\n\n| Style      | Description                       |\n|------------|-----------------------------------|\n| `:normal`  | Standard box drawing characters   |\n| `:rounded` | Rounded corners                   |\n| `:thick`   | Thick lines                       |\n| `:double`  | Double lines                      |\n| `:hidden`  | Hidden (spacing only)             |\n| `:block`   | Block characters                  |\n| `:ascii`   | ASCII characters (`+`, `-`, `\\|`) |\n\n**Custom borders:**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .border_custom(\n    top: \"~\", bottom: \"~\",\n    left: \"|\", right: \"|\",\n    top_left: \"+\", top_right: \"+\",\n    bottom_left: \"+\", bottom_right: \"+\"\n  )\n\nputs style.render(\"Custom border!\")\n```\n\n**Per-side border colors:**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .border(:rounded)\n  .border_top_foreground(\"#FF0000\")\n  .border_right_foreground(\"#00FF00\")\n  .border_bottom_foreground(\"#0000FF\")\n  .border_left_foreground(\"#FFFF00\")\n\nputs style.render(\"Rainbow border!\")\n```\n\n### Layout\n\n**Join content horizontally:**\n\n```ruby\nleft = box.render(\"Left\")\nright = box.render(\"Right\")\n\nputs Lipgloss.join_horizontal(:top, left, right)\n```\n\n**Join content vertically:**\n\n```ruby\nputs Lipgloss.join_vertical(:center, left, right)\n```\n\n**Place content in whitespace:**\n\n```ruby\nputs Lipgloss.place(40, 10, :center, :center, \"Centered\")\n```\n\n**Position symbols:** `:top`, `:bottom`, `:left`, `:right`, `:center` (or numeric 0.0-1.0)\n\n### Colors\n\n**Simple hex colors:**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .foreground(\"#FF0000\")\n  .background(\"#0000FF\")\n```\n\n**Adaptive colors (auto-detect light/dark terminal):**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .foreground(Lipgloss::AdaptiveColor.new(light: \"#000\", dark: \"#FFF\"))\n```\n\n**Complete colors with fallbacks:**\n\n```ruby\ncolor = Lipgloss::CompleteColor.new(\n  true_color: \"#FF6B6B\",  # 24-bit color\n  ansi256: 196,           # 256-color fallback (integer)\n  ansi: :bright_red       # 16-color fallback (symbol)\n)\n\nstyle = Lipgloss::Style.new.foreground(color)\n```\n\n**ANSI color symbols:** `:black`, `:red`, `:green`, `:yellow`, `:blue`, `:magenta`, `:cyan`, `:white`, and bright variants (`:bright_red`, etc.)\n\n**Complete adaptive colors:**\n\n```ruby\nlight = Lipgloss::CompleteColor.new(true_color: \"#000\", ansi256: :black, ansi: :black)\ndark = Lipgloss::CompleteColor.new(true_color: \"#FFF\", ansi256: :bright_white, ansi: :bright_white)\ncolor = Lipgloss::CompleteAdaptiveColor.new(light: light, dark: dark)\n\nstyle = Lipgloss::Style.new.foreground(color)\n```\n\n### Style Inheritance\n\n**Inherit styles from a parent:**\n\n```ruby\nbase = Lipgloss::Style.new\n  .foreground(\"#FF0000\")\n  .bold(true)\n\nchild = Lipgloss::Style.new\n  .padding(1)\n  .inherit(base)  # Inherits foreground and bold\n\nputs child.render(\"Inherited style!\")\n```\n\n**Unset specific properties:**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .bold(true)\n  .foreground(\"#FF0000\")\n  .unset_bold        # Remove bold\n  .unset_foreground  # Remove foreground color\n```\n\n### SetString\n\n**Set default text for a style:**\n\n```ruby\nstyle = Lipgloss::Style.new\n  .bold(true)\n  .foreground(\"#7D56F4\")\n  .set_string(\"Hello!\")\n\nputs style.to_s  # Renders \"Hello!\" with the style\n```\n\n### Tables\n\n**Create styled tables:**\n\n```ruby\ntable = Lipgloss::Table.new\n  .headers([\"Language\", \"Greeting\"])\n  .rows([\n    [\"English\", \"Hello\"],\n    [\"Spanish\", \"Hola\"],\n    [\"Japanese\", \"こんにちは\"]\n  ])\n  .border(:rounded)\n\nputs table.render\n```\n\n**Style cells with StyleFunc:**\n\n```ruby\nheader_style = Lipgloss::Style.new.bold(true).background(\"#5A56E0\")\neven_style = Lipgloss::Style.new.background(\"#3C3C3C\")\nodd_style = Lipgloss::Style.new.background(\"#4A4A4A\")\n\ntable = Lipgloss::Table.new\n  .headers([\"Name\", \"Role\"])\n  .rows([[\"Alice\", \"Engineer\"], [\"Bob\", \"Designer\"]])\n  .border(:rounded)\n  .style_func(rows: 2, columns: 2) do |row, column|\n    if row == Lipgloss::Table::HEADER_ROW\n      header_style\n    elsif row.even?\n      even_style\n    else\n      odd_style\n    end\n  end\n\nputs table.render\n```\n\n### Lists\n\n**Create styled lists:**\n\n```ruby\nlist = Lipgloss::List.new\n  .items([\"First item\", \"Second item\", \"Third item\"])\n  .enumerator(:bullet)\n\nputs list.render\n```\n\n**Available enumerators:**\n\n| Enumerator  | Output             |\n|-------------|--------------------|\n| `:bullet`   | `•`                |\n| `:dash`     | `-`                |\n| `:asterisk` | `*`                |\n| `:arabic`   | `1.`, `2.`, `3.`   |\n| `:alphabet` | `A.`, `B.`, `C.`   |\n| `:roman`    | `I.`, `II.`, `III.` |\n\n**Styled list items:**\n\n```ruby\nlist = Lipgloss::List.new\n  .items([\"Red\", \"Green\", \"Blue\"])\n  .enumerator(:bullet)\n  .enumerator_style(Lipgloss::Style.new.foreground(\"#FF0000\"))\n  .item_style(Lipgloss::Style.new.bold(true))\n\nputs list.render\n```\n\n### Trees\n\n**Create tree structures:**\n\n```ruby\ntree = Lipgloss::Tree.root(\"Project\")\n  .child(\"src\")\n  .child(\"lib\")\n  .child(\"test\")\n\nputs tree.render\n```\n\n**Nested trees:**\n\n```ruby\nsrc = Lipgloss::Tree.root(\"src\").child(\"main.rb\").child(\"helper.rb\")\ntest = Lipgloss::Tree.root(\"test\").child(\"test_main.rb\")\n\ntree = Lipgloss::Tree.root(\"Project\")\n  .child(src)\n  .child(test)\n\nputs tree.render\n```\n\n## Style Methods\n\n### Text Formatting\n\n| Method                | Description                   |\n|-----------------------|-------------------------------|\n| `bold(bool)`          | Bold text                     |\n| `italic(bool)`        | Italic text                   |\n| `underline(bool)`     | Underlined text               |\n| `strikethrough(bool)` | Strikethrough text            |\n| `reverse(bool)`       | Reverse foreground/background |\n| `blink(bool)`         | Blinking text                 |\n| `faint(bool)`         | Dimmed text                   |\n\n### Colors\n\n| Method                     | Description             |\n|----------------------------|-------------------------|\n| `foreground(color)`        | Text color              |\n| `background(color)`        | Background color        |\n| `margin_background(color)` | Margin background color |\n\n### Dimensions\n\n| Method           | Description    |\n|------------------|----------------|\n| `width(int)`     | Set width      |\n| `height(int)`    | Set height     |\n| `max_width(int)` | Maximum width  |\n| `max_height(int)`| Maximum height |\n\n### Spacing\n\n| Method                                         | Description           |\n|------------------------------------------------|-----------------------|\n| `padding(top, right, bottom, left)`            | Padding (CSS shorthand) |\n| `padding_top(int)`, `padding_right(int)`, etc. | Individual padding    |\n| `margin(top, right, bottom, left)`             | Margin (CSS shorthand) |\n| `margin_top(int)`, `margin_right(int)`, etc.   | Individual margin     |\n\n### Borders\n\n| Method                                         | Description                 |\n|------------------------------------------------|-----------------------------|\n| `border(type, *sides)`                         | Set border type and sides   |\n| `border_style(type)`                           | Set border type only        |\n| `border_foreground(color)`                     | Border color (all sides)    |\n| `border_background(color)`                     | Border background (all sides) |\n| `border_top_foreground(color)`, etc.           | Per-side border colors      |\n| `border_top_background(color)`, etc.           | Per-side border backgrounds |\n| `border_top(bool)`, `border_right(bool)`, etc. | Enable/disable sides        |\n| `border_custom(**opts)`                        | Custom border characters    |\n\n### Alignment\n\n| Method                        | Description          |\n|-------------------------------|----------------------|\n| `align(horizontal, vertical)` | Set alignment        |\n| `align_horizontal(position)`  | Horizontal alignment |\n| `align_vertical(position)`    | Vertical alignment   |\n\n**Position symbols:** `:top`, `:bottom`, `:left`, `:right`, `:center` (or numeric 0.0-1.0)\n\n### Other\n\n| Method             | Description                               |\n|--------------------|-------------------------------------------|\n| `inline(bool)`     | Render inline (no margins/padding/borders) |\n| `tab_width(int)`   | Tab character width (-1 to disable)       |\n| `set_string(text)` | Set default text                          |\n| `inherit(style)`   | Inherit from another style                |\n| `to_s`             | Render with default text                  |\n\n### Unset Methods\n\n| Method                                 | Description          |\n|----------------------------------------|----------------------|\n| `unset_bold`, `unset_italic`, etc.     | Clear text formatting |\n| `unset_foreground`, `unset_background` | Clear colors         |\n| `unset_width`, `unset_height`          | Clear dimensions     |\n| `unset_padding_top`, etc.              | Clear padding        |\n| `unset_margin_top`, etc.               | Clear margin         |\n| `unset_border_style`                   | Clear border         |\n| `unset_inline`                         | Clear inline         |\n\n## Module Methods\n\n| Method                                                    | Description               |\n|-----------------------------------------------------------|---------------------------|\n| `Lipgloss.join_horizontal(position, *strings)`            | Join strings horizontally |\n| `Lipgloss.join_vertical(position, *strings)`              | Join strings vertically   |\n| `Lipgloss.width(string)`                                  | Get rendered width        |\n| `Lipgloss.height(string)`                                 | Get rendered height       |\n| `Lipgloss.size(string)`                                   | Get `[width, height]`     |\n| `Lipgloss.place(width, height, h_pos, v_pos, string)`     | Place in whitespace       |\n| `Lipgloss.place_horizontal(width, position, string)`      | Place horizontally        |\n| `Lipgloss.place_vertical(height, position, string)`       | Place vertically          |\n| `Lipgloss.has_dark_background?`                           | Check terminal background |\n\n### Color Blending\n\n| Method                                                         | Description                    |\n|----------------------------------------------------------------|--------------------------------|\n| `Lipgloss::ColorBlend.blend(c1, c2, t, mode:)`                 | Blend two colors (0.0-1.0)     |\n| `Lipgloss::ColorBlend.blends(c1, c2, steps, mode:)`            | Generate color gradient array  |\n| `Lipgloss::ColorBlend.grid(c1, c2, c3, c4, x, y, mode:)`       | Generate 2D color grid         |\n\n**Blend modes:** `:luv` (default, perceptually uniform), `:rgb`, `:hcl`\n\n#### Generate a 5-color gradient\n\n```ruby\ncolors = Lipgloss::ColorBlend.blends(\"#FF0000\", \"#0000FF\", 5)\n# =\u003e [\"#ff0000\", \"#c1007f\", \"#7a00c1\", \"#0000ff\", ...]\n```\n\n#### Blend two colors at 50%\n\n```ruby\nmid = Lipgloss::ColorBlend.blend(\"#FF0000\", \"#00FF00\", 0.5)\n# =\u003e \"#b5b500\"\n```\n\n## Development\n\n**Requirements:**\n- Go 1.23+\n- Ruby 3.2+\n\n**Install dependencies:**\n\n```bash\nbundle install\n```\n\n**Build the Go library and compile the extension:**\n\n```bash\nbundle exec rake compile\n```\n\n**Run tests:**\n\n```bash\nbundle exec rake test\n```\n\n**Run demos:**\n\n```bash\n./demo/basic\n./demo/colors\n./demo/layout\n./demo/table\n./demo/list\n./demo/tree\n```\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/marcoroth/lipgloss-ruby.\n\n## License\n\nThe gem is available as open source under the terms of the MIT License.\n\n## Acknowledgments\n\nThis gem wraps [charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss), part of the excellent [Charm](https://charm.sh) ecosystem. Charm Ruby is not affiliated with or endorsed by Charmbracelet, Inc.\n\n---\n\nPart of [Charm Ruby](https://charm-ruby.dev).\n\n\u003ca href=\"https://charm-ruby.dev\"\u003e\u003cimg alt=\"Charm Ruby\" src=\"https://marcoroth.dev/images/heros/glamorous-christmas.png\" width=\"400\"\u003e\u003c/a\u003e\n\n[Lipgloss](https://github.com/marcoroth/lipgloss-ruby) • [Bubble Tea](https://github.com/marcoroth/bubbletea-ruby) • [Bubbles](https://github.com/marcoroth/bubbles-ruby) • [Glamour](https://github.com/marcoroth/glamour-ruby) • [Huh?](https://github.com/marcoroth/huh-ruby) • [Harmonica](https://github.com/marcoroth/harmonica-ruby) • [Bubblezone](https://github.com/marcoroth/bubblezone-ruby) • [Gum](https://github.com/marcoroth/gum-ruby) • [ntcharts](https://github.com/marcoroth/ntcharts-ruby)\n\nThe terminal doesn't have to be boring.\n","funding_links":["https://github.com/sponsors/marcoroth"],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcoroth%2Flipgloss-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcoroth%2Flipgloss-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcoroth%2Flipgloss-ruby/lists"}