v0.0.1
uncurses is a Rust library for building terminal user interfaces. It gives you a direct, framework-free way to draw to the terminal and read input — you own every cell and your own event loop, whether you run inline, take over the full screen, or mix the two.
A diffing renderer that redraws only what changed, Unicode-aware width, truecolor styling with automatic downsampling, hyperlinks, and typed keyboard, mouse, and paste input. It asks the terminal what it supports instead of looking it up in a terminfo database, so the same code runs on Linux, macOS, and Windows.
[dependencies]
uncurses = "0.0.1"Using ratatui? uncurses-ratatui provides a backend.
This is the first release, so expect the API to move before 0.1.
Guides, concepts, and API reference: uncurses.org
Changelog
Bug Fixes
- Correct two test expectations for Windows
- Tighten CSI decoder matching for private/intermediate/param length
- Preserve source cursor row across inline shrinks
- Emit underline colors in ITU T.416 colon form
- Honor WT_SESSION on Windows when TERM is unset
- Land reset cursor at last-rendered bottom, not live height
- Store Style hyperlink behind Arc
- Advance sync_front by cell width
- Decode Kitty event types for non-CSI-u keys
- Force cursor reassert after invalidate
- Tee input at fd read site instead of parse()
- Compare Key by code and modifiers only
- Canonicalize Tab+Shift to BackTab in normalize
- Gate shifted_key text auto-pop on shift state
- Only apply CAPS_LOCK as shifted layer for ASCII letters
- Treat CAPS_LOCK as shifted layer for any cased letter
- Lowercase ASCII letters in C1 introducer fallback
- Align win32 input mode with normalize rules
- Exclude lock states from Key equality and hash
- Error on leading
+and clarifymatcheslock-state docs - Make Key::normalize public so intra-doc links resolve
- Keep UTF-8 glyphs intact in wire dumps
- Fall back to input fd for window size
- Detect TrueColor when CI is set
- Build kevent from a zeroed value
- Disable color for an explicit dumb TERM everywhere
- Trace synthesized input bytes on windows
- Use the select poller on the generic unix fallback
- Accept in-band resize reports without pixel fields
- Stop tab planner overshooting past the last stop
- Drop the async event stream on finish and pause
- Honor DECRPM permanent states in capability detection
- Emit the hyperlink opener from Style::write after the SGR
- Restore landing page spacing and rebrand the footer
- Make API reference links root-absolute
- Re-anchor inline cursor on resume to stop eating lines
- Paint task_picker's SGR strings through a Painter
- Drain pending query replies on teardown to stop shell bleed
- Emit no escapes for empty styled spans
- Correct Windows raw mode console flags
- Gate test-only decoder helpers to test builds
- Reset pointer shape with "default" not empty OSC 22
- Resolve clippy lints on unix paths
- Preserve wide cell style when broken into blanks
- Drop redundant borrow in assert formatting
- Drain in-band resize echo to stop shell bleed
- Chain to the displaced SIGWINCH handler
Documentation
- Add README
- Add MIT license
- Deduplicate CapsLock paragraph in normalize
- Clarify single-char parse path accepts literal
+ - Sized constructor and crate stdio in quick-start doctests
- Add compositional terminal example
- Add capability-probe example for the query API
- Expand capabilities into a colorful capability report
- Correct the Copy claim on Single
- Illustrate the managed area for fullscreen and inline
- Probe capabilities across the execution × method matrix
- Add terminal fundamentals and tutorial guides
- Polish READMEs in a human voice
- Add image to README for output illustration
- Show querying a terminal by hand
- List supported terminal features
- Note uncurses runs on other unix-like systems
- Document character widths and the ambiguous policy
- Expand crate, module, and Screen rustdoc
- Add use-case examples to module docs and a low-level demo
- Document remaining public items and ratatui crate quick start
- Add module-level examples to color, buffer, cell, and ansi
- Add styling and terminal-query examples
- Add input-only, draw-only, offscreen, mouse, and async examples
- Add bracketed-paste and truecolor-gradient examples
- Add pause/resume and paste-spilling examples
- Drive the styles example with Style open/close sequences
- Overhaul READMEs and guides for the current API and examples
- Clarify Screen starts inline with the cursor visible
- Link the README taste to the repo and set the inline example to one row
- Comprehensive rustdoc with ASCII diagrams across the API
- Slim package READMEs to point at the docs site
- Add the documentation website
- Showcase Style::new() in README and website snippets
- Correct the output buffering and flushing description
- Use screen.render() in the README quick start
- Rebuild the Concepts section from scratch
- Fix stale source-doc references after the recent API changes
- Slim the READMEs down to pointers to the website
- Center Mermaid diagrams
- Clarify the Terminals intro
- Make grid figures use 1-based rows and columns
- Reframe layers by use case and call uncurses a terminal toolkit library
- Rebuild the Getting Started section
- Drop the Explanations section
- Add Guides section and Color concept page
- Audit and proofread pass across all pages
- List the unicode module in the module map
- Use set_color_profile in the color guide
- Flag the advanced ScreenOptions transport knobs
- Use ansi::color in the querying guide
- Fix stale references after the Display alternate-flag change
- Drop the removed bench feature from the feature table
- Update mouse guide for the MouseTracking bitflags API
- Correct the diff module overview
- Drop the anstyle crate reference from the styling guide
- Fix KittyKeyboardFlags import path
- Fix broken intra-doc links in the non-async build
- Clarify KeyCode::Space is distinct from Char(' ')
- Revamp READMEs and point at uncurses.org
- Document Display for Key emits structural spelling
- Observe events after reads and add async_screen
- Add uncurses agent skill
- Uniform pure-read contract, opt-in observe, trim internals
- Show surface width methods
- Note Screen is Send + Sync
- Add image sources for dark and light themes in README
- Replace website links with usage sections
- Reword name origin, drop em dashes
- Add website hints to readmes
- Document inline click mapping
- Rewrite intro, add example GIFs, size inline quickstart
- Use alternate screen in the quickstart examples
- Wait for a keypress in the quickstart examples
- Unwrap example GIFs from anchor links
- Update image sources in README.md
- Link all README badges to their targets
- Update images in README with new picture tags
Features
- Import terminal rendering library source
- Expose scroll region ops on SurfaceMut
- Implement ratatui Backend over Screen
- Port ratatui examples to the uncurses backend
- Add space starfield demos
- Add Windows poll backend and unify wait via Poller
- Drop inline viewport support
- Support color scheme update notifications (DEC 2031)
- Add five demo examples
- Move cursor to last row at the start of reset
- Add blink and rapid_blink builders
- Add tour demo showcasing styles and hyperlinks
- Add modal and modal_inline demos
- Detect Windows Terminal for iTerm2 inline images
- Tee output from Screen::flush
- Track default colors and kitty keyboard flags
- Auto-populate Key::text for printable Char codes
- Add cursor_pad scratch-pad example
- Canonicalize key event representation across decoders
- Canonicalize Key Display output
- Parse Key and KeyCode from string
- Add KeyCode::function checked constructor
- Tighten Key string syntax to a single separator
- Display PageUp/PageDown/Escape in full
- Accept
pgdownas PageDown alias - Name minus/equals/plus in Display and accept aliases
- Add Key::matches and Key::matches_any
- Make Unicode backend opt-in via features
- Size-required constructors, config builders, present()
- Add read_matching and try_read_matching to the event source
- Add query module for terminal request/reply helpers
- Add composable Terminal device handle
- Suspend and resume keylog and screen_toggle
- Add async EventStream behind the async feature
- Convert file_explorer to async EventStream and tokio
- Add Style::write and Style::write_styled
- Support fds beyond FD_SETSIZE in the Darwin select backend
- Add in-band resize (DEC 2048) support
- Add EventSource resize-delivery toggle for in-band mode
- Add cursor bookkeeping helpers
- Owned-stack backend with inline viewport support
- Add read_clipboard query
- Add Display, styled(), and StyledText for Style
- Implement Display for ColorScheme
- Implement Display for ModeSetting
- Add from_terminal constructor
- Add string and grapheme width helpers
- Add a god-Screen facade over terminal, canvas, and input
- Add capability detection, terminal modes, and options
- Add async events, text trait, and port examples
- Add hex/hsl constructors and to_hex/to_hsl conversions
- Request pixel mouse only when SGR-pixel is supported
- Accept Option in color setters and adopt across examples
- Emit OSC 8 hyperlink from write_styled when a link is set
- Add Screen::with_canvas constructor
- Add Encode trait to serialize a surface to escape sequences
- Add set_str_truncate with a styled tail indicator
- Convert Option<Style> into Style, mapping None to EMPTY
- Reset hardware tab stops on init when TABS is on
- Make insert_above self-contained
- Stage per-frame cursor and add atomic frame toggle
- Add clear_cursor_position, accept bare tuples in set_cursor_position
- Add OSC 0/1/2 title controls
- Treat an empty title as clearing the override
- Pure Screen event reads and async event streaming
- Pure backend event reads with opt-in observe
- Add pointer_shape hyperlink hover demo
- Use the uncurses symbol as the favicon
- Track inline cursor origin for mouse hit testing
- Add mouse-driven inline calculator
- Add horizontal mouse-wheel scroll to file_explorer
Miscellaneous Tasks
- Initialize workspace with uncurses and uncurses-ratatui crates
- Resolve clippy warnings and apply fmt
- Test on tier-1 platforms, the BSDs, and musl
- Test on illumos and Solaris
- Skip the ratatui adapter on VM jobs
- Install gcc on Solaris and drop DragonFly
- Trigger on main after the default branch rename
- Deploy the website to Cloudflare Pages
- Trigger on main after the default branch rename
- Record Cloudflare deploys as native GitHub deployments
- Force HTTP/1.1 for cargo downloads in the website deploy
- Upgrade website deploy actions to Node 24 majors
- Install Hugo via peaceiris/actions-hugo
- Cache Hugo modules via website/go.sum
- Add publish metadata and doc(cfg) feature badges
- Set initial release version to 0.0.1
- Sync Cargo.lock to workspace 0.0.1 version
- Ignore .wrangler build artifacts
- Publish crates and release from tags
- Use lfs for gifs
Performance
- Avoid String allocs when parsing Key tokens
Refactor
- Use uncurses stdio handles
- Use no_private to mirror no_intermediate in CSI recognizer
- Fold hyperlink into Style; remove Link type
- Make Style fields private; expose getters
- Align Style API with Rust conventions
- Factor clear primitives and fix redundant ED
- Move Capabilities into the screen module
- Switch Feature::probe to write_probe<W: Write>
- Replace Capabilities/Feature with request_* methods
- Rename kitty keyboard types and drop disable helper
- Replace width field with CellKind enum
- Remove Cell::new in favor of explicit constructors
- Rename CellKind to Kind
- Consolidate key invariants behind Key::new
- Re-canonicalize key after protocol field overrides
- Match
g/Gon resolved text - Use Key::matches for binding dispatch
- Make Key::new transparent and normalization explicit
- Drop KeyCode::BackTab in favor of Tab + SHIFT
- Mouse::new takes modifiers
- Expose fields, drop with_ prefix, rename LinkData to Link
- Use Style::default() in place of Style::EMPTY
- Expose style field, fold with_style into style builder
- Collapse with_* setters into constructors / Options structs
- Use screen.set_str instead of Painter
- Process-wide singletons with shared lock
- Bind stdin/stdout once per fn
- Process-wide singletons with shared lock
- Drop try_clone dance for tty handles
- Rename Source to EventSource
- Adopt Terminal handle with App lifecycle template
- Rename enable_raw_mode to make_raw_mode, drop disable_raw_mode
- Render() presents a complete frame
- Remove decoder parser hooks
- Replace EventSource Options with builder methods
- Make terminal queries data-based
- Make staging setters infallible
- Drop redundant attribute getters
- Move terminal requests into data-based queries
- Make frame and lifecycle staging infallible
- Inline reset/restore/insert_above staging
- Share a &self readiness poller and split source by platform
- Share the source between EventStream and sync queries
- Drop root re-exports; access types via their modules
- Unify terminal queries behind a generic Query trait
- Rename Screen render primitive to Canvas
- Drop non-render modes from Canvas
- Make set_str take a style and add wrap variants
- Simplify input source and rework the async stream
- Drive the Backend through the Screen facade
- Remove PasteBuffer in favour of raw chunk bytes
- Accept impl Into<Style> and add Style::new
- Dissolve Canvas into Screen
- Split literal TextSurface from escape-aware Painter
- Make Painter fields private
- Fold present() into render()
- Rename tracked-cursor API and add move_cursor_by
- Model DEC 2031 reports with the ColorScheme enum
- Call width_mode via method syntax in insert_above
- Emit mouse modes unconditionally, drop caps gating
- Apply inline escapes onto a per-call base style
- Symmetric opener/closer API for styles
- Flatten BasicColor into Color
- Extract grapheme segmentation from cell into a unicode module
- Shrink public API surface before v1
- Drop flattening re-exports for one canonical path
- Rename use_color_profile/use_optimizations to set_*
- Rename Env::empty/bool to new/is_truthy
- Move hash_line into a shared module
- Rename the background module to color
- Rename OutputHandle trait to Output
- Replace write_*/reset/styled with Display alternate flag
- Move benches in-crate so renderer stays private
- Model mouse tracking as MouseTracking bitflags
- Drop KittyKeyboardFlags::NONE in favor of empty()
- Drop the Screen::events async adapter
- Move grapheme_width/grapheme_cells to TextSurface
- Rename grapheme_cells to grapheme_widths
- Make Screen Send + Sync
Styling
- Consolidate terminal imports in modal
- Cargo fmt for the text module additions
- Apply rustfmt
Testing
- Align inline byte-stream expectation with leaner clear
- Cover shifted input across scripts and decoder paths
- Lock in legacy fixterms CSI u decoding
- Exhaustive cross-decoder identity coverage
- Verify ESC ESC [ Z decodes as Alt+BackTab
- Issue stream queries before delivering the reply
- Gate pipe-polling drain tests to Unix
- Skip the pty resize test where TIOCGWINSZ is unsupported
Build
- Forward unicode-rs/icu features through examples and ratatui adapter
Examples
- Demonstrate Key equality with parsed bindings
- Size inline screen to current frame
- Add async EventStream, custom-events, and neon arcade demos