From 33020470cf077ea7ea889e1091d709c2c27b583e Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 31 Oct 2024 15:39:19 -0400 Subject: [PATCH] feat(examples): add impure examples --- examples/go.mod | 13 +-- examples/go.sum | 8 ++ examples/impure/bubbletea/main.go | 144 +++++++++++++++++++++++++++++ examples/impure/standalone/main.go | 66 +++++++++++++ 4 files changed, 223 insertions(+), 8 deletions(-) create mode 100644 examples/impure/bubbletea/main.go create mode 100644 examples/impure/standalone/main.go diff --git a/examples/go.mod b/examples/go.mod index f53db7e6..a51b7139 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -2,16 +2,13 @@ module examples go 1.19 -replace github.com/charmbracelet/lipgloss => ../ - -replace github.com/charmbracelet/lipgloss/list => ../list - -replace github.com/charmbracelet/lipgloss/table => ../table +replace github.com/charmbracelet/lipgloss/v2 => ../ require ( - github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241016204941-d95e2750ec12 - github.com/charmbracelet/colorprofile v0.1.2 + github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241031180054-a3bec0b7b8a8 + github.com/charmbracelet/colorprofile v0.1.6 github.com/charmbracelet/lipgloss v0.13.1-0.20240822211938-b89f1a3db2a4 + github.com/charmbracelet/lipgloss/v2 v2.0.0-00010101000000-000000000000 github.com/charmbracelet/ssh v0.0.0-20240401141849-854cddfa2917 github.com/charmbracelet/wish v1.4.0 github.com/charmbracelet/x/term v0.2.0 @@ -25,7 +22,7 @@ require ( github.com/charmbracelet/bubbletea v0.25.0 // indirect github.com/charmbracelet/keygen v0.5.0 // indirect github.com/charmbracelet/log v0.4.0 // indirect - github.com/charmbracelet/x/ansi v0.3.2 // indirect + github.com/charmbracelet/x/ansi v0.4.2 // indirect github.com/charmbracelet/x/errors v0.0.0-20240117030013-d31dba354651 // indirect github.com/charmbracelet/x/exp/term v0.0.0-20240328150354-ab9afc214dfd // indirect github.com/charmbracelet/x/input v0.2.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index c611d60f..167a009c 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -7,10 +7,16 @@ github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241016204941-d95e2750ec12 h1:w1Dt/pl0gXE6PO2U+EUMoeMiSHe07/RR1Slcy9cH6kQ= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241016204941-d95e2750ec12/go.mod h1:8vhUTCIihfP3GfyyfznbOU7XyFe/ID1n7pdh/uT5Rug= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241031180054-a3bec0b7b8a8 h1:DQCVs696jYRcewAVwTkT/jJnE150/YrmTcCOvrz/J6U= +github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241031180054-a3bec0b7b8a8/go.mod h1:/w0ccIhyZqnVm+47JBkA/872fruM99gHxXTibc2kEMY= github.com/charmbracelet/colorprofile v0.1.2 h1:nuB1bd/yAExT4fkcZvpqtQ2N5/8cJHSRIKb6CzT7lAM= github.com/charmbracelet/colorprofile v0.1.2/go.mod h1:1htIKZYeI4TQs+OykPvpuBTUbUJxBYeSYBDIZuejMj0= +github.com/charmbracelet/colorprofile v0.1.6 h1:nMMqCns0c0DfCwNGdagBh6SxutFqkltSxxKk5S9kt+Y= +github.com/charmbracelet/colorprofile v0.1.6/go.mod h1:3EMXDxwRDJl0c17eJ1jX99MhtlP9OxE/9Qw0C5lvyUg= github.com/charmbracelet/keygen v0.5.0 h1:XY0fsoYiCSM9axkrU+2ziE6u6YjJulo/b9Dghnw6MZc= github.com/charmbracelet/keygen v0.5.0/go.mod h1:DfvCgLHxZ9rJxdK0DGw3C/LkV4SgdGbnliHcObV3L+8= +github.com/charmbracelet/lipgloss v0.13.1-0.20240822211938-b89f1a3db2a4 h1:BuZojjzjQ89wObGNVxJzFqyeh2S6Crbwhybb8bZNveI= +github.com/charmbracelet/lipgloss v0.13.1-0.20240822211938-b89f1a3db2a4/go.mod h1:ZbN5GVH/VrXHPRa1lZqZ1HWJyayJHJYaf9ywsCuI9zQ= github.com/charmbracelet/log v0.4.1-0.20241010222913-47ce960d4847 h1:3uto8OPDaseTS92giSw/8GfVQ+TCjcVE+QOaf8lT0Zc= github.com/charmbracelet/log v0.4.1-0.20241010222913-47ce960d4847/go.mod h1:3UCs04fasl8pA1HoNNJ8HCYCaKoeMBZrNXo9iy5F0vY= github.com/charmbracelet/ssh v0.0.0-20240401141849-854cddfa2917 h1:NZKjJ7d/pzk/AfcJYEzmF8M48JlIrrY00RR5JdDc3io= @@ -19,6 +25,8 @@ github.com/charmbracelet/wish v1.4.0 h1:pL1uVP/YuYgJheHEj98teZ/n6pMYnmlZq/fcHvom github.com/charmbracelet/wish v1.4.0/go.mod h1:ew4/MjJVfW/akEO9KmrQHQv1F7bQRGscRMrA+KtovTk= github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.4.2 h1:0JM6Aj/g/KC154/gOP4vfxun0ff6itogDYk41kof+qk= +github.com/charmbracelet/x/ansi v0.4.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/errors v0.0.0-20240117030013-d31dba354651 h1:3RXpZWGWTOeVXCTv0Dnzxdv/MhNUkBfEcbaTY0zrTQI= github.com/charmbracelet/x/errors v0.0.0-20240117030013-d31dba354651/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= diff --git a/examples/impure/bubbletea/main.go b/examples/impure/bubbletea/main.go new file mode 100644 index 00000000..f93b148a --- /dev/null +++ b/examples/impure/bubbletea/main.go @@ -0,0 +1,144 @@ +package main + +import ( + "fmt" + "os" + + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" + "github.com/charmbracelet/lipgloss/v2/impure" +) + +var ( + frameColor = impure.AdaptiveColor{Light: lipgloss.Color("#C5ADF9"), Dark: lipgloss.Color("#864EFF")} + textColor = impure.AdaptiveColor{Light: lipgloss.Color("#696969"), Dark: lipgloss.Color("#bdbdbd")} + keywordColor = impure.AdaptiveColor{Light: lipgloss.Color("#37CD96"), Dark: lipgloss.Color("#22C78A")} + inactiveBgColor = impure.AdaptiveColor{Light: lipgloss.Color(0x988F95), Dark: lipgloss.Color(0x978692)} + inactiveFgColor = impure.AdaptiveColor{Light: lipgloss.Color(0xFDFCE3), Dark: lipgloss.Color(0xFBFAE7)} +) + +// Style definitions. +type styles struct { + frame, + paragraph, + text, + keyword, + activeButton, + inactiveButton lipgloss.Style +} + +// Styles are initialized based on the background color of the terminal. +func newStyles() (s styles) { + // Define some styles. adaptive.Color() can be used to choose the + // appropriate light or dark color based on the detected background color. + s.frame = lipgloss.NewStyle(). + Border(lipgloss.RoundedBorder()). + BorderForeground(frameColor). + Padding(1, 3). + Margin(1, 3) + s.paragraph = lipgloss.NewStyle(). + Width(40). + MarginBottom(1). + Align(lipgloss.Center) + s.text = lipgloss.NewStyle(). + Foreground(textColor) + s.keyword = lipgloss.NewStyle(). + Foreground(keywordColor). + Bold(true) + + s.activeButton = lipgloss.NewStyle(). + Padding(0, 3). + Background(lipgloss.Color(0xFF6AD2)). // you can also use octal format for colors, i.e 0xff38ec. + Foreground(lipgloss.Color(0xFFFCC2)) + s.inactiveButton = s.activeButton. + Background(inactiveBgColor). + Foreground(inactiveFgColor) + return s +} + +type model struct { + styles styles + yes bool + chosen bool + aborted bool +} + +func (m model) Init() (tea.Model, tea.Cmd) { + m.yes = true + m.styles = newStyles() + return m, nil +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.KeyPressMsg: + switch msg.String() { + case "q", "esc", "ctrl+c": + m.aborted = true + return m, tea.Quit + case "enter": + m.chosen = true + return m, tea.Quit + case "left", "right", "h", "l": + m.yes = !m.yes + case "y": + m.yes = true + m.chosen = true + return m, tea.Quit + case "n": + m.yes = false + m.chosen = true + return m, tea.Quit + } + } + + return m, nil +} + +func (m model) View() string { + if m.chosen || m.aborted { + // We're about to exit, so wipe the UI. + return "" + } + + var ( + s = m.styles + y = "Yes" + n = "No" + ) + + if m.yes { + y = s.activeButton.Render(y) + n = s.inactiveButton.Render(n) + } else { + y = s.inactiveButton.Render(y) + n = s.activeButton.Render(n) + } + + return s.frame.Render( + lipgloss.JoinVertical(lipgloss.Center, + s.paragraph.Render( + s.text.Render("Are you sure you want to eat that ")+ + s.keyword.Render("moderatly ripe")+ + s.text.Render(" banana?"), + ), + y+" "+n, + ), + ) +} + +func main() { + m, err := tea.NewProgram(model{}).Run() + if err != nil { + fmt.Fprintf(os.Stderr, "Uh oh: %v", err) + os.Exit(1) + } + + if m := m.(model); m.chosen { + if m.yes { + fmt.Println("Are you sure? It's not ripe yet.") + } else { + fmt.Println("Well, alright. It was probably good, though.") + } + } +} diff --git a/examples/impure/standalone/main.go b/examples/impure/standalone/main.go new file mode 100644 index 00000000..6b385dc9 --- /dev/null +++ b/examples/impure/standalone/main.go @@ -0,0 +1,66 @@ +// This example illustrates how to detect the terminal's background color and +// choose either light or dark colors accordingly when using Lip Gloss in a. +// standalone fashion, i.e. independent of Bubble Tea. +// +// For an example of how to do this in a Bubble Tea program, see the +// 'bubbletea' example. +package main + +import ( + "github.com/charmbracelet/lipgloss/v2" + "github.com/charmbracelet/lipgloss/v2/impure" +) + +var ( + frameColor = impure.AdaptiveColor{Light: lipgloss.Color("#C5ADF9"), Dark: lipgloss.Color("#864EFF")} + textColor = impure.AdaptiveColor{Light: lipgloss.Color("#696969"), Dark: lipgloss.Color("#bdbdbd")} + keywordColor = impure.AdaptiveColor{Light: lipgloss.Color("#37CD96"), Dark: lipgloss.Color("#22C78A")} + inactiveBgColor = impure.AdaptiveColor{Light: lipgloss.Color(0x988F95), Dark: lipgloss.Color(0x978692)} + inactiveFgColor = impure.AdaptiveColor{Light: lipgloss.Color(0xFDFCE3), Dark: lipgloss.Color(0xFBFAE7)} +) + +func main() { + // Define some styles. adaptive.Color() can be used to choose the + // appropriate light or dark color based on the detected background color. + frameStyle := lipgloss.NewStyle(). + Border(lipgloss.RoundedBorder()). + BorderForeground(frameColor). + Padding(1, 3). + Margin(1, 3) + paragraphStyle := lipgloss.NewStyle(). + Width(40). + MarginBottom(1). + Align(lipgloss.Center) + textStyle := lipgloss.NewStyle(). + Foreground(textColor) + keywordStyle := lipgloss.NewStyle(). + Foreground(keywordColor). + Bold(true) + + activeButton := lipgloss.NewStyle(). + Padding(0, 3). + Background(lipgloss.Color(0xFF6AD2)). // you can also use octal format for colors, i.e 0xff38ec. + Foreground(lipgloss.Color(0xFFFCC2)) + inactiveButton := activeButton. + Background(inactiveBgColor). + Foreground(inactiveFgColor) + + // Build layout. + text := paragraphStyle.Render( + textStyle.Render("Are you sure you want to eat that ") + + keywordStyle.Render("moderatly ripe") + + textStyle.Render(" banana?"), + ) + buttons := activeButton.Render("Yes") + " " + inactiveButton.Render("No") + block := frameStyle.Render( + lipgloss.JoinVertical(lipgloss.Center, text, buttons), + ) + + // Print the block to stdout. It's important to use Lip Gloss's print + // functions to ensure that colors are downsampled correctly. If output + // isn't a TTY (i.e. we're logging to a file) colors will be stripped + // entirely. + // + // Note that in Bubble Tea downsampling happens automatically. + impure.Println(block) +}