Releases: charmbracelet/bubbletea
v1.3.3
This release restore the program options that were deprecated in the previous releases.
Changelog
Full Changelog: v1.3.2...v1.3.3
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.3.2
Fix canceling terminal input reads on Windows.
Changelog
Bug fixes
- b0186ad: fix: windows: handle cancel io error (@aymanbagabas)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.3.1
This release introduces some important bug fixes when it comes to cursor movements while rendering, and properly handle Windows AltGr key on non-English keyboards.
Changelog
Bug fixes
- 771a101: fix: renderer: use newline instead of cud1 to move cursor down (#1323) (@aymanbagabas)
- c66daf9: fix: windows: AltGr maps to LEFT_CTRL+RIGHT_ALT (#1162) (@aymanbagabas)
Other work
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.3.0
Sorry to interrupt: it's time for Bubble Tea v1.3.0!
Bubble Tea now ships with refined interrupt handling, courtesy @caarlos0. Now, you can throw your terminal a ctrl+c or an interrupt signal, Bubble Tea will take it with grace and poise. Switch any olโ run-of-the-mill tea.Quit
command with tea.Interrupt
for seamless interruptions.
Bug Fixes
- 2556e01: The last rendered line count now includes those sneaky alt screen lines, thanks to @semihbkgr's keen eye (#1254)
- c8d6005: Windows users rejoice! @awoodbeck has managed to cancel those unruly threads like an expert party planner using
CancelIoEx
(#1305)
New Contributors
Special thanks to the following new contributors:
- @awoodbeck, for totally fixing input on Windows
- @Bilogweb3, for help with the docs
- @simonnordberg, for catching some outdated typos
Changelog
New Features
Bug fixes
- 2556e01: fix: getting last rendered line counts including alt screen lines (#1254) (@semihbkgr)
- 31b433c: fix: replace deprecated ansi codes (@aymanbagabas)
- c8d6005: fix: use CancelIoEx to cancel Windows conInputReader across threads (#1305) (@awoodbeck)
Documentation updates
- 9306010: docs(example): resize chat example based on window (#1262) (@bashbunni)
- 2060f93: docs(examples): fix glamour example (#1204) (@meowgorithm)
- 07288b1: docs(readme): add more stuff to "In the Wild" (@meowgorithm)
- 1bf1886: docs(readme): additional readme tiyding up (@meowgorithm)
- 79cc2fb: docs(readme): fix tiny typo in readme (@meowgorithm)
- e0515bc: docs(readme): fix typos (#1265) (@Bilogweb3)
- 39f9fae: docs: clarify imports in the readme (#1234) (@caarlos0)
Other work
- eb7e3d0: Update README.md references to main branch (@simonnordberg)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.2.4
A few little rendering fixes
This release fixes a couple rendering bugs. Quality rendering in Bubble Tea is paramount!
Changelog
Bug fixes
- 4ad0792: fix: cursor position adjustment after exiting alt screen (#1241) (@semihbkgr)
- ede8caa: fix: renderer: keep a separate count of lines rendered in the alt screen (@aymanbagabas)
Other work
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.2.3
Altscreen-not-altscreen
This release fixes a sneaky longstanding bug in the renderer where mis-paints could happen when toggling in and out of the altscreen if the height of the TUI changed whilst in the altscreen. Special thanks to @applejag for reporting the issue and @semihbkgr for the fix.
Changelog
- f8f840c: fix: cursor position adjustment after exiting alt screen (#1241) (@semihbkgr)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v2.0.0-alpha.2
Are you excited about another alpha release?
We know we are! This release is chock full of features and improvements.
If youโre new to Bubble Tea v2 we recommending taking a look at the v2.0.0-alpha.1
release notes as well.
If you're already using v2.0.0-alpha.1
there's nothing new to do for v2.0.0-alpha.2
. You can blissfully ignore everything below and gleefully reap the benefitsโฆbut don't you want to know whatโs new?
Let's dive in!
๐ Packages
This release was designed to work with Bubble Tea, Bubbles, and Lip Gloss v2 alphas with the same tag, so make sure you catch โem all:
go get github.com/charmbracelet/bubbletea/v2@v2.0.0-alpha.2
go get github.com/charmbracelet/bubbles/v2@v2.0.0-alpha.2
go get github.com/charmbracelet/lipgloss/v2@v2.0.0-alpha.2
๐ฉ Better Windows Input Support
We take Windows support seriously, and with this release, we've revamped the
Windows input handling. Now, Bubble Tea works even better on Windows.
Bubble Tea now takes advantage of the Windows Console API to
get the terminal's size, focus events, and advanced keyboard and mouse
handling. This won't interfere with the existing escape sequence handling, so
you can still use the same code across different platforms.
๐ช Program-level Color Profiles and Styles
Bubble Tea now automatically downsamples ANSI, when necessary, for the appropriate output. For example, if you're setting 24-bit (TrueColor) colors in your application, and the user is using Apple Terminal, the colors will be automatically downsampled to the nearest colors in the 256 color spectrum. Or, if output's being directed to a file, colors will be stripped entirely.
Even better, this works with colors and styling generated by anything, not just Lip Gloss.
That means you can flow in ANSI styling from any tool or library and rest assured that colors
will just work with the user's terminal. This is all thanks to our new
magical colorprofile
library.
Detecting the color profile
Need to use the detected color profile in your app? Listen to tea.ColorProfileMsg
in Update
:
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.ColorProfileMsg:
m.colorProfile = msg.Profile // gottem!
}
return m, nil
}
Manually applying a color profile
What's that you say? You want to manually set a color profile for testing? Now you can, on the program level.
import (
"github.com/charmbraclelet/bubbletea/v2"
"github.com/charmbraclelet/colorprofile"
)
p := colorprofile.TrueColor // i love colors. lets' use 16,777,216 of 'em
p = colorprofile.ANSI256 // jk, 256 colors are plenty
p = colorprofile.ANSI // actually let's juse use 16 colors
p = colorprofile.Ascii // nm, no colors, but keep things like bold, italics, etc.
p = colorprofile.NoTTY // lol actually strip all ANSI sequences
prog := tea.Program(tea.WithColorProfile(p))
Want to hard detect the color profile in wish? We bet you do.
func main() {
var s ssh.Session
pty, _, _ := s.Pty()
// Get the environment...
envs := append(s.Environ(), "TERM="+pty.Term)
// ...and give it to Bubble Tea so it can detect the color profile.
opt := tea.WithEnvironment(envs)
p := tea.NewProgram(model,
tea.WithInput(pty.Slave),
tea.WithOutput(pty.Slave),
opt, // wow
)
}
Going deep
Hungry for more? This is for the more hard core terminal devs, like you.
๐ฎ An Acual Cursor
Another nice feature is the ability to use a real terminal
cursor. If you enable the cursor visibility, you can control the cursor
position and shape in your program.
func (m model) Init() (tea.Model, tea.Cmd) {
return m, tea.Batch(
tea.ShowCursor,
tea.SetCursorStyle(tea.CursorBlock, false), // non-blinking block cursor
tea.SetCursorStyle(tea.CursorUnderline, true), // blinking underline cursor
tea.SetCursorStyle(tea.CursorBar, true), // blinking vertical bar cursor
)
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q":
return m, tea.Quit
}
}
// move the cursor to the second row and first column of the program screen.
return m, tea.SetCursorPosition(0, 1)
}
func (m model) View() string {
return "Hey there!\n <- I'm a cursor!"
}
You can also request the cursor position by using the tea.RequestCursorPosition
command.
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
switch msg.String() {
case "enter":
return m, tea.RequestCursorPosition
case "q":
return m, tea.Quit
}
case tea.CursorPositionMsg:
m.cursorPosition.X, m.cursorPosition.Y = msg.X, msg.Y
}
return m, nil
}
Weโre still in the process of integrating true cursor support into textarea
and textinput
in Bubbles, however a true cursor is now at your disposal.
๐๏ธ Uniform Key Handling
One of the biggest changes coming to Bubble Tea v2 is enhanced keyboard
handling. This includes support for more key events, and complex key
combinations, as well as key releases.
When targeting users on different platforms and keyboard layouts, it's
important to have a consistent and reliable way to handle key events. With this
release, you can now use tea.WithUniformKeyLayout
keyboard enhancement to
ensure that your program works as expected across different keyboard layouts.
For example, on a multi-layout QWERTY keyboard, ctrl+a should always
trigger a ctrl+a
event, regardless of the layout language. Similarly,
shift+h should send a shift+h
event with the letter H
as its
printable value. But what happens when you press shift+h in a
different QWERTY layout?
Let's take the PC-101 QWERTY Arabic layout as an example. In this layout,
shift+h corresponds to the Arabic letter ุฃ
. If you're building a
game or an application that relies on key events where you don't really care
about the actual printable value of the key press, you'd want to ensure that
shift+h always sends a shift+h
event despite the layout language.
This will also respect the keyboard layout and send the correct printable
value for the key press. For example, on a US QWERTY keyboard, ctrl+a
corresponds to the first letter on the second row of the keyboard. On a French
AZERTY keyboard, the same key combinations correspond to ctrl+q.
To achieve this, you can use the tea.WithUniformKeyLayout
option and let Bubble
Tea handle the rest.
p := tea.NewProgram(model, tea.WithEnhancedKeyboard(
tea.WithKeyReleases, // Do we want to listen to key releases?
tea.WithUniformKeyLayout,
))
// Later in your program's Update function.
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
switch msg.String() {
case "ctrl+a":
// Handle ctrl+a event regardless of the keyboard layout.
case "shift+h":
// Handle shift+h event regardless of the keyboard layout and get the correct printable value.
}
}
return m, nil
}
๐ฌ Requesting Terminal Properties
With this release, we made it explicit how to request terminal properties. Use
the tea.Request...
commands to get the terminal's size, background color,
foreground color, etc.
// Before
func (m model) Init() (tea.Model, tea.Cmd) {
return m, tea.BackgroundColor
}
// After
func (m model) Init() (tea.Model, tea.Cmd) {
return m, tea.RequestBackgroundColor
}
The following Cmd
s are now at your disposal:
tea.RequestBackgroundColor
(sends atea.BackgroundColorMsg
)tea.RequestForegroundColor
(sends atea.ForgroundColorMsg
)tea.RequestCursorColor
(sends atea.CursorColorMsg
)tea.RequestWindowSize
(sends atea.WindowSizeMsg
)tea.RequestCursorPosition
(sends atea.CursorPostionMsg
)
๐ Grapheme Clustering
Grapheme what? In short, grapheme clustering is a way to handle Unicode text
segmentation and boundaries. It's useful when you want to determine the terminal
cell width a string or a grapheme cluster occupies. The algorithm is defined
in the Unicode Text Segmentation UAX #29.
For example, '๐งโ๐พ' is a single grapheme cluster, but it's made up of 3
UTF-8 codepoints. Terminals that support grapheme clustering will treat this as
a 2 cell wide character, while those that don't might treat it as 2, 4, 5, or
even 6 cells wide. Our friend Mitchell Hashimoto has a great blog post on this
topic: Grapheme Clusters and Terminal Emulators.
We've added grapheme clustering and mode 2027 support in the previous alpha.1
release, and it was on by default. We've noticed that some terminals, like
Apple Terminal, don't play well with this feature. Specifically, with the
DECRQM
control sequence. Not cool.
Now we're making the feature opt-in and off by default. You can still enable it by
using the tea.WithGraphemeClustering
option.
p := tea.NewProgram(model, tea.WithGraphemeClustering())
// Or in your program's Init function.
func (m model) In...
v1.2.2
Hi! This release fixes some bugs found the fast new renderer introduced in v1.2.0. Happy rendering!
Fixed
- Incorrect line skipping in renderer flush by @semihbkgr in #1233
- Erase the rest of the line when it's shorter than the width by @aymanbagabas in #1227
New Contributors
- @semihbkgr made their first contribution in #1233
Full Changelog: v1.2.0...v1.2.2
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.2.0
Itโs performance boost time
Sometimes you have to take matters into your own hands. Thatโs exactly what @LeperGnome did when he wanted faster rendering. This release features adjustments to the rendering algorithm for faster repaints. We encourage you to upgrade and give it a go!
Note
Renderer changes are no laughing matter. Weโve tested the new renderer extensively, however if you notice any bugs let us know. Rendering accuracy is among our top priorities.
Changelog
- rendering speed improvements by @LeperGnome in #1132
New Contributors
- @LeperGnome made their first contribution in #1132
Full Changelog: v1.1.2...v1.2.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v1.1.2
This and that
A tiny tiny release that fixes the tests on Windows, and uses the latest ansi
package definitions.
Changelog
New Features
- 12b04c5: feat(ci): use meta lint workflow (@aymanbagabas)
- 3209d62: feat(ci): use meta lint-sync workflow to sync linter config (@aymanbagabas)
Bug fixes
- 566879a: fix(ci): run lint workflow on all platforms (@aymanbagabas)
- cd1e4d3: fix: exec tests on windows (@aymanbagabas)
Documentation updates
- d928d8d: docs: update contributing guidelines (#1186) (@bashbunni)
- de4788d: docs: update readme badge images (@aymanbagabas)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.