GithubHelp home page GithubHelp logo

charmbracelet / lipgloss Goto Github PK

View Code? Open in Web Editor NEW
7.4K 36.0 196.0 532 KB

Style definitions for nice terminal layouts 👄

License: MIT License

Go 100.00%
tui go golang cli layout style hacktoberfest

lipgloss's Introduction

Lip Gloss

Lip Gloss title treatment
Latest Release GoDoc Build Status phorm.ai

Style definitions for nice terminal layouts. Built with TUIs in mind.

Lip Gloss example

Lip Gloss takes an expressive, declarative approach to terminal rendering. Users familiar with CSS will feel at home with Lip Gloss.

import "github.com/charmbracelet/lipgloss"

var style = lipgloss.NewStyle().
    Bold(true).
    Foreground(lipgloss.Color("#FAFAFA")).
    Background(lipgloss.Color("#7D56F4")).
    PaddingTop(2).
    PaddingLeft(4).
    Width(22)

fmt.Println(style.Render("Hello, kitty"))

Colors

Lip Gloss supports the following color profiles:

ANSI 16 colors (4-bit)

lipgloss.Color("5")  // magenta
lipgloss.Color("9")  // red
lipgloss.Color("12") // light blue

ANSI 256 Colors (8-bit)

lipgloss.Color("86")  // aqua
lipgloss.Color("201") // hot pink
lipgloss.Color("202") // orange

True Color (16,777,216 colors; 24-bit)

lipgloss.Color("#0000FF") // good ol' 100% blue
lipgloss.Color("#04B575") // a green
lipgloss.Color("#3C3C3C") // a dark gray

...as well as a 1-bit ASCII profile, which is black and white only.

The terminal's color profile will be automatically detected, and colors outside the gamut of the current palette will be automatically coerced to their closest available value.

Adaptive Colors

You can also specify color options for light and dark backgrounds:

lipgloss.AdaptiveColor{Light: "236", Dark: "248"}

The terminal's background color will automatically be detected and the appropriate color will be chosen at runtime.

Complete Colors

CompleteColor specifies exact values for truecolor, ANSI256, and ANSI color profiles.

lipgloss.CompleteColor{True: "#0000FF", ANSI256: "86", ANSI: "5"}

Automatic color degradation will not be performed in this case and it will be based on the color specified.

Complete Adaptive Colors

You can use CompleteColor with AdaptiveColor to specify the exact values for light and dark backgrounds without automatic color degradation.

lipgloss.CompleteAdaptiveColor{
    Light: CompleteColor{TrueColor: "#d7ffae", ANSI256: "193", ANSI: "11"},
    Dark:  CompleteColor{TrueColor: "#d75fee", ANSI256: "163", ANSI: "5"},
}

Inline Formatting

Lip Gloss supports the usual ANSI text formatting options:

var style = lipgloss.NewStyle().
    Bold(true).
    Italic(true).
    Faint(true).
    Blink(true).
    Strikethrough(true).
    Underline(true).
    Reverse(true)

Block-Level Formatting

Lip Gloss also supports rules for block-level formatting:

// Padding
var style = lipgloss.NewStyle().
    PaddingTop(2).
    PaddingRight(4).
    PaddingBottom(2).
    PaddingLeft(4)

// Margins
var style = lipgloss.NewStyle().
    MarginTop(2).
    MarginRight(4).
    MarginBottom(2).
    MarginLeft(4)

There is also shorthand syntax for margins and padding, which follows the same format as CSS:

// 2 cells on all sides
lipgloss.NewStyle().Padding(2)

// 2 cells on the top and bottom, 4 cells on the left and right
lipgloss.NewStyle().Margin(2, 4)

// 1 cell on the top, 4 cells on the sides, 2 cells on the bottom
lipgloss.NewStyle().Padding(1, 4, 2)

// Clockwise, starting from the top: 2 cells on the top, 4 on the right, 3 on
// the bottom, and 1 on the left
lipgloss.NewStyle().Margin(2, 4, 3, 1)

Aligning Text

You can align paragraphs of text to the left, right, or center.

var style = lipgloss.NewStyle().
    Width(24).
    Align(lipgloss.Left).  // align it left
    Align(lipgloss.Right). // no wait, align it right
    Align(lipgloss.Center) // just kidding, align it in the center

Width and Height

Setting a minimum width and height is simple and straightforward.

var style = lipgloss.NewStyle().
    SetString("What’s for lunch?").
    Width(24).
    Height(32).
    Foreground(lipgloss.Color("63"))

Borders

Adding borders is easy:

// Add a purple, rectangular border
var style = lipgloss.NewStyle().
    BorderStyle(lipgloss.NormalBorder()).
    BorderForeground(lipgloss.Color("63"))

// Set a rounded, yellow-on-purple border to the top and left
var anotherStyle = lipgloss.NewStyle().
    BorderStyle(lipgloss.RoundedBorder()).
    BorderForeground(lipgloss.Color("228")).
    BorderBackground(lipgloss.Color("63")).
    BorderTop(true).
    BorderLeft(true)

// Make your own border
var myCuteBorder = lipgloss.Border{
    Top:         "._.:*:",
    Bottom:      "._.:*:",
    Left:        "|*",
    Right:       "|*",
    TopLeft:     "*",
    TopRight:    "*",
    BottomLeft:  "*",
    BottomRight: "*",
}

There are also shorthand functions for defining borders, which follow a similar pattern to the margin and padding shorthand functions.

// Add a thick border to the top and bottom
lipgloss.NewStyle().
    Border(lipgloss.ThickBorder(), true, false)

// Add a double border to the top and left sides. Rules are set clockwise
// from top.
lipgloss.NewStyle().
    Border(lipgloss.DoubleBorder(), true, false, false, true)

For more on borders see the docs.

Copying Styles

Just use Copy():

var style = lipgloss.NewStyle().Foreground(lipgloss.Color("219"))

var wildStyle = style.Copy().Blink(true)

Copy() performs a copy on the underlying data structure ensuring that you get a true, dereferenced copy of a style. Without copying, it's possible to mutate styles.

Inheritance

Styles can inherit rules from other styles. When inheriting, only unset rules on the receiver are inherited.

var styleA = lipgloss.NewStyle().
    Foreground(lipgloss.Color("229")).
    Background(lipgloss.Color("63"))

// Only the background color will be inherited here, because the foreground
// color will have been already set:
var styleB = lipgloss.NewStyle().
    Foreground(lipgloss.Color("201")).
    Inherit(styleA)

Unsetting Rules

All rules can be unset:

var style = lipgloss.NewStyle().
    Bold(true).                        // make it bold
    UnsetBold().                       // jk don't make it bold
    Background(lipgloss.Color("227")). // yellow background
    UnsetBackground()                  // never mind

When a rule is unset, it won't be inherited or copied.

Enforcing Rules

Sometimes, such as when developing a component, you want to make sure style definitions respect their intended purpose in the UI. This is where Inline and MaxWidth, and MaxHeight come in:

// Force rendering onto a single line, ignoring margins, padding, and borders.
someStyle.Inline(true).Render("yadda yadda")

// Also limit rendering to five cells
someStyle.Inline(true).MaxWidth(5).Render("yadda yadda")

// Limit rendering to a 5x5 cell block
someStyle.MaxWidth(5).MaxHeight(5).Render("yadda yadda")

Tabs

The tab character (\t) is rendered differently in different terminals (often as 8 spaces, sometimes 4). Because of this inconsistency, Lip Gloss converts tabs to 4 spaces at render time. This behavior can be changed on a per-style basis, however:

style := lipgloss.NewStyle() // tabs will render as 4 spaces, the default
style = style.TabWidth(2)    // render tabs as 2 spaces
style = style.TabWidth(0)    // remove tabs entirely
style = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact

Rendering

Generally, you just call the Render(string...) method on a lipgloss.Style:

style := lipgloss.NewStyle().Bold(true).SetString("Hello,")
fmt.Println(style.Render("kitty.")) // Hello, kitty.
fmt.Println(style.Render("puppy.")) // Hello, puppy.

But you could also use the Stringer interface:

var style = lipgloss.NewStyle().SetString("你好,猫咪。").Bold(true)
fmt.Println(style) // 你好,猫咪。

Custom Renderers

Custom renderers allow you to render to a specific outputs. This is particularly important when you want to render to different outputs and correctly detect the color profile and dark background status for each, such as in a server-client situation.

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 an example on using a custom renderer over SSH with Wish see the SSH example.

Utilities

In addition to pure styling, Lip Gloss also ships with some utilities to help assemble your layouts.

Joining Paragraphs

Horizontally and vertically joining paragraphs is a cinch.

// Horizontally join three paragraphs along their bottom edges
lipgloss.JoinHorizontal(lipgloss.Bottom, paragraphA, paragraphB, paragraphC)

// Vertically join two paragraphs along their center axes
lipgloss.JoinVertical(lipgloss.Center, paragraphA, paragraphB)

// Horizontally join three paragraphs, with the shorter ones aligning 20%
// from the top of the tallest
lipgloss.JoinHorizontal(0.2, paragraphA, paragraphB, paragraphC)

Measuring Width and Height

Sometimes you’ll want to know the width and height of text blocks when building your layouts.

// Render a block of text.
var style = lipgloss.NewStyle().
    Width(40).
    Padding(2)
var block string = style.Render(someLongString)

// Get the actual, physical dimensions of the text block.
width := lipgloss.Width(block)
height := lipgloss.Height(block)

// Here's a shorthand function.
w, h := lipgloss.Size(block)

Placing Text in Whitespace

Sometimes you’ll simply want to place a block of text in whitespace.

// Center a paragraph horizontally in a space 80 cells wide. The height of
// the block returned will be as tall as the input paragraph.
block := lipgloss.PlaceHorizontal(80, lipgloss.Center, fancyStyledParagraph)

// Place a paragraph at the bottom of a space 30 cells tall. The width of
// the text block returned will be as wide as the input paragraph.
block := lipgloss.PlaceVertical(30, lipgloss.Bottom, fancyStyledParagraph)

// Place a paragraph in the bottom right corner of a 30x80 cell space.
block := lipgloss.Place(30, 80, lipgloss.Right, lipgloss.Bottom, fancyStyledParagraph)

You can also style the whitespace. For details, see the docs.

Rendering Tables

Lip Gloss ships with a table rendering sub-package.

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 docs and examples.


FAQ

Why are things misaligning? Why are borders at the wrong widths?

This is most likely due to your locale and encoding, particularly with regard to Chinese, Japanese, and Korean (for example, zh_CN.UTF-8 or ja_JP.UTF-8). The most direct way to fix this is to set RUNEWIDTH_EASTASIAN=0 in your environment.

For details see https://github.com/charmbracelet/lipgloss/issues/40.

Why isn't Lip Gloss displaying colors?

Lip Gloss automatically degrades colors to the best available option in the given terminal, and if output's not a TTY it will remove color output entirely. This is common when running tests, CI, or when piping output elsewhere.

If necessary, you can force a color profile in your tests with SetColorProfile.

import (
    "github.com/charmbracelet/lipgloss"
    "github.com/muesli/termenv"
)

lipgloss.SetColorProfile(termenv.TrueColor)

Note: this option limits the flexibility of your application and can cause ANSI escape codes to be output in cases where that might not be desired. Take careful note of your use case and environment before choosing to force a color profile.

What about Bubble Tea?

Lip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea companion. It was designed to make assembling terminal user interface views as simple and fun as possible so that you can focus on building your application instead of concerning yourself with low-level layout details.

In simple terms, you can use Lip Gloss to help build your Bubble Tea views.

Under the Hood

Lip Gloss is built on the excellent Termenv and Reflow libraries which deal with color and ANSI-aware text operations, respectively. For many use cases Termenv and Reflow will be sufficient for your needs.

Rendering Markdown

For a more document-centric rendering solution with support for things like lists, tables, and syntax-highlighted code have a look at Glamour, the stylesheet-based Markdown renderer.

Feedback

We’d love to hear your thoughts on this project. Feel free to drop us a note!

License

MIT


Part of Charm.

The Charm logo

Charm热爱开源 • Charm loves open source

lipgloss's People

Contributors

76creates avatar ahmedkhalf avatar alyxpractice avatar aymanbagabas avatar bashbunni avatar benwaffle avatar caarlos0 avatar dependabot[bot] avatar evertras avatar gzipchrist avatar ismaelpadilla avatar isti115 avatar kiyonlin avatar maaslalani avatar mark2185 avatar meowgorithm avatar mikelorant avatar muesli avatar nerg4l avatar nervo avatar reidmason avatar schmurfy avatar stefanvanburen avatar trytriangles avatar unseenbook avatar winder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lipgloss's Issues

Rendering Issues with zh_CN.UTF-8

Hello, when I run the example on mac, the typesetting is out of order, what's the matter?

  • My system is macOS Big Sur 11.4
  • Terminal is oh-my-zsh

image

Width issue with certain emoji

While checking out the ssh git.charm.ssh demo, I noticed that the window showing the "Home" tab ends up rendering an incorrect border when certain emoji are used in a line:

image-2

Hard to know exactly which emoji would cause this, but these two being used in the demo definitely are!

Border size computations look wrong

  1. GetBorderTopSize and GetBorderBottomSize returns the maximum rune width of all the border characters.
    This is wrong: the top/bottom border sizes are just 1 (1 line)

  2. GetBorderLeftSize and GetBorderRightSize are using maxRuneWidth() on every part, but they should use runewidth.StringWidth() instead.

Found while working on #109

Border background color is not inherited?

Since the Background property does not apply to borders (they have their own background keys),
Inherit should apply the background color to the borders as well.

Found while working on #109.

New API: fast colors

Hi,

I'm building a new tool that requires a lot of Render calls (right now I prerender every line for a viewbox). The cpu profile shows lipgloss.Render func is taking lots of time:
Снимок экрана 2022-04-14 в 18 13 49

But I use only colors. Is it possible to add new methods, which allow to access only color functionality (no padding, borders, etc.)?

Thanks!

Unable to provide lipgloss background on text highlighted by Chroma

I attempted to highlight some JSON using Chroma and seemed to be unable to highlight the background of the highlighted text using lipgloss.

Code roughly looked like:

buf := new(bytes.Buffer)
quick.Highlight(buf, prettyJSON.String(), "json", utils.GetTerminalColorSupport(), chromaStyle.Name)
fmt.Println(lipgloss.NewStyle().Background(lipgloss.Color("22")).Render(buf.String()))

Resulted in:

image

Using a hex color for the background also did not work.

I can definitely try and provide more info if needed.

Formatting lost on linewrap

When rendering a long string with styles applied in a "box" the text formatting is lost when lines wrap.

Attached output + example code to reproduce (uses lipgloss 0.5.0)

Output
image

Code to reproduce

func main() {
	parts := strings.Split("aaaaaaaaaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccc", ".")
	formatted := fmt.Sprintf("%s.%s.%s",
		lipgloss.NewStyle().Foreground(lipgloss.Color("#874BFD")).Render(parts[0]),
		lipgloss.NewStyle().Foreground(lipgloss.Color("#ABE9B3")).Render(parts[1]),
		lipgloss.NewStyle().Foreground(lipgloss.Color("#89DCEB")).Render(parts[2]))

	dialogBoxStyle := lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		Padding(1, 1).
		Width(40).
		BorderTop(true).
		BorderLeft(true).
		BorderRight(true).
		BorderBottom(true)

	inp := dialogBoxStyle.BorderForeground(lipgloss.Color("#df8e1d")).Render(formatted)

	fmt.Println(inp)
}

encoding issue

Run on powershell

--placeholder='请选择颜色'

$s=@('黑色','白色','红色','蓝色') | gum filter --no-limit --placeholder='请选择颜色' | Where {$_ -notmatch 'failed'}

image

and filter text can not input unicode chars

Rendering issues

First of all, congratulations for the good job you have done.

I am configuring a server (redhat 8.4) to see the example correctly, but I havent achieved yet.

Reading the issues I got the colors to work

export TERM=xterm-256color
export COLORTERM=true

But Im still missing something. Could you please help me?

image

Thanks in advance

Long pause/halt when lipgloss is determining background color

Sometimes when running my program (very similar to the fancy list demo and using the same lipgloss variables), when my list is created, I see a very long pause. It doesn't happen all the time -- over half the time, but not every time -- but that pause can take anywhere from a few seconds to 30 seconds or more. I got a SIGQUIT stack trace -- it's down in termenv so let me know if you'd rather I post there than here, but since my entrypoint there is lipgloss I figured I'd start here.

goroutine 1 [syscall]:
syscall.syscall(0x10060cbe0, 0x1, 0x14000390077, 0x1)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/runtime/sys_darwin.go:22 +0x1c
syscall.read(0x1, {0x14000390077, 0x1, 0x1})
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/syscall/zsyscall_darwin_arm64.go:1171 +0x5c
syscall.Read(...)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/syscall/syscall_unix.go:189
internal/poll.ignoringEINTRIO(...)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/internal/poll/fd_unix.go:582
internal/poll.(*FD).Read(0x140001a0060, {0x14000390077, 0x1, 0x1})
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/internal/poll/fd_unix.go:163 +0x214
os.(*File).read(...)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/os/file_posix.go:32
os.(*File).Read(0x1400019e008, {0x14000390077, 0x1, 0x1})
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/os/file.go:119 +0x74
github.com/muesli/termenv.readNextByte(0x1400019e008)
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv_unix.go:135 +0x98
github.com/muesli/termenv.readNextResponse(0x1400019e008)
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv_unix.go:185 +0x1c8
github.com/muesli/termenv.termStatusReport(0xb)
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv_unix.go:246 +0x22c
github.com/muesli/termenv.backgroundColor()
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv_unix.go:85 +0x28
github.com/muesli/termenv.BackgroundColor()
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv.go:67 +0x6c
github.com/muesli/termenv.HasDarkBackground()
        /Users/jeff/go/pkg/mod/github.com/muesli/[email protected]/termenv.go:72 +0x20
github.com/charmbracelet/lipgloss.HasDarkBackground.func1()
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/color.go:60 +0x20
sync.(*Once).doSlow(0x1070a68a8, 0x10653e450)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/sync/once.go:68 +0x10c
sync.(*Once).Do(...)
        /opt/homebrew/Cellar/go/1.17.8/libexec/src/sync/once.go:59
github.com/charmbracelet/lipgloss.HasDarkBackground()
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/color.go:59 +0x5c
github.com/charmbracelet/lipgloss.AdaptiveColor.value(...)
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/color.go:167
github.com/charmbracelet/lipgloss.AdaptiveColor.color({{0x101437372, 0x7}, {0x101437491, 0x7}})
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/color.go:174 +0x2c
github.com/charmbracelet/lipgloss.Style.Render({0x140006749f0, {0x101432dc9, 0x3}}, {0x101432dc9, 0x3})
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/style.go:230 +0x10e0
github.com/charmbracelet/lipgloss.Style.String(...)
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/style.go:109
github.com/charmbracelet/bubbles/list.New({0x0, 0x0, 0x0}, {0x106585f38, 0x140000dea90}, 0x0, 0x0)
        /Users/jeff/go/pkg/mod/github.com/charmbracelet/[email protected]/list/list.go:165 +0x2a4
<my code>

Let me know what other info I can provide. Thanks!

Colors not working

Hey, somehow colors are not working for me.

What i did
Clone this Repo, cd into examples and ran go mod tidy to download deps.

What did i expect
See the exact same UI as in this Repos Readme. Sadly colors are not working for me
image

My Terminal supports 256 colors, so this should not be the problem.
image

Do you have any ideas what could cause this issue?

Best regards

Vertical Blocks Joined Centrally Not Centrally Aligned When Rendered By Vertically Aligned Style

Example code:
https://go.dev/play/p/m_4_YwnUyNI

Summary:
I'm trying to align a check box vertically with its header (which can differ based on the data). It seems that when I join the Header and the checkbox vertically, they're fine; the [X] had 3 sectors of whitespace to the left, and 2 the right.

However, when I then style that joined-string to a minwidth of 21 and align it centrally, the checkbox ends up with 10 sectors of whitespace to the left and 8 sectors to the right instead of 9 and 9.

Explicitly setting the color profile

Curious how y'all test the lipgloss output. I'm currently running into issues where the terminal colors are sometimes rendered in tests and sometimes they are not, and it seems to be based on which directory I'm running go test from. Any ideas on how to handle this?

Screen Shot 2021-05-26 at 10 16 31 AM

Style to pointer - CGO

Hi this is really not related to lipgloss and it's just a part of my Go journey. I want to use lipgloss with Nodejs via FFI + CGO but I have no idea how to convert a lipgloss.Style to a C pointer. I only know how to convert string using C.char etc...

package main

/*
#include <stdlib.h>
#include <string.h>
*/
import "C"

import (
	"fmt"
	"unsafe"

	"github.com/charmbracelet/lipgloss"
)

func main() {}

//export SimpleString
func SimpleString() *C.char {
	return C.CString("hello world")
}

//export CreateStyle
func CreateStyle() {
	var style = lipgloss.NewStyle().
		Bold(true).
		Foreground(lipgloss.Color("#FAFAFA")).
		Background(lipgloss.Color("#7D56F4")).
		PaddingTop(2).
		PaddingLeft(4).
		Width(22)

	// How to return style as a pointer?
}

any help would be much appreciated!

Rendering Issues on Windows

I found border rendering is very strange, I've tried on Windows Terminal and legacy CMD, both are missing some characters, am I missing some configs?
7cf793398ba9c0f97cad7e956f9ccf1
baff54d81acc85835c65aadec4cdad6
Here is my code:
logo := "foo bar" fmt.Printf(lipgloss.NewStyle().BorderStyle(lipgloss.DoubleBorder()).Render(logo))

BTW, I love this lib and bubbletea. I'm trying to build a cli tool in go, your repo is the most elegant framework I've ever seen. Thanks for building this.

(question) animated tui

Hi guys,

Hope you are all well !

I developed a tui for parsing my nginx/apache logs with termui but I am not a bug fan of the colors available with this package ^^

So, I tried the lipgloss example but could not figure out how to animate/update the content of pans.

Here is what I did with termui that I did like to igrate to lipgloss:
https://user-images.githubusercontent.com/1963546/134805573-fa3cd18d-1d82-4758-a461-109cc4912189.mp4

How can build a similar layout with lipgloss ? Is it possible ? How to update content of my tables ?

Thanks for any insights or inputs on these questions.

Cheers,
Luc Michalski

Revision cannot be found

While installing another library I got the error

/.../pkg/mod/github.com/charmbracelet/[email protected]/align.go:7:2: github.com/muesli/[email protected]: invalid version: unknown revision d729275e0977

was there a deleted revision? If yes, it possible to recreate it so other libraries do not fail to install?

Inline concatenates words from multiple lines

When I do style.Render("hello\nworld")
I am expecting 2 different words.

If I use Inline, the result is helloworld without space.

I think we want 2 separate words here, i.e. replace newlines by spaces during inline mode.

Found while working on #109.

Feature Request: Override AdaptiveColor, Force Dark/Light mode

Hey Team Charm,

I am currently using lipgloss.AdaptiveColor{} to adapt the colors of my TUI based on the user's color scheme. It is working great and I find this feature very useful.

I was wondering if there was I way where I could override which color AdaptiveColor resolves to, so that a user could run the program like so: cli --force-light-mode.

I can see this being useful where getting the color scheme is not possible, like from tmux or screen. It can also be useful where the user's color scheme borders between the cutoff point between dark and light.

Add ability to show block title over the border

The title could be shown either on top or bottom of the block.
Here one example of such UI

The API might look like the following

var style = lipgloss.NewStyle().
    BorderStyle(lipgloss.NormalBorder()).
    BorderForeground(lipgloss.Color("63")).
    Title(lipgloss.Top, "Title")

There is also a need to change the title dynamically

  style.SetTitle((lipgloss.Top, "New Title"))

Titles which do not fit the width of the block can be automatically truncated at the front or back. The fact of truncation can be represented by adding character

No colour on linux tty terminal

On Ubuntu - everything works fine in the Gnome Terminal and $TERM is xterm-256color

If I switch to tty console where the $TERM is linux then I get no colour. I expected it fall back to 4-bit, which is supported

Image rendering

Thanks, Was waiting for such a beauty a long time ago.

These people managed to render an image in a terminal with rust:
https://github.com/atanunq/viu

Is it possible to add an image rendering feature to lipgloss?

Thanks.

Emoji + Nerd Font Support?

I would love to see support for double width characters and also having functions to fetch emojis and nerd font icons by name, to help declutter all of the unicode symbols. This would also create an opportunity to have alternative icons when no double width characters are supported.

Example program outputs broken escape codes in Alacritty

When running the example program under Alacritty, some gibberish escape codes are printed at the beginning of the output:

2021-04-03_21-18-11_100001:lg:1

In the screenshot, I am running Alacritty in the left pane and Kitty in the right.

I'm not sure if this is an issue with the example program or the library itself. Other than the extraneous escape codes, both outputs look identical (and very cool!)

$ alacritty --version
alacritty 0.8.0-dev (d5dd009a)

VS Code test-output terminal does not render styles

Like any reasonable person with a three-year-old, I'm making a TUI Connect-4 clone for local network play (toddlers cannot physically prevent you from making a blocking move when they are in another room).

Testing my work-in-progress had me seriously confused:

c4Colors

Turns out that the terminal which displays the output from this inline test-running button (maybe the entire integrated test runner) doesn't display any colours. (You would certainly know better than me how to characterize the behaviour).

Note that this is not the case for VSCode's more general terminal:

c4colorsWorking

Suggestions:

  • a word of caution in the readme
  • file (or fix) upstream (I did not check for existing upstream issues)

Nice library. Enjoying the renewed interest and vigor in modernizing cli / tui tooling. Good luck!

Apply background on colored text

When aplying a style with background, it doesn't fill some whitespace after a colored text.
How to do it right?

example:

package main

import (
	"fmt"
	"strings"

	"github.com/charmbracelet/lipgloss"
)

var (
	box = lipgloss.NewStyle().
		Background(lipgloss.Color("237")).
		Padding(2)
	label = lipgloss.NewStyle().
		Foreground(lipgloss.Color("6"))
	text = lipgloss.NewStyle().
		Foreground(lipgloss.Color("9"))
)

func main() {
	var col1, col2 strings.Builder
	col1.WriteString(label.Render("foo:"))
	col1.WriteRune('\n')
	col1.WriteString(label.Render("bar:"))
	col2.WriteString(text.Render("1235"))
	col2.WriteRune('\n')
	col2.WriteString(text.Render("ABC"))
	fmt.Println(
		box.Render(
			lipgloss.JoinHorizontal(
				lipgloss.Bottom,
				col1.String(),
				lipgloss.NewStyle().PaddingLeft(5).Render(col2.String()),
			),
		),
	)
}

output:
screenshot

[Question] How to force text to wrap?

I created a UI with only 64 width, but if the text contains "file path", the text will not be forced to wrap:

The text contains "file path":

image

The text does not contain "file path":

image

weird wordwrapping

Hi, I'm facing some weird behavior when I use lipgloss to wrap some strings. Somehow it doesn't behave the same way as wrap.String() from @muesli's reflow package.

Example

package main

import (
	"fmt"

	"github.com/charmbracelet/lipgloss"
	"github.com/muesli/reflow/wrap"
)

var x = "x10-test, x10-ab, x10-test1, x10-test10-test, x10-testing-this"

func main() {
	fmt.Println(wrap.String(x, 28))
	fmt.Println(lipgloss.NewStyle().Width(28).Render(x))
}

Result

Using wrap.String() prints:

x10-test, x10-ab, x10-test1,
x10-test10-test, x10-testing
-this

Using lipgloss:

x10-test, x10-ab, x10-test1,
x10-test10-test, x10-testing
-
this

Is there an option I'm missing in lipgloss or am I wrong to expect them to behave the same?

Compositing

I'm trying to build an app that displays a popup which needs to be drawn on top of other view (bubble component). Is it possible to achieve that with lipgloss?

Faint style also affects the background

The docstring for the faint method specify that:

Faint sets a rule for rendering the foreground color in a dimmer shade.

However in my app the background is also affected:

image

Provide ability to prevent insertion of Reset sequence

I want to be able to concatenate two strings with different foreground colors, but not have termenv insert the reset sequence in between.
The reset sequence prevents the ability to set a shared background for the strings without setting a bg on both strings individually.

My use case is a custom table component I implemented.
When a row is selected, I apply a background on the entire row, but the bg is only applied on the first string, because of the reset sequence.

This is the raw string:

'\x1B[41m\x1B[38;5;245m#158\x1B[0m\x1B[38;5;245mDifferentiate draft PRs from open PRs\x1B[0m\x1B[0m'

Which is the result of calling:

	prNumber := lipgloss.NewStyle().Foreground("<some fg>").Render("#158")
	title := lipgloss.NewStyle().Foreground("<some other fg>").Render("Differentiate draft PRs from open PRs")
	lipgloss.NewStyle().Background(lipgloss.Color("1")).
		Render(fmt.Sprintf("%s%s", prNumber, title))

What have I tried

  • Using lipgloss.JoinHorizontal yields the same results
  • I can always do prNumber = strings.Replace(prNumber, "\x1b[0", "", -1) which works but feels hacky as it relies on the escape sequence encoding termenv is using.

Possible solution

Maybe provide a PreventReset() method on the lipgloss.Style?

Example for simple table with Borders

Really great library and examples, but I am struggling to render a table with borders.

It would be really useful to add an example for this. Seems like a common use case.

There are a few libraries that do complex interactive table around based on this library, but I'm looking for a really simple way to just render some text in a table, with the ability for additional styling (foreground / background color etc) with lipgloss.

Vertical Alignment

Lip Gloss currently supports horizontal alignment in blocks:

var style = lipgloss.NewStyle().Width(40).Align(lipgloss.Left)

It would also be handy to support vertical alignment:

var style = lipgloss.NewStyle().Width(40).Height(20).VerticalAlign(lipgloss.Bottom)

Currently, the only way to vertically align blocks is to manually add padding.

Piping to pager (eg. less -R) loses all color

I must be missing something obvious, but when I pipe any output of lipgloss to a pager, I lose all color formatting. I'm aware I need to use a -R flag on less in order to preserve escape codes. However, I can pipe straight to vim and see that no codes are preserved.

A minimal example:

package main

import (
	"fmt"

	"github.com/charmbracelet/lipgloss"
)

func main() {
	style := lipgloss.NewStyle().Foreground(lipgloss.Color("4"))
	fmt.Println(style.Render("Hello, world"))
}
$ go run ./

Output to terminal

(In blue) Hello, world

$ go run ./ | less -R

Output to less -R

(No color) Hello, world

Expected output to less -R

(In blue) Hello, world

Am I missing something??

Lazy loading dark background causes sporadic performance issues

Commit b3934f5 for some reason started causing major sporadic performance issues in my environment: the call to HasDarkBackground sometimes takes up to one minute to complete. About 50% of the time everything runs smoothly, and other 50% it gets stuck for at least a couple of seconds.

When checking out to v0.5.0 and running git revert b3934f5, the problem disappears. The issue exists on master as well.

My environment:
Alacritty 0.10.1
Tmux 3.3
Macos 12.4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.