okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
7bfbaab
main
Ultraviolet
<img width="400" alt="Charm Ultraviolet" src="https://github.com/user-attachments/assets/3484e4b0-3741-4e8c-bebf-9ea51f5bb49c" /> <p> <a href="https://pkg.go.dev/github.com/charmbracelet/ultraviolet?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/ultraviolet?status.svg" alt="GoDoc"></a> <a href="https://github.com/charmbracelet/ultraviolet/actions"><img src="https://github.com/charmbracelet/ultraviolet/actions/workflows/build.yml/badge.svg" alt="Build Status"></a> </p>[!NOTE] This is a fork of charmbracelet/ultraviolet used by albedo.
mainis upstream (theupstreambranch) plus one patch: the input reader keeps OSC, DCS and other ST-terminated replies whole when a read ends between the ESC and backslash of the terminator, and holds a partial OSC 5522 clipboard reply up to 5 seconds instead of flushing it at the 50 ms escape timeout. Use it withreplace github.com/charmbracelet/ultraviolet => tangled.org/okami.mom/ultraviolet <version>.
Ultraviolet is a set of primitives for building terminal user interfaces in Go.
It provides cell-based rendering, cross-platform input handling, and a diffing
renderer inspired by ncurses—without
the need for terminfo or termcap databases.
Ultraviolet powers Bubble Tea v2 and Lip Gloss v2. It replaces the ad-hoc terminal primitives from earlier versions with a cohesive, imperative API that can also be used standalone.
Install
go get github.com/charmbracelet/ultraviolet@latest
Quick Start
package mainimport ("log" uv"github.com/charmbracelet/ultraviolet" "github.com/charmbracelet/ultraviolet/screen" )func main () {t := uv .DefaultTerminal ()scr := t .Screen ()scr .EnterAltScreen ()if err := t .Start ();err != nil {log .Fatalf ("failed to start terminal: %v" ,err ) }defer t .Stop ()ctx := screen .NewContext (scr )text := "Hello, World!" textWidth := scr .StringWidth (text )display := func () {screen .Clear (scr )bounds := scr .Bounds ()x := (bounds .Dx ()- textWidth )/ 2 y := bounds .Dy ()/ 2 ctx .DrawString (text ,x ,y )scr .Render ()scr .Flush () }for ev := range t .Events () {switch ev := ev .(type ) {case uv.WindowSizeEvent :scr .Resize (ev .Width ,ev .Height )display ()case uv.KeyPressEvent :if ev .MatchString ("q" ,"ctrl+c" ) {return } } } }
Architecture
Ultraviolet is organized as a set of layered primitives:
-
Terminal — manages the application lifecycle: raw mode, input event loop, start/stop. Create one with
DefaultTerminal()orNewTerminal(console, opts). -
TerminalScreen — the screen state manager. Handles rendering, alternate screen buffer, cursor, mouse modes, keyboard enhancements, bracketed paste, window title, and more. Access it via
terminal.Screen(). -
Screen — a minimal interface (
Bounds,CellAt,SetCell,WidthMethod) implemented byTerminalScreen,Buffer,Window, andScreenBuffer. Write code againstScreento stay decoupled from the terminal. -
Buffer / Window — off-screen cell buffers.
Bufferis a flat grid of cells.Windowadds parent/child relationships and shared-buffer views. Both implementScreenandDrawable. -
screen package — drawing helpers that operate on any
Screen: aContextfor styled text rendering (Print,DrawString, etc.) and utility functions likeClear,Fill,Clone. -
layout package — a constraint-based layout solver built on the Cassowary algorithm. Partition screen space with
Len,Min,Max,Percent,Ratio, andFillconstraints.
Features
-
Cell-based diffing renderer — only redraws what changed. Optimizes cursor movement, uses ECH/REP/ICH/DCH when available, and supports scroll optimizations. Minimal bandwidth, critical for SSH.
-
Universal input — unified keyboard and mouse event handling across platforms. Supports legacy encodings, Kitty keyboard protocol, SGR mouse, and Windows Console input.
-
Inline and fullscreen — works in both alternate screen (fullscreen) and inline mode. Inline TUIs preserve terminal context and scrollback.
-
Cross-platform — first-class support for Unix (termios + ANSI) and Windows (Console API). Consistent behavior across terminal emulators.
-
Suspend/resume —
Stop()andStart()can be called repeatedly for suspend/resume cycles, shelling out to editors, or process suspension viauv.Suspend().
Examples
See the examples/ directory for core examples and
examples/advanced/ for more complex demos.
Tutorial
See TUTORIAL.md for a step-by-step guide to building your first Ultraviolet application.
[!NOTE] Ultraviolet is in active development. The API may change.
Feedback
We'd love to hear your thoughts on this project. Feel free to drop us a note!
License
Part of Charm.
<a href="https://charm.sh/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-next.jpg" /></a>
Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة
1# Ultraviolet 2 3> [!NOTE] 4> This is a fork of [charmbracelet/ultraviolet](https://github.com/charmbracelet/ultraviolet) 5> used by [albedo](https://tangled.org/okami.mom/albedo). `main` is upstream 6> (the `upstream` branch) plus one patch: the input reader keeps OSC, DCS and 7> other ST-terminated replies whole when a read ends between the ESC and 8> backslash of the terminator, and holds a partial OSC 5522 clipboard reply up 9> to 5 seconds instead of flushing it at the 50 ms escape timeout. Use it with 10> `replace github.com/charmbracelet/ultraviolet => tangled.org/okami.mom/ultraviolet <version>`. 11 12< img width ="400 "alt ="Charm Ultraviolet "src ="https://github.com/user-attachments/assets/3484e4b0-3741-4e8c-bebf-9ea51f5bb49c "/> 13 14< p > 15< a href =" https://pkg.go.dev/github.com/charmbracelet/ultraviolet?tab=doc ">< img src =" https://godoc.org/github.com/charmbracelet/ultraviolet?status.svg " alt =" GoDoc "></ a > 16< a href =" https://github.com/charmbracelet/ultraviolet/actions ">< img src =" https://github.com/charmbracelet/ultraviolet/actions/workflows/build.yml/badge.svg " alt =" Build Status "></ a > 17</ p > 18 19Ultraviolet is a set of primitives for building terminal user interfaces in Go. 20It provides cell-based rendering, cross-platform input handling, and a diffing 21renderer inspired by [ncurses](https://invisible-island.net/ncurses/)—without 22the need for `terminfo` or `termcap` databases. 23 24Ultraviolet powers [Bubble Tea v2][bbt] and [Lip Gloss v2][lg]. It replaces the 25ad-hoc terminal primitives from earlier versions with a cohesive, imperative API 26that can also be used standalone. 27 28[bbt] : https://github.com/charmbracelet/bubbletea 29[lg] : https://github.com/charmbracelet/lipgloss 30 31## Install 32 33``` bash 34go get github.com/charmbracelet/ultraviolet@latest 35``` 36 37## Quick Start 38 39``` go 40package main 41 42import ( 43"log" 44 45uv "github.com/charmbracelet/ultraviolet" 46"github.com/charmbracelet/ultraviolet/screen" 47) 48 49func main () { 50t := uv . DefaultTerminal () 51scr := t . Screen () 52 53scr . EnterAltScreen () 54 55if err := t . Start (); err != nil { 56log . Fatalf ( "failed to start terminal: %v" , err ) 57} 58defer t . Stop () 59 60ctx := screen . NewContext ( scr ) 61text := "Hello, World!" 62textWidth := scr . StringWidth ( text ) 63 64display := func () { 65screen . Clear ( scr ) 66bounds := scr . Bounds () 67x := ( bounds . Dx () - textWidth ) / 2 68y := bounds . Dy () / 2 69ctx . DrawString ( text , x , y ) 70scr . Render () 71scr . Flush () 72} 73 74for ev := range t . Events () { 75switch ev := ev .( type ) { 76case uv. WindowSizeEvent : 77scr . Resize ( ev . Width , ev . Height ) 78display () 79case uv. KeyPressEvent : 80if ev . MatchString ( "q" , "ctrl+c" ) { 81return 82} 83} 84} 85} 86``` 87 88## Architecture 89 90Ultraviolet is organized as a set of layered primitives: 91 92- **Terminal** — manages the application lifecycle: raw mode, input event loop, 93start/stop. Create one with `DefaultTerminal()` or `NewTerminal(console, opts)`. 94 95- **TerminalScreen** — the screen state manager. Handles rendering, alternate 96screen buffer, cursor, mouse modes, keyboard enhancements, bracketed paste, 97window title, and more. Access it via `terminal.Screen()`. 98 99- **Screen** — a minimal interface (`Bounds`, `CellAt`, `SetCell`, 100`WidthMethod`) implemented by `TerminalScreen`, `Buffer`, `Window`, and 101`ScreenBuffer`. Write code against `Screen` to stay decoupled from the 102terminal. 103 104- **Buffer / Window** — off-screen cell buffers. `Buffer` is a flat grid of 105cells. `Window` adds parent/child relationships and shared-buffer views. 106Both implement `Screen` and `Drawable`. 107 108- **screen package** — drawing helpers that operate on any `Screen`: a 109`Context` for styled text rendering (`Print`, `DrawString`, etc.) and 110utility functions like `Clear`, `Fill`, `Clone`. 111 112- **layout package** — a constraint-based layout solver built on the 113[Cassowary algorithm][casso]. Partition screen space with `Len`, `Min`, 114`Max`, `Percent`, `Ratio`, and `Fill` constraints. 115 116[casso] : https://en.wikipedia.org/wiki/Cassowary_(software) 117 118## Features 119 120- **Cell-based diffing renderer** — only redraws what changed. Optimizes 121cursor movement, uses ECH/REP/ICH/DCH when available, and supports scroll 122optimizations. Minimal bandwidth, critical for SSH. 123 124- **Universal input** — unified keyboard and mouse event handling across 125platforms. Supports legacy encodings, Kitty keyboard protocol, SGR mouse, 126and Windows Console input. 127 128- **Inline and fullscreen** — works in both alternate screen (fullscreen) and 129inline mode. Inline TUIs preserve terminal context and scrollback. 130 131- **Cross-platform** — first-class support for Unix (termios + ANSI) and 132Windows (Console API). Consistent behavior across terminal emulators. 133 134- **Suspend/resume** — `Stop()` and `Start()` can be called repeatedly for 135suspend/resume cycles, shelling out to editors, or process suspension 136via `uv.Suspend()`. 137 138## Examples 139 140See the [`examples/`](./examples/) directory for core examples and 141[`examples/advanced/`](./examples/advanced/) for more complex demos. 142 143## Tutorial 144 145See [TUTORIAL.md](./TUTORIAL.md) for a step-by-step guide to building your 146first Ultraviolet application. 147 148> [!NOTE] 149> Ultraviolet is in active development. The API may change. 150 151## Feedback 152 153We'd love to hear your thoughts on this project. Feel free to drop us a note! 154 155- [Twitter](https://twitter.com/charmcli) 156- [Discord](https://charm.land/discord) 157- [Slack](https://charm.land/slack) 158- [The Fediverse](https://mastodon.social/@charmcli) 159 160## License 161 162[MIT](./LICENSE) 163 164--- 165 166Part of [Charm](https://charm.land). 167 168<a href="https://charm.sh/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-next.jpg" /></a> 169 170Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة