Skip to content

Releases: charmbracelet/lipgloss

v0.11.1

10 Jul 14:10
v0.11.1
e6edbac
Compare
Choose a tag to compare

A lil’ truncation fix

This release is a small patch release to fix text truncation in table cells. For details see: #324.

Other stuff

Full Changelog: v0.11.0...v0.11.1


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Discord.

v0.11.0

23 May 18:57
5cd858c
Compare
Choose a tag to compare

Immutable Styles and Raw Speed, Baby

So! The big news in this release is:

  • Style methods will now always return new styles
  • Style and ANSI operations under the hood are faster

There are also a handful of great lil' bug fixes. Read on for more.

Immutable Styles

Every Style method now returns a completely new style with its own underlying data structure no matter what. This means working with Styles is a lot easier. No more need for Copy()!

// Before
s := lipgloss.NewStyle().Bold(true)
newStyle := s.Copy()

// After
s := lipgloss.NewStyle().Bold(true)
newStyle := s // this is a true copy

Okay, but why are styles easier to work with now? Consider this:

// Before
baseStyle := lipgloss.NewStyle().Background(lipgloss.Color("59"))
styleAtRuntime := baseStyle.Copy().Width(m.Width)

// After
baseStyle := lipgloss.NewStyle().Padding(1, 2)
styleAtRuntime := baseStyle.Width(m.Width)

It might seem small, but eliminating the risk of mutations in persistent styles in an enormous usability improvement.

How to upgrade

There's nothing to do, however Style.Copy() is now deprecated and only returns itself, so you can just remove Style.Copy() calls. If you need to just copy a style without any changes to it you can simply b := a.

Faster ANSI

Sometimes watch companies brag about their "in-house" watch movement. Well, now we're bragging about our in-house-amazing x/ansi library by our own @aymanbagabas. It's a fine-tuned, low-level way to manage ANSI sequencing and, because we're pretty nerdy, we’re super excited about it.


What's Changed

New!

Changed

Fixed

  • fix combining both conditional and unconditional wrapping by @aymanbagabas in #275
  • fix UnderlineSpaces and StrikethroughSpaces by @Taz03 in #299
  • always render horizontal border edges when enabled by @UnseenBook in #211
  • fix possible nil panic by @maaslalani in #245
  • fix transform operating on ANSI sequences by @meowgorithm in #274
  • change propkeys from int to int64 by @hugoleodev in #291

New Contributors

Full Changelog: v0.10.0...v0.11.0


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Discord.

v0.10.0

05 Mar 15:57
v0.10.0
439c06f
Compare
Choose a tag to compare

String Transforms πŸ’„

Lip Gloss v0.10.0 features a brand new Transform function for Styles to alter strings at render time. As well as some bug fixes, like ANSI-aware table cell truncation. 🧹

Simply define a Transform function as func (string) string and apply it to any style:

// Example:
s := NewStyle().Transform(strings.ToUpper)
fmt.Println(s.Render("raow!") // "RAOW!"

Or, if you prefer:

// Example:
reverse := func(s string) string {
    n := 0
    rune := make([]rune, len(s))
    for _, r := range s {
        rune[n] = r
	n++
    }
    rune = rune[0:n]
    for i := 0; i < n/2; i++ {
        rune[i], rune[n-1-i] = rune[n-1-i], rune[i]
    }
    return string(rune)
}

s := NewStyle().Transform(reverse)
fmt.Println(s.Render("The quick brown 狐 jumped over the lazy 犬")
// "犬 yzal eht revo depmuj 狐 nworb kciuq ehT",

What's Changed?

New Contributors

Full Changelog: v0.9.1...v0.10.0


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Discord.

v0.9.1

12 Oct 05:14
v0.9.1
f093bc1
Compare
Choose a tag to compare

This bugfix release changes the Table Headers API to accept []string for consistency with Row / Rows and downgrades Lip Gloss to Go version v1.17.

What's Changed

Full Changelog: v0.9.0...v0.9.1

v0.9.0

10 Oct 15:33
v0.9.0
4476263
Compare
Choose a tag to compare

My, how the tables have turned

Now you can draw Tables with Lip Gloss! πŸ’…

image

View the source code.

Let's get started

import "github.com/charmbracelet/lipgloss/table"

Define some rows of data.

rows := [][]string{
    {"Chinese", "您ε₯½", "δ½ ε₯½"},
    {"Japanese", "こんにけは", "やあ"},
    {"Arabic", "Ψ£Ω‡Ω„ΩŠΩ†", "Ψ£Ω‡Ω„Ψ§"},
    {"Russian", "ЗдравствуйтС", "ΠŸΡ€ΠΈΠ²Π΅Ρ‚"},
    {"Spanish", "Hola", "ΒΏQuΓ© tal?"},
}

Use the table package to style and render the table.

t := table.New().
    Border(lipgloss.NormalBorder()).
    BorderStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("99"))).
    StyleFunc(func(row, col int) lipgloss.Style {
        switch {
        case row == 0:
            return HeaderStyle
        case row%2 == 0:
            return EvenRowStyle
        default:
            return OddRowStyle
        }
    }).
    Headers("LANGUAGE", "FORMAL", "INFORMAL").
    Rows(rows...)

// You can also add tables row-by-row
t.Row("English", "You look absolutely fabulous.", "How's it going?")

Print the table.

fmt.Println(t)
Table example

For more on tables see the examples.

Additional Borders

Lip Gloss' Border now supports additional middle border separators.

type Border struct {
    // ...
    MiddleLeft   string
    MiddleRight  string
    Middle       string
    MiddleTop    string
    MiddleBottom string
}

v0.8.0

22 Aug 18:36
07d2272
Compare
Choose a tag to compare

Predictable Tabs

At last: tabs that render the way you want ’em to. With the new Style.TabWidth() method, you can determine exactly how a \t will render.

Before this release, Lip Gloss used to mis-measure a tab (i.e. a \t) at 0 cells wide when they actually render at different widths in different terminals (usually 8 cells, sometimes 4 cells). For these reasons, tabs are almost never what you want when designing layouts for TUIs.

With this release, a tab will get converted to 4 spaces by defaultβ€”so this is a behavioral changeβ€”but you can customize the behavior as well as disable it entirely.

s := lipgloss.NewStyle()        // 4 spaces per tab, the default
s = s.TabWidth(2)               // 2 spaces per tab
s = s.TabWidth(0)               // remove tabs
s = s.TabWidth(-1)              // don't convert tabs to spaces
s = s.TabWidth(NoTabConversion) // alias of the above

You can disable the feature with Style.TabWidth(NoTabConversion) (or Style.TabWidth(-1), if you're the pedantic type).

Bug Fixes

This release also includes a bunch of bug fixes. This includes:


Full Changelog: v0.7.1...v0.8.0

v0.7.1

09 Mar 19:14
Compare
Choose a tag to compare

This bugfix release fixes a problem introduced in v0.7.0 where applications could freeze or hang on start-up.

What's Changed

Full Changelog: v0.7.0...v0.7.1

v0.7.0

08 Mar 20:29
19ca9a3
Compare
Choose a tag to compare

Custom Renderers

We're pleased to introduce custom renders for Lip Gloss! Custom renderers allow you to render to a specific outputs, which is particularly important when you want to detect the color profile and dark background status for multiple different outputs at runtime, such as in a server-client situation.

Here's what it looks like:

func myLittleHandler(sess ssh.Session) {
    // Create a renderer for the client.
    renderer := lipgloss.NewRenderer(sess)

    // Create a new style on the renderer.
    style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: "63", Dark: "228"})

    // Render. The color profile and dark background state will be correctly detected.
    io.WriteString(sess, style.Render("Heyyyyyyy"))
}

For a full example on using a custom renderer over SSH with Wish see the SSH example.

New API Stuff

  • type Renderer struct
  • NewRenderer(io.Writer)
  • DefaultRenderer()
  • SetDefaultRenderer(*lipgloss.Renderer)
  • style.Renderer(*lipgloss.Renderer) Style

What's Changed

New

Fixed

New Contributors

Full Changelog: v0.6.0...v0.7.0

v0.6.0

06 Sep 18:36
Compare
Choose a tag to compare

Vertical Alignment & Per-Profile Color Settings

In this latest release of Lip Gloss, styles now support vertical alignment! Additionally, we introduced two new color types, CompleteColor and CompleteAdaptiveColor, which lets you bypass automatic color interpolation choose colors for each color profile (ANSI, ANSI256, and TrueColor).

Align content in a Style vertically at the top, center, or bottom. To get started make a style with some Height and an AlignVertical property.

lipgloss.NewStyle().Height(5).AlignVertical(lipgloss.Center).Render("Hello, Center!")

or use the Align shorthand which sets both horizontal and vertical alignments:

lipgloss.NewStyle().Height(5).Align(lipgloss.Left, lipgloss.Bottom).Render("Hello, Center!")

image

New API:

Note, there are no breaking changes since if the Align shorthand will still accept 1 argument (variadic arguments) and will set only the horizontal alignment to maintain original functionality

  • Align(p ...Position)
  • AlignVertical(p Position)
  • AlignHorizontal(p Position)
  • GetAlignVertical() Position
  • GetAlignHorizontal() Position

Complete Colors

This revision introduces two new color types CompleteColor and CompleteAdaptiveColor. Not for the faint of heart, these types are for bypassing automatic color interpolation so you can specify exact colors for all color profiles in cases where the interpolation can benefit from manual adjustment:

cc := CompleteColor{
	TrueColor: "#6B51FF",
	ANSI256: "63",
	ANSI: "5",
}

cac := CompleteAdaptiveColor{
	Light: CompleteColor{
		TrueColor: "#FF51CE",
		ANSI256: "213",
		ANSI: "5",
	},
	Dark: CompleteColor{
		TrueColor: "#6B51FF",
		ANSI256: "63",
		ANSI: "5",
	},
}

New

Fixed

  • Protect against concurrent color profile access with a sync.RWMutex by @meowgorithm in #68
  • don't overwrite background when inheriting by @76creates in #69

New Contributors

Full Changelog: v0.5.0...v0.6.0


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Slack.

v0.5.0

14 Feb 21:41
Compare
Choose a tag to compare

Laziness

Happy Valentines Day! Have you ever noticed that programming is the one field where laziness is totally awesome?

The big news in this release is that Lip Gloss will now wait until absolutely necessary to query for the terminal's background color. This was formerly a fairly heavy hit on the system, however it's been optimized to the point where we can now run it on demand. This, and some other major performance benefits, come from some acute improvements upstream in Termenv. For the low level details check out the release notes for the mighty Termenv v0.10.0 and v0.11.0 releases.

New

  • Styles now have a Value() method for getting the underlying string value set with SetString() (thanks @76creates) #66

Improved

  • Lazily detect the background color #61
  • Use termenv's EnvColorProfile, which respects NO_COLOR and CLICOLOR_FORCE env vars #64

Fixed

  • Fix JoinVertical behavior for non-edge non-center alignments (thanks @ryantriangles) #49

New Contributors

Full Changelog: v0.4.0...v0.5.0


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Slack.