Skip to content
Draft
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
723 commits
Select commit Hold shift + click to select a range
2e5288f
fix: renderer: truncate lines in insertAbove
aymanbagabas May 28, 2025
03deb77
refactor: use RenderComponent instead of Display
aymanbagabas May 28, 2025
a26855e
fix: renderer: compute rendered frame outside of mutex
aymanbagabas May 28, 2025
ca493b9
chore: run `modernize`
andreynering May 30, 2025
31fb503
feat: update to use uv package
aymanbagabas May 30, 2025
a73e084
feat: support setting terminal fg/bg using the View API
aymanbagabas Jun 2, 2025
69b915a
feat: add support for setting terminal window title using the View API
aymanbagabas Jun 2, 2025
1e6aaa5
feat: implement hit detection for layers in cursed renderer
aymanbagabas Jun 2, 2025
abe6d21
chore: bump ansi package to latest main and update color handling
aymanbagabas Jun 2, 2025
765f948
Merge branch 'v2-exp' into v2-exp-tv-io-viewable
aymanbagabas Jun 2, 2025
f1eadf4
feat: embed mouse events in hit messages
aymanbagabas Jun 2, 2025
9ea9a8c
feat(examples): add clickable example
aymanbagabas Jun 2, 2025
e67ab35
feat(examples): add layer hit message to canvas example
aymanbagabas Jun 2, 2025
99a80e6
feat: keyboard: split keyboard enhancements into separate functions
aymanbagabas Jun 2, 2025
576a623
fix(example): fix `keyboard-enhancements` example
andreynering Jun 3, 2025
7820424
chore: fix lint
andreynering Jun 3, 2025
19dc7c2
feat: add NewView helper function
aymanbagabas Jun 3, 2025
d2ecd81
fix: cursed_renderer: use Erase instead of Clear
aymanbagabas Jun 4, 2025
65af983
fix: renderer: reset cursor state on close
aymanbagabas Jun 9, 2025
a22e5d1
fix: renderer: properly handle insertAbove newlines
aymanbagabas Jun 9, 2025
e1dbca6
fix: renderer: set terminal colors only if they differ
aymanbagabas Jun 9, 2025
b7f6a5c
fix: no need to set terminal colors twice
aymanbagabas Jun 9, 2025
0f75ac7
fix: renderer: reset cursor state on close
aymanbagabas Jun 9, 2025
f9391ae
fix: mouse mode uv value
aymanbagabas Jun 10, 2025
3f1d09f
chore: bump ansi package to v0.9.3
aymanbagabas Jun 17, 2025
d9e8ce3
chore: update go.mod and go.sum
aymanbagabas Jun 23, 2025
a2fcb4d
Merge branch 'v2-exp' into v2-exp-tv-io-viewable
aymanbagabas Jun 23, 2025
2e8f670
fix: render: styled string api changes
aymanbagabas Jun 23, 2025
fe8fa9d
chore: update terminal reader api
aymanbagabas Jun 24, 2025
73dbb77
fix: renderer: resizing the alt screen buffer too often may cause issues
aymanbagabas Jun 25, 2025
c3a99ef
feat: input: use new uv input reader api
aymanbagabas Jun 26, 2025
9b921df
feat: add option to disable key enhancements
aymanbagabas Jun 26, 2025
73b42b8
fix(renderer): only send non-empty layer hit messages
aymanbagabas Jun 27, 2025
efd37e6
chore: update to use ultraviolet repository name
aymanbagabas Jun 30, 2025
b755bb7
chore: update dependencies
aymanbagabas Jul 1, 2025
391d1c6
chore: bump ultraviolet
aymanbagabas Jul 1, 2025
46c5cdc
fix: renderer: reset touched lines buffer on resize
aymanbagabas Jul 1, 2025
0013d07
fix: renderer: reset touched lines buffer on resize
aymanbagabas Jul 2, 2025
a991b58
chore: bump ultraviolet
aymanbagabas Jul 2, 2025
a42fb60
chore: remove StyledString function
aymanbagabas Jul 3, 2025
e4402a5
chore: bump ultraviolet to latest main
aymanbagabas Jul 7, 2025
34f66cd
chore: bump x/input to v0.3.5
aymanbagabas Jul 7, 2025
1b86faa
chore: bump x/input to v0.3.6
aymanbagabas Jul 7, 2025
3ce0c24
feat: create a panic trace file (#1446)
aymanbagabas Jul 7, 2025
24fc6de
chore: bump dependencies
aymanbagabas Jul 7, 2025
911530d
Merge branch 'main' into v2-exp
aymanbagabas Jul 7, 2025
f4c5598
Merge branch 'v2-exp' into v2-exp-tv-io-viewable
aymanbagabas Jul 7, 2025
f4b2ad3
chore: bump ultraviolet
aymanbagabas Jul 8, 2025
144080f
chore: bump dependencies
aymanbagabas Jul 8, 2025
2fe539b
fix: kitty keyboard has its own state for main and alternate screens
aymanbagabas Jul 10, 2025
81ed4ba
chore: retract v2.0.0-beta1
aymanbagabas Jul 10, 2025
3c0ffd2
Merge branch 'v2-exp' into v2-exp-tv-io-viewable
aymanbagabas Jul 10, 2025
71ae903
chore: remove unused program fields
aymanbagabas Jul 14, 2025
5d1379f
chore: bump ultraviolet
aymanbagabas Jul 16, 2025
e58f3ca
chore: tests: update golden files for the new renderer
aymanbagabas Jul 16, 2025
d6c0563
chore: tests: update testdata for windows
aymanbagabas Jul 16, 2025
7d819d8
chore(examples): update go.mod and go.sum
aymanbagabas Jul 16, 2025
9bfcf3f
chore(examples): update lipgloss to latest v2-exp
aymanbagabas Jul 16, 2025
5ca4720
chore: fix lint issues
aymanbagabas Jul 16, 2025
bb75e8f
Merge pull request #1452 from charmbracelet/v2-exp-tv-io-viewable
aymanbagabas Jul 17, 2025
8babccd
chore: bump ultraviolet to latest
aymanbagabas Jul 21, 2025
7684eea
chore: bump ultraviolet
aymanbagabas Jul 21, 2025
875f553
fix: disable modifyOtherKeys for tmux
aymanbagabas Jul 22, 2025
5ba56e2
chore: go mod tidy
aymanbagabas Jul 24, 2025
56ff714
fix(renderer): reset cursor style on close
aymanbagabas Jul 30, 2025
70e94a2
fix(keyboard): use kitty keyboard state command
aymanbagabas Aug 5, 2025
aa832ac
chore: bump x/ansi to v0.10.0
aymanbagabas Aug 5, 2025
b149293
chore: bump ultraviolet and ansi dependencies
aymanbagabas Aug 5, 2025
ec08f6f
chore: examples: update dependencies
aymanbagabas Aug 6, 2025
9ef921a
Merge branch 'main' into v2-exp
aymanbagabas Aug 7, 2025
68df41d
Merge branch 'main' into v2-exp
aymanbagabas Aug 8, 2025
f9df81b
fix(renderer): clear screen on exit when not using alt screen
aymanbagabas Aug 13, 2025
4ea1703
fix: ensure cmd() is called in a separate function
aymanbagabas Aug 13, 2025
51804bc
fix(examples): ensure we have a newline at the end of the simple example
aymanbagabas Aug 13, 2025
d4d69f6
fix(renderer): drop lines from top of buffer when frame height exceed…
aymanbagabas Aug 13, 2025
5cc219d
chore: bump dependencies to fix caching colors on linux console
aymanbagabas Aug 13, 2025
0db2eab
Bump Ultraviolet and update input handling (#1493)
aymanbagabas Sep 9, 2025
59b04aa
fix: remove enhanced keyboard windows special casing
aymanbagabas Sep 9, 2025
997384b
chore: bump ultraviolet to fix esc key
aymanbagabas Sep 10, 2025
c50f808
Merge branch 'main' into v2-exp
aymanbagabas Sep 11, 2025
816d7bb
chore: fix and unify screen testdata
aymanbagabas Sep 11, 2025
439500e
fix: update screen_test to not depend on platform for test names
aymanbagabas Sep 11, 2025
4cafc09
feat: add support for terminal progress bars (#1499)
aymanbagabas Sep 30, 2025
1cbd575
chore: remove unused examples
aymanbagabas Oct 1, 2025
688573d
refactor: remove WithContext and pass context to Run
aymanbagabas Sep 30, 2025
94c70a4
feat: add OpenTTY to open the terminal's TTY
aymanbagabas Sep 30, 2025
6b64145
refactor: replace WithInput and WithOutput options with Input and Out…
aymanbagabas Sep 30, 2025
608155c
refactor: remove WithInputTTY option and related code
aymanbagabas Sep 30, 2025
7b13c33
refactor: remove WithEnvironment option in favor of Env field on Program
aymanbagabas Sep 30, 2025
cf7bb13
refactor: remove WithoutSignalHandler option in favor of a field in P…
aymanbagabas Sep 30, 2025
8b68181
refactor: remove WithoutCatchPanics option in favor of a boolean field
aymanbagabas Sep 30, 2025
657e54e
refactor: remove WithoutSignals option in favor of IgnoreSignals field
aymanbagabas Sep 30, 2025
b4236df
refactor: move WithFilter to Program.Filter
aymanbagabas Sep 30, 2025
7db9526
chore: add docs for Program fields
aymanbagabas Sep 30, 2025
220e3df
refactor: support disabling input via Program struct field
aymanbagabas Sep 30, 2025
6bc94a9
refactor: remove WithFPS option in favor of Program.FPS field
aymanbagabas Sep 30, 2025
fd39cfc
refactor: remove WithColorProfile option in favor of Program.ColorPro…
aymanbagabas Sep 30, 2025
d112824
refactor: remove WithWindowSize option in favor of InitialWidth and I…
aymanbagabas Sep 30, 2025
fb3e0a4
refactor: lean more into the View struct to manage terminal state
aymanbagabas Sep 30, 2025
53884ef
refactor: move term modes into View struct and renderer logic
aymanbagabas Sep 30, 2025
0ee1cf1
refactor: move key enhancement logic and options to View struct
aymanbagabas Oct 1, 2025
8f0d83c
fix: reset kitty keyboard protocol when switching alt screen
aymanbagabas Oct 1, 2025
bd747e7
refactor: clean up redundant code and update testdata
aymanbagabas Oct 1, 2025
edc51e3
refactor: rename TerminalVersion to RequestTerminalVersion
aymanbagabas Oct 1, 2025
93c3157
refactor: remove unused startupOptions
aymanbagabas Oct 1, 2025
5cbd22b
refactor: expose InitialModel field in Program struct
aymanbagabas Oct 1, 2025
178b34d
refactor: simplify NewProgram by moving channel initializations to Run
aymanbagabas Oct 1, 2025
6c1e051
refactor: make renderer flush method not require Program parameter and
aymanbagabas Oct 1, 2025
30a273a
fix: ensure Program is initialized before use
aymanbagabas Oct 1, 2025
20e5ff5
fix: ensure program is initialized before sending messages
aymanbagabas Oct 1, 2025
0fbbd9a
fix: ignore nested lint if in flush()
aymanbagabas Oct 1, 2025
f51fc36
feat: add helper method SetContent to View
aymanbagabas Oct 1, 2025
18a970e
fix: rely on the view's altscreen and cursor state
aymanbagabas Oct 1, 2025
c4303e1
fix: dry passed width and height to newCursedRenderer and send resize
aymanbagabas Oct 1, 2025
d5cd60b
chore: update testdata
aymanbagabas Oct 1, 2025
72e6622
fix: use nilRenderer when no renderer is set
aymanbagabas Oct 1, 2025
f2d8c4d
chore: update examples and api
aymanbagabas Oct 1, 2025
cf6866f
fix: add View to Model interface and introduce DisableRenderer field
aymanbagabas Oct 1, 2025
2265bcd
chore: update tui-daemon-combo to use tea.View
aymanbagabas Oct 1, 2025
705f25b
docs: improve godoc for View struct
aymanbagabas Oct 1, 2025
20b1d5d
chore: update examples to use tea.View
aymanbagabas Oct 1, 2025
4b049d1
docs(examples): chat: enable AltScreen
aymanbagabas Oct 1, 2025
c6588c4
fix: renderer: relative cursor logic
aymanbagabas Oct 1, 2025
b958dc7
chore: update testdata
aymanbagabas Oct 1, 2025
5435371
docs(examples): update colorprofile example
aymanbagabas Oct 1, 2025
73ab62b
docs(examples): textarea: fix background color handling
aymanbagabas Oct 1, 2025
f58ca7a
chore(examples): simple: disable test temporarily
aymanbagabas Oct 1, 2025
474f7af
fix: renderer: account for new View fields in viewEquals
aymanbagabas Oct 1, 2025
9e857f4
fix: only render progress bar if it's not none at start and end
aymanbagabas Oct 1, 2025
fd7b043
fix: renderer: properly resize the internal buffer
aymanbagabas Oct 1, 2025
2e341cf
fix: protect output buffer with mutex (#1502)
aymanbagabas Oct 1, 2025
3b687ff
fix(progress): reset on shutdown (#1511)
caarlos0 Oct 11, 2025
be3c7e5
refactor: restore options
aymanbagabas Oct 14, 2025
72c4ec6
Merge branch 'v2-exp' into v2-idiomatic
aymanbagabas Oct 14, 2025
eecd887
docs: update examples to use the new api
aymanbagabas Oct 14, 2025
a1bd1d9
chore: go mod tidy
aymanbagabas Oct 14, 2025
fe01c2a
chore: fix examples to use functional options
aymanbagabas Oct 14, 2025
511ec98
docs(examples): space: fix off-by-one error in height calculation
aymanbagabas Oct 14, 2025
57c1888
docs(examples): splash: fix extra newline at bottom of gradient
aymanbagabas Oct 14, 2025
87f9a59
fix: remove deprecated WithInputTTY option
aymanbagabas Oct 14, 2025
d5c3029
fix: renderer: no need to compare last frame and view
aymanbagabas Oct 14, 2025
78e3b36
fix: remove resetLinesRendered calls around exec
aymanbagabas Oct 14, 2025
1f4de36
fix: renderer: properly handle screen repainting
aymanbagabas Oct 14, 2025
e9e4d1d
fix: renderer: remove unused repaint functionality
aymanbagabas Oct 14, 2025
47cd981
refactor: use struct for ClipboardMsg to include selection type
aymanbagabas Oct 14, 2025
9783b51
fix: renderer: no need to render the buffer to a string
aymanbagabas Oct 14, 2025
351510f
fix: renderer: remove unused field lastFrameHeight
aymanbagabas Oct 14, 2025
42a5296
fix: renderer: delay prepend until flush and optimize rendering it
aymanbagabas Oct 14, 2025
0c3e204
chore: remove unused repaint method from nilRenderer
aymanbagabas Oct 14, 2025
f0c5a2d
fix: remove unnecessary key disambiguation support check
aymanbagabas Oct 14, 2025
094aa2e
chore: remove unused CursorModel interface
aymanbagabas Oct 14, 2025
718c8e7
feat: restore WithoutRenderer option
aymanbagabas Oct 14, 2025
d97f20b
fix: use uint8 for KeyboardEnhancementsMsg
aymanbagabas Oct 15, 2025
23f994f
chore(examples): update tui-daemon-combo to use ProgramOptions
aymanbagabas Oct 15, 2025
506041e
chore: update ultraviolet and x/sys
aymanbagabas Oct 15, 2025
ab0bc8e
fix: correct event type name
aymanbagabas Oct 15, 2025
256e348
fix(examples): add newline to keyboard-enhancements example output
aymanbagabas Oct 15, 2025
4a065bf
chore: bump ultraviolet to v0.0.0-20251015160106-36a5aeb2b2dd
aymanbagabas Oct 15, 2025
78ff9b5
docs(examples): add vanish-on-exit example (#1516)
meowgorithm Oct 16, 2025
ea76ea2
Merge branch 'v2-exp' into v2-idiomatic
aymanbagabas Oct 16, 2025
8fc7516
docs(examples): update vanish example to use tea.View
aymanbagabas Oct 16, 2025
fe05df7
Merge pull request #1500 from charmbracelet/v2-idiomatic
aymanbagabas Oct 22, 2025
b4d105e
Merge branch 'main' into v2-exp
aymanbagabas Oct 22, 2025
d7c95b8
fix: renderer: sync buffer resize with frame rate
aymanbagabas Oct 30, 2025
fa36fb1
fix: renderer: only move cursor to bottom when we're in the main screen
aymanbagabas Oct 30, 2025
72ca5f4
chore: update golden files
aymanbagabas Oct 30, 2025
c087023
Merge pull request #1525 from charmbracelet/v2-delay-render-resize
aymanbagabas Oct 30, 2025
6781fb5
fix: renderer: ensure we reset cursor style and color on close
aymanbagabas Oct 30, 2025
4accb1c
fix: renderer: avoid requesting keyboard enhancements on close
aymanbagabas Oct 30, 2025
7a6e8fc
chore: bump ultraviolet and x/ansi, x/term minor versions
aymanbagabas Nov 4, 2025
b947ade
refactor: change several message types to structs for extensibility
aymanbagabas Nov 4, 2025
6a65a1f
chore(docs): update examples and dependencies for v2-exp
aymanbagabas Nov 4, 2025
b864579
refactor: update module path to charm.land/bubbletea/v2
aymanbagabas Nov 4, 2025
842bea3
chore: update example go.mod and go.sum to use new charm.land module …
aymanbagabas Nov 4, 2025
ff8c824
docs(examples): migrate imports to charm.land
aymanbagabas Nov 4, 2025
cc0168c
refactor: migrate imports to charm.land domain
aymanbagabas Nov 4, 2025
101fd11
Revert "fix: renderer: sync buffer resize with frame rate"
aymanbagabas Nov 5, 2025
1dcdea9
fix: renderer: use the correct size when resizing the screen
aymanbagabas Nov 5, 2025
514da28
perf: renderer: skip flush if no changes
aymanbagabas Nov 5, 2025
db021e2
chore: test: add benchmark for tea Run method
aymanbagabas Nov 5, 2025
3138f1c
chore: bump ultraviolet and colorprofile dependencies
aymanbagabas Nov 5, 2025
d9f7210
fix(renderer): avoid unnecessary resize on alt screen buffer
aymanbagabas Nov 6, 2025
f03c467
refactor: keyboard enhancements api improvements (#1534)
aymanbagabas Nov 6, 2025
a1ecb94
refactor: rename View.Layer to View.Content for clarity (#1536)
aymanbagabas Nov 6, 2025
06c0cda
chore: bump ultraviolet to include recent changes
aymanbagabas Nov 6, 2025
579e174
chore: bump dependencies for v2-exp
aymanbagabas Nov 6, 2025
aa0071e
fix: renderer: we want to always use the frame area for drawing
aymanbagabas Nov 6, 2025
f952eb9
fix: renderer: use an interface for inline height calculation
aymanbagabas Nov 6, 2025
3780c0e
docs: update keyboard enhancement flags comment
aymanbagabas Nov 12, 2025
94247ed
feat: add SupportsKeyDisambiguation to KeyboardEnhancementsMsg
aymanbagabas Nov 12, 2025
3a71934
fix: renderer: ensure prepended lines queued before render
aymanbagabas Nov 12, 2025
f01fc81
fix: renderer: reset cursor position in inline mode to avoid line wraps
aymanbagabas Nov 12, 2025
39e9984
chore: bump dependencies for v2-exp
aymanbagabas Nov 12, 2025
7120058
feat: introduce ModeReportMsg for terminal mode reports
aymanbagabas Nov 13, 2025
f1799cd
feat: add synchronized updates option to renderer interface
aymanbagabas Nov 13, 2025
349783e
feat: query terminal for synchronized output support (mode 2026)
aymanbagabas Nov 13, 2025
c3c752d
refactor: renderer: support mode 2026, manage cursor visibility and a…
aymanbagabas Nov 13, 2025
b1241c9
chore(examples): go mod tidy
aymanbagabas Nov 13, 2025
a74936a
chore(tests): fix tests and update testdata
aymanbagabas Nov 13, 2025
8f17c35
fix(examples): revert textarea pointers to values
aymanbagabas Nov 13, 2025
2c7af7f
fix: renderer: avoid redundant cursor toggles
aymanbagabas Nov 14, 2025
fa796c9
chore: update testdata for cursor hide/show changes
aymanbagabas Nov 14, 2025
39f38b1
Merge branch 'v2-exp' into charm-853-cursor-flash-interruptions-mode-…
aymanbagabas Nov 14, 2025
d88ab58
feat: renderer: use uv altscreen helpers
aymanbagabas Nov 14, 2025
befc5a4
chore: bump dependencies to use uv helpers
aymanbagabas Nov 14, 2025
cfe6724
docs: update code example formatting in screen.go
aymanbagabas Nov 14, 2025
9878b7a
docs: update NewView and SetContent to add examples and notes
aymanbagabas Nov 14, 2025
ed050cd
refactor: extract terminal capability detection into helper function …
Copilot Nov 14, 2025
03b6524
fix: edge case where cursor visibility is the only change
aymanbagabas Nov 14, 2025
78766cd
fix(examples): use updated progress bar blend api
aymanbagabas Nov 14, 2025
6dfb887
chore: bump ultraviolet to 20251114211315-f6a8e3732033
aymanbagabas Nov 14, 2025
5133131
fix: renderer: always erase to end of line when prepending lines
aymanbagabas Nov 14, 2025
1ef7dd4
fix: ensure TERM_PROGRAM is set
aymanbagabas Nov 14, 2025
55b3503
Merge pull request #1542 from charmbracelet/charm-853-cursor-flash-in…
aymanbagabas Nov 14, 2025
f60735d
chore: bump dependencies
aymanbagabas Nov 16, 2025
f19cb68
fix: renderer: defer resize and draw until flush
aymanbagabas Nov 16, 2025
83e606b
fix: renderer: handle cursor visibility and syncd output efficiently
aymanbagabas Nov 16, 2025
f206009
fix: renderer: always redraw on resize
aymanbagabas Nov 16, 2025
42f01c6
chore: bump ultraviolet dependency to latest
aymanbagabas Nov 16, 2025
6483c7e
chore(tests): update golden files
aymanbagabas Nov 16, 2025
4687350
fix: renderer: check for cellbuf size change before skipping flush
aymanbagabas Nov 16, 2025
15f884b
Merge pull request #1546 from charmbracelet/v2-tear
aymanbagabas Nov 17, 2025
0b47252
feat: add view callback support
aymanbagabas Nov 20, 2025
e78528d
chore(examples): update clickable example to use v2 callback for laye…
aymanbagabas Nov 20, 2025
d1cf96d
refactor: limit view callback to onMouse for mouse events
aymanbagabas Nov 24, 2025
fb79053
fix(renderer): make sure we don't skip prepended lines on no-op frames
aymanbagabas Nov 24, 2025
46b608f
docs: update OnMouse callback to use msg parameter
aymanbagabas Nov 24, 2025
e02ba76
chore(examples): update to bubbletea v2 onMouse callback
aymanbagabas Nov 24, 2025
ba8f605
fix: go.mod and go.sum to use lipgloss v2
aymanbagabas Nov 24, 2025
5de0f1f
Merge pull request #1549 from charmbracelet/v2-callback
aymanbagabas Nov 24, 2025
ec0d820
fix(tea): only send actual mouse events to renderer on mouse callback
aymanbagabas Nov 26, 2025
2a0096c
fix(renderer): restore state when restarting cursed renderer (#1553)
aymanbagabas Nov 26, 2025
551c60e
chore: bump dependencies
aymanbagabas Dec 1, 2025
5fa38b7
chore: bump ultraviolet to fix rendering issues with unnecessary cursor
aymanbagabas Dec 2, 2025
59807cf
fix(renderer): reset kitty keyboard protocol on alt screen switch (#1…
aymanbagabas Dec 10, 2025
9e01328
chore: bump ultraviolet to control renderer scroll optimization
aymanbagabas Dec 10, 2025
4e524db
chore: remove local replace of ultraviolet module
aymanbagabas Dec 10, 2025
c50235b
chore: remove local replace of ultraviolet in examples go.mod
aymanbagabas Dec 10, 2025
69636dd
chore: bump ultraviolet to fix cursor movement issue that cause artif…
aymanbagabas Dec 10, 2025
3f03681
chore: bump ultraviolet to fix scroll empty line bug
aymanbagabas Dec 10, 2025
9ed8357
chore: bump dependencies for v2-exp
aymanbagabas Dec 11, 2025
7adbf08
chore: remove local replace directive for ultraviolet module
aymanbagabas Dec 12, 2025
6348bd4
chore: bump uv to fix non en lang rendering issues
aymanbagabas Dec 12, 2025
fdb8651
fix(renderer): always move cursor to bottom on close
aymanbagabas Dec 16, 2025
99c33bc
fix(renderer): move cursor to bottom before disabling alt screen
aymanbagabas Dec 16, 2025
819e2e8
fix(renderer): flush after moving cursor on close
aymanbagabas Dec 16, 2025
7ae2c09
chore(examples): update lipgloss to v2.0.0-beta.3.0.20251205162909-78…
aymanbagabas Jan 13, 2026
76f2e6d
fix(render): always assume raw mode for terminal output
aymanbagabas Jan 26, 2026
b65daeb
fix(examples): capability make sure input is focused on start
aymanbagabas Jan 30, 2026
61a3f5c
fix(render): execute insert above immediately (#1576)
aymanbagabas Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import (
"fmt"
"os"

tea "github.com/charmbracelet/bubbletea"
tea "github.com/charmbracelet/bubbletea/v2"
)
```

Expand All @@ -96,7 +96,7 @@ type model struct {
}
```

### Initialization
## Initialization

Next, we’ll define our application’s initial state. In this case, we’re defining
a function to return our initial model, however, we could just as easily define
Expand All @@ -116,14 +116,25 @@ func initialModel() model {
}
```

Next, we 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."
After that, we’ll define our application’s initial state in 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."

```go
func (m model) Init() tea.Cmd {
func (m model) Init() (tea.Model, tea.Cmd) {
m = {
// Our to-do list is 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{}),
}

// Just return `nil`, which means "no I/O right now, please."
return nil
return m, nil
}
```

Expand All @@ -144,15 +155,15 @@ 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.
For now, we'll just deal with `tea.KeyPressMsg` messages, which are
automatically sent to the update function when keys are pressed.

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

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

// Cool, what was the actual key pressed?
switch msg.String() {
Expand All @@ -173,9 +184,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
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", " ":
// The "enter" key and the space bar (a literal space) toggle the
// selected state for the item that the cursor is pointing at.
case "enter", "space":
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
Expand Down
69 changes: 69 additions & 0 deletions clipboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package tea

// ClipboardMsg is a clipboard read message event. This message is emitted when
// a terminal receives an OSC52 clipboard read message event.
type ClipboardMsg string

// String returns the string representation of the clipboard message.
func (e ClipboardMsg) String() string {
return string(e)
}

// PrimaryClipboardMsg is a primary clipboard read message event. This message
// is emitted when a terminal receives an OSC52 primary clipboard read message
// event. Primary clipboard selection is a feature present in X11 and Wayland
// only.
type PrimaryClipboardMsg string

// String returns the string representation of the primary clipboard message.
func (e PrimaryClipboardMsg) String() string {
return string(e)
}

// setClipboardMsg is an internal message used to set the system clipboard
// using OSC52.
type setClipboardMsg string

// SetClipboard produces a command that sets the system clipboard using OSC52.
// Note that OSC52 is not supported in all terminals.
func SetClipboard(s string) Cmd {
return func() Msg {
return setClipboardMsg(s)
}
}

// readClipboardMsg is an internal message used to read the system clipboard
// using OSC52.
type readClipboardMsg struct{}

// ReadClipboard produces a command that reads the system clipboard using OSC52.
// Note that OSC52 is not supported in all terminals.
func ReadClipboard() Msg {
return readClipboardMsg{}
}

// setPrimaryClipboardMsg is an internal message used to set the primary
// clipboard using OSC52.
type setPrimaryClipboardMsg string

// SetPrimaryClipboard produces a command that sets the primary clipboard using
// OSC52. Primary clipboard selection is a feature present in X11 and Wayland
// only.
// Note that OSC52 is not supported in all terminals.
func SetPrimaryClipboard(s string) Cmd {
return func() Msg {
return setPrimaryClipboardMsg(s)
}
}

// readPrimaryClipboardMsg is an internal message used to read the primary
// clipboard using OSC52.
type readPrimaryClipboardMsg struct{}

// ReadPrimaryClipboard produces a command that reads the primary clipboard
// using OSC52. Primary clipboard selection is a feature present in X11 and
// Wayland only.
// Note that OSC52 is not supported in all terminals.
func ReadPrimaryClipboard() Msg {
return readPrimaryClipboardMsg{}
}
121 changes: 121 additions & 0 deletions color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package tea

import (
"image/color"

uv "github.com/charmbracelet/ultraviolet"
)

// backgroundColorMsg is a message that requests the terminal background color.
type backgroundColorMsg struct{}

// RequestBackgroundColor is a command that requests the terminal background color.
func RequestBackgroundColor() Msg {
return backgroundColorMsg{}
}

// foregroundColorMsg is a message that requests the terminal foreground color.
type foregroundColorMsg struct{}

// RequestForegroundColor is a command that requests the terminal foreground color.
func RequestForegroundColor() Msg {
return foregroundColorMsg{}
}

// cursorColorMsg is a message that requests the terminal cursor color.
type cursorColorMsg struct{}

// RequestCursorColor is a command that requests the terminal cursor color.
func RequestCursorColor() Msg {
return cursorColorMsg{}
}

// setBackgroundColorMsg is a message that sets the terminal background color.
type setBackgroundColorMsg struct{ color.Color }

// SetBackgroundColor is a command that sets the terminal background color.
func SetBackgroundColor(c color.Color) Cmd {
return func() Msg {
return setBackgroundColorMsg{c}
}
}

// setForegroundColorMsg is a message that sets the terminal foreground color.
type setForegroundColorMsg struct{ color.Color }

// SetForegroundColor is a command that sets the terminal foreground color.
func SetForegroundColor(c color.Color) Cmd {
return func() Msg {
return setForegroundColorMsg{c}
}
}

// setCursorColorMsg is a message that sets the terminal cursor color.
type setCursorColorMsg struct{ color.Color }

// SetCursorColor is a command that sets the terminal cursor color.
func SetCursorColor(c color.Color) Cmd {
return func() Msg {
return setCursorColorMsg{c}
}
}

// ForegroundColorMsg represents a foreground color message. This message is
// emitted when the program requests the terminal foreground color with the
// [RequestForegroundColor] Cmd.
type ForegroundColorMsg struct{ color.Color }

// String returns the hex representation of the color.
func (e ForegroundColorMsg) String() string {
return uv.ForegroundColorEvent(e).String()
}

// IsDark returns whether the color is dark.
func (e ForegroundColorMsg) IsDark() bool {
return uv.ForegroundColorEvent(e).IsDark()
}

// BackgroundColorMsg represents a background color message. This message is
// emitted when the program requests the terminal background color with the
// [RequestBackgroundColor] Cmd.
//
// This is commonly used in [Update.Init] to get the terminal background color
// for style definitions. For that you'll want to call
// [BackgroundColorMsg.IsDark] to determine if the color is dark or light. For
// example:
//
// func (m Model) Init() (Model, Cmd) {
// return m, RequestBackgroundColor()
// }
//
// func (m Model) Update(msg Msg) (Model, Cmd) {
// switch msg := msg.(type) {
// case BackgroundColorMsg:
// m.styles = newStyles(msg.IsDark())
// }
// }
type BackgroundColorMsg struct{ color.Color }

// String returns the hex representation of the color.
func (e BackgroundColorMsg) String() string {
return uv.BackgroundColorEvent(e).String()
}

// IsDark returns whether the color is dark.
func (e BackgroundColorMsg) IsDark() bool {
return uv.BackgroundColorEvent(e).IsDark()
}

// CursorColorMsg represents a cursor color change message. This message is
// emitted when the program requests the terminal cursor color.
type CursorColorMsg struct{ color.Color }

// String returns the hex representation of the color.
func (e CursorColorMsg) String() string {
return uv.CursorColorEvent(e).String()
}

// IsDark returns whether the color is dark.
func (e CursorColorMsg) IsDark() bool {
return uv.CursorColorEvent(e).IsDark()
}
60 changes: 15 additions & 45 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
//
// Example:
//
// func (m model) Init() Cmd {
// return tea.Batch(someCommand, someOtherCommand)
// func (m model) Init() (Model, Cmd) {
// return m, tea.Batch(someCommand, someOtherCommand)
// }
func Batch(cmds ...Cmd) Cmd {
return compactCmds[BatchMsg](cmds)
Expand Down Expand Up @@ -84,9 +84,9 @@ func compactCmds[T ~[]Cmd](cmds []Cmd) Cmd {
// })
// }
//
// func (m model) Init() Cmd {
// func (m model) Init() (Model, Cmd) {
// // Start ticking.
// return tickEvery()
// return m, tickEvery()
// }
//
// func (m model) Update(msg Msg) (Model, Cmd) {
Expand Down Expand Up @@ -138,9 +138,9 @@ func Every(duration time.Duration, fn func(time.Time) Msg) Cmd {
// })
// }
//
// func (m model) Init() Cmd {
// func (m model) Init() (Model, Cmd) {
// // Start ticking.
// return doTick()
// return m, doTick()
// }
//
// func (m model) Update(msg Msg) (Model, Cmd) {
Expand All @@ -163,44 +163,16 @@ func Tick(d time.Duration, fn func(time.Time) Msg) Cmd {
}
}

// Sequentially produces a command that sequentially executes the given
// commands.
// The Msg returned is the first non-nil message returned by a Cmd.
//
// func saveStateCmd() Msg {
// if err := save(); err != nil {
// return errMsg{err}
// }
// return nil
// }
//
// cmd := Sequentially(saveStateCmd, Quit)
//
// Deprecated: use Sequence instead.
func Sequentially(cmds ...Cmd) Cmd {
return func() Msg {
for _, cmd := range cmds {
if cmd == nil {
continue
}
if msg := cmd(); msg != nil {
return msg
}
}
return nil
}
}

// setWindowTitleMsg is an internal message used to set the window title.
type setWindowTitleMsg string

// SetWindowTitle produces a command that sets the terminal title.
//
// For example:
//
// func (m model) Init() Cmd {
// func (m model) Init() (Model, Cmd) {
// // Set title.
// return tea.SetWindowTitle("My App")
// return m, tea.SetWindowTitle("My App")
// }
func SetWindowTitle(title string) Cmd {
return func() Msg {
Expand All @@ -210,13 +182,11 @@ func SetWindowTitle(title string) Cmd {

type windowSizeMsg struct{}

// WindowSize is a command that queries the terminal for its current size. It
// delivers the results to Update via a [WindowSizeMsg]. Keep in mind that
// WindowSizeMsgs will automatically be delivered to Update when the [Program]
// starts and when the window dimensions change so in many cases you will not
// need to explicitly invoke this command.
func WindowSize() Cmd {
return func() Msg {
return windowSizeMsg{}
}
// RequestWindowSize is a command that queries the terminal for its current
// size. It delivers the results to Update via a [WindowSizeMsg]. Keep in mind
// that WindowSizeMsgs will automatically be delivered to Update when the
// [Program] starts and when the window dimensions change so in many cases you
// will not need to explicitly invoke this command.
func RequestWindowSize() Msg {
return windowSizeMsg{}
}
Loading
Loading