A powerful little TUI framework 🏗

Overview

Bubble Tea

Bubble Tea Title Treatment
Latest Release GoDoc Build Status

The fun, functional and stateful way to build terminal apps. A Go framework based on The Elm Architecture. Bubble Tea is well-suited for simple and complex terminal applications, either inline, full-window, or a mix of both.

Bubble Tea Example

Bubble Tea is in use in production and includes a number of features and performance optimizations we’ve added along the way. Among those is a standard framerate-based renderer, a renderer for high-performance scrollable regions which works alongside the main renderer, and mouse support.

To get started, see the tutorial below, the examples, the docs and some common resources.

By the way

Be sure to check out Bubbles, a library of common UI components for Bubble Tea.

Bubbles Badge   Text Input Example from Bubbles


Tutorial

Bubble Tea is based on the functional design paradigms of The Elm Architecture which happens work nicely with Go. It's a delightful way to build applications.

By the way, the non-annotated source code for this program is available on GitHub.

This tutorial assumes you have a working knowledge of Go.

Enough! Let's get to it.

For this tutorial we're making a to-do list.

To start we'll define our package and import some libraries. Our only external import will be the Bubble Tea library, which we'll call tea for short.

package main

import (
    "fmt"
    "os"

    tea "github.com/charmbracelet/bubbletea"
)

Bubble Tea programs are comprised of a model that describes the application state and three simple methods on that model:

  • Init, a function that returns an initial command for the application to run.
  • Update, a function that handles incoming events and updates the model accordingly.
  • View, a function that renders the UI based on the data in the model.

The Model

So let's start by defining our model which will store our application's state. It can be any type, but a struct usually makes the most sense.

type model struct {
    choices  []string           // items on the to-do list
    cursor   int                // which to-do list item our cursor is pointing at
    selected map[int]struct{}   // which to-do items are selected
}

Initialization

Next we'll define our application’s initial state. We’ll store our initial model in a simple variable, and then define the Init method. Init can return a Cmd that could perform some initial I/O. For now, we don't need to do any I/O, so for the command we'll just return nil, which translates to "no command."

var initialModel = model{
    // Our to-do list is just a grocery list
    choices:  []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},

    // A map which indicates which choices are selected. We're using
    // the  map like a mathematical set. The keys refer to the indexes
    // of the `choices` slice, above.
    selected: make(map[int]struct{}),
}

func (m model) Init() tea.Cmd {
    // Just return `nil`, which means "no I/O right now, please."
    return nil
}

The Update Method

Next we'll define the update method. The update function is called when "things happen." Its job is to look at what has happened and return an updated model in response to whatever happened. It can also return a Cmd and make more things happen, but for now don't worry about that part.

In our case, when a user presses the down arrow, update's job is to notice that the down arrow was pressed and move the cursor accordingly (or not).

The "something happened" comes in the form of a Msg, which can be any type. Messages are the result of some I/O that took place, such as a keypress, timer tick, or a response from a server.

We usually figure out which type of Msg we received with a type switch, but you could also use a type assertion.

For now, we'll just deal with tea.KeyMsg messages, which are automatically sent to the update function when keys are pressed.

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {

    // Is it a key press?
    case tea.KeyMsg:

        // Cool, what was the actual key pressed?
        switch msg.String() {

        // These keys should exit the program.
        case "ctrl+c", "q":
            return m, tea.Quit

        // The "up" and "k" keys move the cursor up
        case "up", "k":
            if m.cursor > 0 {
                m.cursor--
            }

        // The "down" and "j" keys move the cursor down
        case "down", "j":
            if m.cursor < len(m.choices)-1 {
                m.cursor++
            }

        // The "enter" key and the spacebar (a literal space) toggle
        // the selected state for the item that the cursor is pointing at.
        case "enter", " ":
            _, ok := m.selected[m.cursor]
            if ok {
                delete(m.selected, m.cursor)
            } else {
                m.selected[m.cursor] = struct{}{}
            }
        }
    }

    // Return the updated model to the Bubble Tea runtime for processing.
    // Note that we're not returning a command.
    return m, nil
}

You may have noticed that "ctrl+c" and "q" above return a tea.Quit command with the model. That's a special command which instructs the Bubble Tea runtime to quit, exiting the program.

The View Method

At last, it's time to render our UI. Of all the methods, the view is the simplest. We look at the model in it's current state and use it to return a string. That string is our UI!

Because the view describes the entire UI of your application, you don't have to worry about redraw logic and stuff like that. Bubble Tea takes care of it for you.

func (m model) View() string {
    // The header
    s := "What should we buy at the market?\n\n"

    // Iterate over our choices
    for i, choice := range m.choices {

        // Is the cursor pointing at this choice?
        cursor := " " // no cursor
        if m.cursor == i {
            cursor = ">" // cursor!
        }

        // Is this choice selected?
        checked := " " // not selected
        if _, ok := m.selected[i]; ok {
            checked = "x" // selected!
        }

        // Render the row
        s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
    }

    // The footer
    s += "\nPress q to quit.\n"

    // Send the UI for rendering
    return s
}

All Together Now

The last step is to simply run our program. We pass our initial model to tea.NewProgram and let it rip:

func main() {
    p := tea.NewProgram(initialModel)
    if err := p.Start(); err != nil {
        fmt.Printf("Alas, there's been an error: %v", err)
        os.Exit(1)
    }
}

What's Next?

This tutorial covers the basics of building an interactive terminal UI, but in the real world you'll also need to perform I/O. To learn about that have a look at the Command Tutorial. It's pretty simple.

There are also several Bubble Tea examples available and, of course, there are Go Docs.

Libraries we use with Bubble Tea

  • Bubbles: Common Bubble Tea components such as text inputs, viewports, spinners and so on
  • Lip Gloss: Style, format and layout tools for terminal applications. Built on Termenv and Reflow below
  • Termenv: Advanced ANSI styling for terminal applications
  • Reflow: Advanced ANSI-aware methods for working with text

Bubble Tea in the Wild

For some Bubble Tea programs in production, see:

  • Glow: a markdown reader, browser and online markdown stash
  • The Charm Tool: the Charm user account manager
  • kboard: a typing game
  • tasktimer: a dead-simple task timer
  • fork-cleaner: cleans up old and inactive forks in your GitHub account
  • STTG: teletext client for SVT, Sweden’s national public television station
  • gitflow-toolkit: a GitFlow submission tool
  • ticker: a terminal stock watcher and stock position tracker
  • tz: an aid for scheduling across multiple time zones
  • httpit: a rapid http(s) benchmark tool
  • gembro: a Gemini browser

Feedback

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

Acknowledgments

Bubble Tea is based on the paradigms of The Elm Architecture by Evan Czaplicki et alia and the excellent go-tea by TJ Holowaychuk.

License

MIT


Part of Charm.

The Charm logo

Charm热爱开源! / Charm loves open source!

You might also like...
TUI Flappy Bird. It‘s a lil bit jank tbh

EBIRD TUI Flappy Bird. It's a lil bit jank tbh. Build and Install Build dependen

Tabouli: a TUI for interacting with firmware/embedded devices that support a CLI via serial interface/virtual COM Port
Tabouli: a TUI for interacting with firmware/embedded devices that support a CLI via serial interface/virtual COM Port

Tabouli Information Tabouli is a TUI for interacting with firmware/embedded devi

A TUI implementation of the popular word quiz wordle!

gordle A TUI implementation of the popular word quiz Wordle! Building Build the cli command: $ go build ./cmd/cli Empty output on build success Buil

Podman-tui - A Terminal User Interface to interact with the podman (v3.x)
Podman-tui - A Terminal User Interface to interact with the podman (v3.x)

podman-tui podman-tui is a Terminal User Interface to interact with the podman (

The Cloud Aviator: TUI client for cloud services (AWS, Vultr, Heroku, Render.com, ...)
The Cloud Aviator: TUI client for cloud services (AWS, Vultr, Heroku, Render.com, ...)

=== T H E C L O U D A V I A T O R === ⠀⠀⠀⠀⠀⠀⠀⠀⢶⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

Handy little CLI for interacting with OCI data

oci-tool Handy little CLI for interacting with OCI data Installation go get github.com/csweichel/oci-tool I use Gitpod for developing this tool; you s

Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst

Go-Suit Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst languages - Go-Lang packages Third Party - g

Little golang app that allows you to download a youtube video as mp3, and optionally embed ID3 tags -Cover Art, Artist ...-

yt2mp3 Little golang app that allows you to download a youtube video as mp3, and optionally embed ID3 tags -Cover Art, Artist ...- Instructions At the

Flag is a simple but powerful command line option parsing library for Go support infinite level subcommand

Flag Flag is a simple but powerful commandline flag parsing library for Go. Documentation Documentation can be found at Godoc Supported features bool

Comments
  • feat(deps): bump github.com/mattn/go-isatty from 0.0.16 to 0.0.17

    feat(deps): bump github.com/mattn/go-isatty from 0.0.16 to 0.0.17

    Bumps github.com/mattn/go-isatty from 0.0.16 to 0.0.17.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
  • Can't redirect output of non-interactive application

    Can't redirect output of non-interactive application

    I use bubbletea for the sole purpose of generating and printing a table in my application. So no interactive features there (until now!). I expected, that I could perform a benchmark-measurement with hyperfine, however it seems like execution is blocked in this case, because hyperfine redirects stdout and stderr.

    Sure enough, if I redirect the output of my program to > /dev/null, then my program never exits.

    Is this something I can solve by writing my application in a different way? Is this a bug with bubbletea?

    opened by tim-hilt 2
  • could not decode rune

    could not decode rune

    i am using the mouse input and always getting a program exit after a while because of "could not decode rune"

    I would expect it continues instead of failing on a invalid utf 8 rune.

    		r, width := utf8.DecodeRune(b[i:])
    		if r == utf8.RuneError {
    			return nil, errors.New("could not decode rune")
    		}
    
    opened by mschneider82 0
  • bug: loss of input on ReleaseTerminal / Bubbletea shutdown

    bug: loss of input on ReleaseTerminal / Bubbletea shutdown

    It is not currently possible to integrate Bubbletea-based programs in scripts or unit tests that buffer terminal input across multiple runs of the Bubbletea event loop.

    The specifics are explained here: https://dr-knz.net/bubbletea-control-inversion.html

    In summary, the input reader function is "greedy" but drops/forgets input event messages during ReleaseTerminal(). This is where the input is lost.

    The text linked above outlines a solution:

    • [ ] invert control of the input reader function, i.e. this PR: https://github.com/charmbracelet/bubbletea/pull/569
    • [ ] synchronise the reading from the external input with Update calls.
    • [ ] for the benefit of programs (like Bubbline) that need to share control of the terminal, introduce a new API to suspend the Bubbletea event loop.
    opened by knz 1
Releases(v0.23.1)
  • v0.23.1(Nov 15, 2022)

    This bugfix release addresses an issue that was introduced by v0.23.0 and prevented programs from re-using stdin after a tea.Program had finished execution.


    Changelog

    Fixed!

    • Don't close stdin by @muesli in https://github.com/charmbracelet/bubbletea/pull/598

    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.23.0(Nov 9, 2022)

    If you are closely following Bubble Tea's development, you may have already noticed that we have been really busy fixing a lot of issues and merged more than just a couple of feature requests in recent weeks. This v0.23.0 release is in fact our biggest update since the initial release of the package: in the last 3 months over 100 commits have reached us by more than 30 individual contributors! Thank you everyone! 💕

    Here's a quick overview of what has changed:

    Custom Outputs

    Don't want to render your beautiful TUI to stdout? A buffer or an alternative file descriptor like stderr seems more appropriate? We got you covered now:

    Render to stderr

    p := tea.NewProgram(model, tea.WithOutput(os.Stderr))
    

    Render to a Buffer

    var buf bytes.Buffer
    p := tea.NewProgram(model, tea.WithOutput(&buf))
    

    Run Like the Wind

    We've introduced the aptly named method Program.Run which replaces and deprecates the existing Program.Start and Program.StartReturningModel methods. This unifies and clarifies the blocking behavior of the Bubble Tea program execution.

    The old methods will continue to work for now, but please update your programs accordingly:

    p := tea.NewProgram(model, tea.WithOutput(os.Stderr))
    model, err := p.Run() // instead of p.Start or p.StartReturningModel
    ...
    

    Bug Fix Galore!

    The initialization and tear-down methods of tea.Program have been revised and some long-standing problems have been resolved. We couldn't list every single fix in the release notes, so please check out the full changelog below!

    🤗 Thanks

    We would like to particularly thank @knz who is the sole author of more than a dozen PRs since the last release. Outstanding work!


    Changelog

    New

    • Render to custom outputs, io.Writers and buffers (tea.WithOutput)
    • Support for new keys: Ctrl(+Alt) - Page, Home, End, and Insert keys
    • Signal handler is optional with program option tea.WithoutSignalHandler
    • tea.ClearScreen, tea.ShowCursor commands
    • Exported BatchMsg

    Fixed!

    • Race conditions in console renderer
    • Issues restoring terminal state on shutdown
    • Kill not resulting in an error returned by Program.Run
    • Repaint behavior
    • Skip over unrecognized CSI sequences
    • Function keys on urxvt
    • Function keys on Linux console
    • Rendering issues with overflowing output buffers
    • Ensure final render on clean shutdown
    • Cursor visibility on altscreen state switch
    • Deadlock in Program.Send on shutdown

    Deprecated

    • Program.Start, Program.StartReturningModel: please use Program.Run

    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.22.1(Aug 19, 2022)

    Mutli-Byte Character Support on Windows

    This is a small release with a big impact for Chinese, Japanese, and Korean users on Windows. The long as short of it is that if you’re using a multi-byte character set that’s not UTF-8, Bubble Tea will covert stuff for you so things work as expected. For details see https://github.com/charmbracelet/bubbletea/pull/343.

    🤗 Enormous thanks to @mattn for the contribution as well as his Go libraries that make CJK support in the Charm ecosystem possible.

    👾 Also, thanks to @aklyachkin, if Bubble Tea on AIX is something you want your dream is a now a reality.

    Changelog

    • support multi-byte strings on Windows by @mattn in https://github.com/charmbracelet/bubbletea/pull/343
    • enable compilation on AIX by @aklyachkin in https://github.com/charmbracelet/bubbletea/pull/381

    Full Changelog: https://github.com/charmbracelet/bubbletea/compare/v0.22.0...v0.22.1


    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.22.0(Jun 27, 2022)

    Unmanaged Output

    Now you can print unmanaged output above your inline applications. This means you can print stuff above your app that won't be cleared on the next render. It’s super useful for cases where you want to build an apt-like package manager.

    Let’s Print

    This release introduces two new Cmds that print output above your inline Bubble Tea program:

    tea.Println("Hello, Bubble Tea")
    tea.Printf("%s, %s", "Hello", "Bubble Tea")
    

    Use it anytime you want to add log-type info to the terminal’s scrollback buffer, such as building your own package manager 📦. And keep in mind that these methods are no-op’s in altscreen mode.

    Package Manager Demo

    For details see the full example and the docs.

    🤗 Thanks

    @fiws has been bugging us to implement this forever and then @Adjective-Object swooped in and did it with style and grace! It’s been a great collaboration all around.


    Changelog

    New

    • Credit card input form example by @maaslalani in https://github.com/charmbracelet/bubbletea/pull/338
    • Allow unmanaged output above the app in standard renderer by @Adjective-Object in https://github.com/charmbracelet/bubbletea/pull/249

    Fixed!

    • Race condition on repaint by @georgijd in https://github.com/charmbracelet/bubbletea/pull/330
    • Handle batched key msgs by @muesli in https://github.com/charmbracelet/bubbletea/pull/326

    New Contributors

    • @georgijd made their first contribution in https://github.com/charmbracelet/bubbletea/pull/330
    • @joaom00 made their first contribution in https://github.com/charmbracelet/bubbletea/pull/313
    • @maaslalani made their first contribution in https://github.com/charmbracelet/bubbletea/pull/338
    • @Adjective-Object made their first contribution in https://github.com/charmbracelet/bubbletea/pull/249

    Full Changelog: https://github.com/charmbracelet/bubbletea/compare/v0.21.0...v0.22.0


    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.21.0(Jun 2, 2022)

    Spawn Interactive Processes + More Keybindings

    Finally! This update allows you to run blocking, interactive processes from Bubble Tea like vim, htop, curl, and even entire shells like fish. It also adds a bunch of new keybindings. Read on for more!

    Let’s Exec

    As we were saying, you can now spawn interactive processes in the terminal from Bubble Tea and resume Bubble Tea when they exit. For example, you could have your Bubble Tea program spawn vim to edit a file, or temporarily open a shell, like fish. Here’s what it looks like:

    type editorFinishedMsg struct{ err error }
    
    func openInVim(path string) tea.Cmd {
    	c := exec.Command("vim", path)
    	return tea.ExecProcess(c, func(err error) tea.Msg {
    		return editorFinishedMsg{err}
    	})
    }
    

    See the full example for details.

    Keys Galore

    Prior to this update, you couldn't bind to the functions keys. Isn't that crazy? @mrusme certainly thought so. With this update you can can now respond to F1 through F20, modifiers included.

    And thanks to @bwahharharrr you can also now bind to arrow keys with the ctrl, shift and alt modifiers.


    High-Level Changelog

    New

    • move cancelreader into a separate package by @muesli in https://github.com/charmbracelet/bubbletea/pull/222
    • Exec, program.ReleaseTerminal and RestoreTerminal to re-use input and terminal by @muesli in https://github.com/charmbracelet/bubbletea/pull/237
    • add support for shift/ctrl + arrow keys by @meowgorithm in https://github.com/charmbracelet/bubbletea/pull/292
    • add function key support by @meowgorithm in https://github.com/charmbracelet/bubbletea/pull/263

    Changed

    • spacebar now sends a KeySpace by @bashbunni in https://github.com/charmbracelet/bubbletea/pull/289 and https://github.com/charmbracelet/bubbletea/pull/315
    • Program#Send, Program#Quit, and Program#Kill no longer provisional by @meowgorithm in https://github.com/charmbracelet/bubbletea/pull/271

    New Contributors

    • @r-darwish made their first contribution in https://github.com/charmbracelet/bubbletea/pull/225
    • @wolves made their first contribution in https://github.com/charmbracelet/bubbletea/pull/250
    • @imranZERO made their first contribution in https://github.com/charmbracelet/bubbletea/pull/254
    • @iamjaredwalters made their first contribution in https://github.com/charmbracelet/bubbletea/pull/279
    • @bashbunni made their first contribution in https://github.com/charmbracelet/bubbletea/pull/289

    Full Changelog: https://github.com/charmbracelet/bubbletea/compare/v0.20.0...v0.21.0


    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.20.0(Feb 15, 2022)

    Force Kill, Bugfixes, and Small Improvements

    This is mostly a bugfix release, but there’s also a new feature where you can quit a Bubble Tea program immediately, skipping the final render, but still restoring the terminal state:

    p := tea.NewProgram(model{})
    
    go func() {
        if err := p.Start(); err != nil {
            fmt.Println("Oh no:", err)
            os.Exit(1)
        }
    }()
    
    // Later
    p.Kill()
    

    This can be useful in when to you need fine-grained management over a Bubble Tea program when using something like Wish. Special thanks to @aymanbagabas for implementing this swiftly and acutely.

    New

    • Added Kill() method to force quit the program and restore terminal state https://github.com/charmbracelet/bubbletea/pull/219
    • Support batched mouse events https://github.com/charmbracelet/bubbletea/pull/215 (see https://github.com/charmbracelet/bubbletea/issues/212 for details)

    Fixed

    • Allocate msgs channel in constructor to fix a data race (thanks @paralin!) https://github.com/charmbracelet/bubbletea/pull/180
    • Handle nil cmds in tea.Sequentially (thanks @ajeetdsouza!) https://github.com/charmbracelet/bubbletea/pull/214
    • tea.Batch now returns nil if all cmds are nil https://github.com/charmbracelet/bubbletea/pull/217
    • Don't check terminal size if output is not a terminal https://github.com/charmbracelet/bubbletea/pull/228

    New Contributors

    • @mamachanko made their first contribution in https://github.com/charmbracelet/bubbletea/pull/178
    • @paralin made their first contribution in https://github.com/charmbracelet/bubbletea/pull/180
    • @dependabot made their first contribution in https://github.com/charmbracelet/bubbletea/pull/203
    • @ajeetdsouza made their first contribution in https://github.com/charmbracelet/bubbletea/pull/214

    Full Changelog: https://github.com/charmbracelet/bubbletea/compare/v0.19.3...v0.20.0


    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.19.3(Jan 7, 2022)

    Altscreen Repaints

    This release fixes a small bug where views would render blank if the view’s return value didn’t change after toggling the altscreen.

    🤗 Special thanks to @chris-miner for flagging this one.


    The Charm logo

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

    Source code(tar.gz)
    Source code(zip)
  • v0.19.2(Dec 17, 2021)

    It’s all about BSD

    This release restores support for Dragonfly BSD and fixes a bug where general BSD builds would fail with Go 1.17. BSD users, let us know if you notice anything else is awry.


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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.19.1(Nov 5, 2021)

  • v0.19.0(Oct 30, 2021)

    Final Model Access

    This release features Program.StartReturningModel, a handy alternative start method for returning the final Model after a Program exits. This makes it easy to access data collected in a Bubble Tea program while still working in an immutable fashion.

    Here’s an example illustrating how it works:

    type MyModel struct {
    	Name         string
    	FaveCatColor string
    }
    
    p := tea.NewProgram(MyModel{})
    
    // Return the final model when we're done
    finalModel, err := p.StartReturningModel()
    if err != nil {
    	fmt.Println("Uh oh", err)
    	os.Exit(1)
    }
    
    // The final model is a generalized tea.Model, so be sure to assert it into
    // your actual model type.
    if m, ok := finalModel.(MyModel); ok {
    	fmt.Printf("Hello, %s. I have a %s kitty for you.\n", m.Name, m.FaveCatColor)
    }
    

    🤗 A big thanks to @Raphexion for both conceptualizing and executing this feature.

    ANSI Compression, Now Opt-In

    We’ve also made the ANSI compressor opt-in by default as we noticed that it was incurring a larger performance hit than we’d like in some cases. To enable the ANSI compressor just use the WithANSICompressor program option:

    tea.NewProgram(model, tea.WithANSICompressor())
    

    Changelog

    Here’s the full changelog for this release.


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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.18.0(Oct 28, 2021)

    Hello, ANSI compressor!

    The big news in this release is the integration of @muesli’s ANSI compressor from his new ANSI package. The compressor, which has been integrated into the renderer, automatically removes redundant ANSI sequences and, as such, it can be considered lossless. This should improve rendering speeds both locally and over the wire.

    Other stuff

    When quitting a Bubble Tea program from the outside you previously had to…

    p.Send(tea.Quit())
    

    …which works, but also feels a little silly. So now you can just…

    p.Quit()
    

    Here’s the full changelog.


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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.17.0(Oct 3, 2021)

    Windows Stuff

    This release adds mouse support in Windows! It also fixes a regression introduced in v0.16.0 where the arrow keys didn't work on Windows.

    As a side effect to the above, cancelable reads have been disabled in Windows for now. This means applications running in Windows can not run multiple Programs in succession in the context of a single application, nor can user input be reliably read after a Program has exited until the Go application exits. This is temporary and a solution is in development.

    Changelog

    New

    • Mouse support in Windows

    Fixed

    • Arrow keys work properly in Windows again

    Changed

    • Input will no longer reliably close on Windows after exiting a Bubble Tea program as it did in v0.16.0. This will be addressed in a subsequent release.

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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.16.0(Sep 28, 2021)

    Cancelable Reads

    This release implements a cancelable input reader which allows user input to be read after a Program has exited. This means that you can now run multiple Programs in succession in a single application as well as generally read user input in other after a Program has exited in the context of a single application.

    In addition, all Goroutines are now gracefully terminated before Program.Start() returns, resulting in reliable behavior between subsequent Programs.

    This update has been a major undertaking by @erikgeiser, who built specific implementations for Linux, BSD/macOS, and Windows as well as a general purpose implementation for other flavors of unix.


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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.15.0(Sep 8, 2021)

    Interop and Inputs

    The big, new feature in this update is Program.Send(Msg), which allows you to send messages to the Update loop from outside a Bubble Tea program. This simplifies Bubble Tea’s interoperability with other libraries quite a lot and we’re excited to see what you do with it.

    Beyond that, we’ve made a lot of small changes under the hood to allow Bubble Tea to work better with more types of terminal input such as PTYs over SSH. The program option WithInputTTY has also been added to make it easier to open a TTY (or console input device on Windows) on demand.

    Changelog

    New

    • Msgs can now be sent to Programs with Program.Send(Msg)
    • WithInputTTY is a new ProgramOption for explicitly opening a new TTY (or console on Windows) for input

    Fixed

    • Fixed a send on closed channel panic that could happen during a shutdown when messages are being sent super fast
    • The cursor will now always hide/show itself during startup/shutdown, regardless of whether input is a terminal
    • Input will now attempt to be read regardless of whether input is a terminal

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

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.14.1(Jun 22, 2021)

  • v0.14.0(Jun 2, 2021)

    Improvements: Races and Rendering

    This release introduces three new ProgramOptions for starting programs with the altscreen and mouse enabled. This was implemented to solve both race conditions when initializing programs as well as correctness with regard to custom inputs.

    // New! This is the recommended way to start your program with the mouse and altscreen active.
    p := tea.NewProgram(model, tea.WithAltScreen(), tea.WithMouseAllMotion())
    
    // Deprecated as this will only operate on stdout, as opposed to a custom output you may have set.
    p := tea.NewProgram(model)
    p.EnableAltScreen()
    p.EnableMouseAllMotion()
    
    // Strongly discouraged as these commands could be sent before starting the renderer, resulting
    // in rendering artifacts. This is due to the fact that commands run asynchronously in a goroutine.
    func (m model) Init() tea.Cmd {
        return tea.Batch(tea.EnterAltScreen, tea.EnableMouseAllMotion)
    }
    

    Also included are two subtle—yet important—rendering improvements.

    Changelog

    New

    • Added ProgramOption WithAltScreen for starting programs in the alternate screen buffer.
    • Added ProgramOptions WithMouseCellMotion and WithMouseAllMotion for starting programs with the mouse enabled.

    Fixed

    • Programs will no longer render artifacts when exiting due to an error or panic.
    • If a view returns the empty string output will be cleared. Previously, rendering would be skipped entirely.

    Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or right here in GitHub Discussions.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.13.4(May 15, 2021)

  • v0.13.3(May 10, 2021)

    Faster Rendering

    This release introduces a performance optimization to the Bubble Tea standard renderer where only lines that have changed since the last render will be drawn.

    Note that there's already an optimization in place that will skip rendering entirely if nothing has changed.


    Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or right here in GitHub Discussions.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.13.2(Apr 8, 2021)

    This bugfix release ensures Bubble Tea clears the bottom line before exiting, preventing the cursor the last row of output from potentially appearing behind the prompt. It also fixes a data race in the default renderer and improves compatibility with rxvt-based terminals.


    Thoughts? Questions? Feel free to reach out on Twitter and The Fediverse.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.13.1(Mar 13, 2021)

  • v0.13.0(Mar 11, 2021)

    This release adds two new features as well as a few other small-ish improvements.

    New: Headless Mode

    WithoutRenderer is a new program option that, when set, will tell Bubble Tea not to manage rendering. With the renderer disabled print and log statements will, by default, go straight to standard output. This opens up a few possibilities:

    • Daemon Mode: It's now possible for your Bubble Tea program to also operate as a daemon in addition to a TUI. See the daemon-tui-combo example for an example implementation.
    • Non-TTY Mode: If output’s not a TTY your Bubble Tea program can simply print or log output to stdout. See the daemon-tui-combo example for an example implementation.
    • General Purpose Application Development: It's possible to use the Bubble Tea framework for general purpose application development. That is to say, your can take advantage of this implementation of The Elm Architecture to build other types of applications, like servers, GUIs and so on.
    Bubble Tea demo of an application switching between TUI and daemon modes

    New: Toggle the Alt Screen

    Previously, you had to choose whether your application would be inline or fullscreen prior to starting your Bubble Tea program. Now you can jump in and out of the altscreen with the new EnterAltScreen and ExitAltScreen commands.

    Bubble Tea demo of an application switching between inline and altscreen modes

    Changelog

    New

    • Added option WithoutRenderer for disabling the Bubble Tea renderer in non-TTY, daemon and general-purpose application development contexts (details)
    • New EnterAltScreen and ExitAltScreen commands for jumping into and out of the alternate screen buffer (read: full window mode)
    • Bubble Tea will not automatically exit the alternate screen buffer on quit

    Changed

    • Type Key now satisfies the Stringer interface (KeyMsg already did)(https://pkg.go.dev/github.com/charmbracelet/[email protected]#KeyType)
    • Program option WithOutput now takes an io.Writer instead of an *os.File

    Fixed

    • All key constants (such as KeyEnter) are now of type [KeyType]

    Thoughts? Questions? Feel free to reach out on Twitter and The Fediverse.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.12.5(Mar 1, 2021)

    This big news in this release is that Bubble Tea will now automatically open a TTY for input (or a ConPTY on Windows) if input is not a terminal. In other words, if you pipe something into Bubble Tea, the keyboard and mouse will just work. Note that if you’re already specifying a custom input via tea.WithInput the Bubble Tea runtime will assume you have things under control and won't open a TTY/ConPTY.

    Example of Bubble Tea working with piped input

    New

    • If input is not a TTY, automatically open a TTY unless the user has explicitly specified a custom input

    Fixed

    • Bubble Tea projects now build properly in Go 1.16. Previously building Bubble Tea on Go 1.16 meant running go mod tidy.

    Thoughts? Questions? Feel free to reach out on Twitter and The Fediverse.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.12.4(Jan 18, 2021)

    This mini-release adds the tea.Sequentially helper command, which is useful for executing several commands in order. For example, maybe you want to save and quit, but only if the save was successful:

    func saveStateCmd() Msg {
    	if err := save(); err != nil {
     		return errMsg{err}
     	}
    	return nil
    }
    
    cmd := Sequentially(saveStateCmd, Quit)
    

    For details, see the docs.


    Thoughts? Questions? Feel free to reach out on Twitter and The Fediverse.

    The Charm logo

    Source code(tar.gz)
    Source code(zip)
  • v0.12.3(Jan 15, 2021)

    This release contains some small but powerful improvements to make Bubble Tea more flexible and more foolproof.

    Improved Rendering

    Lines wider than the window width are now automatically trimmed to prevent line wrapping which previously messed up rendering a little. Note that this is for unix systems only: Windows is not able to determine terminal width, so Bubble Tea wouldn't know where to truncate lines.

    Do note that for more precise control you can also truncate long lines yourself. We recommend the truncate package in @muesli’s excellent Reflow project which Bubble Tea is using internally to trim lines.

    Custom Input and Output

    Input and output can now be set to any valid io.Reader and io.Writer (by default they're os.Stdin and os.Stdout, respectively). Additionally, if input’s not a TTY the runtime will simply stop listening for input (previously, Bubble Tea would exit with error).

    SIGINT

    Bubble Tea now exits gracefully when it receives a SIGINT. In most casts ctrl-c still won’t send an interrupt because those keys are sent through to Bubble Tea so you can map them as you'd like. If input’s not a TTY, however, ctrl-c will generally send an in interrupt and Bubble Tea will restore the terminal and quit.


    Thoughts? Questions? Feel free to reach out on Twitter and The Fediverse.

    Source code(tar.gz)
    Source code(zip)
  • v0.12.2(Nov 2, 2020)

    This release adds support for multi-character input, most notably Chinese and Japanese IME. Adding this support required some API changes:

    • Key.Rune is now Key.Runes
    • Type KeyRune is now KeyRunes
    • Key.IsRune() was removed. To determine if input is a string (or []rune) use Key.Type == KeyRunes
    Source code(tar.gz)
    Source code(zip)
  • v0.12.1(Oct 22, 2020)

Owner
Charm
We build tools to make the command line glamorous
Charm
TUI process monitor written in Go

pst This is TUI process monitor written in Go. Features Monitor process's list, info, tree, open files, Kill process Support OS Mac Linux Requirements

skanehira 330 Nov 25, 2022
A CLI / TUI for Microsoft Teams

teams-cli A Command Line Interface (or TUI) to interact with Microsoft Teams Status The CLI only let you log-in and fetches your user and conversation

null 207 Dec 22, 2022
a TUI for signal messenger, written in Go

siggo A terminal ui for signal-cli, written in Go. Features vim-style ux useful for quick messages or use $EDITOR to compose fancy ones emoji support,

Derric Williams 315 Jan 2, 2023
Canard. A command line TUI client for the journalist RSS aggregator.

Canard Canard. A command line TUI client for the Journalist RSS aggregator. Installation Download a binary from the releases page. Or build it yoursel

マリウス 105 Jan 6, 2023
🧭 TUI for command navigation

devgo a command-line launcher Install latest version curl -o- https://raw.githubusercontent.com/TheWinds/devgo/main/install.sh | bash special version

风影. 14 Apr 19, 2022
A terminal UI (TUI) for HashiCorp Nomad

Damon - A terminal Dashboard for HashiCorp Nomad Damon is a terminal user interface (TUI) for Nomad. It provides functionality to observe and interact

HashiCorp 302 Jan 6, 2023
A TUI multitool for day-to-day operations for software applications.

Bench (WIP) A TUI multitool for day-to-day operations for software applications. Lets you do common operations needed during IT work that are common e

null 1 Dec 5, 2021
🦜 Navigate github repos in a tui

goh Navigate github repos in a tui Why I am constantly refering to my github repos and repos from others for code snippets that are relevant to what I

Taylor Gamache 11 Dec 10, 2021
A tui for playing media from a caddy fileserver

kwatch a little tui interface to play media from a caddy fileserver. options: -a: server address -u: server http username -p: server http password -o:

Rylee 6 Aug 9, 2022
Light weight Terminal User Interface (TUI) to pick material colors written by Go.

mcpick Light weight Terminal User Interface (TUI) to pick material colors. You do NOT need to take your hands off the keyboard to pick colors. Getting

tenkoh 6 Dec 27, 2022