NAME
AppCUI-rs — AppCUI is a fast, cross-platform console and text-based user interface (CUI/TUI) framework for Rust. It combines a…
SYNOPSIS
INFO
DESCRIPTION
AppCUI is a fast, cross-platform console and text-based user interface (CUI/TUI) framework for Rust. It combines a low-level console engine for input (mouse, keyboard, clipboard, etc.), colors, and rendering with a high-level, rich toolkit of widgets such as windows, menus, buttons, checkboxes, and many more, available for Windows, Linux and Mac.
README
AppCUI-rs
⯈ 𝗔𝗽𝗽𝗖𝗨𝗜-𝗿𝘀 🖳
AppCUI-rs is a fast, cross-platform Rust library for building modern, text-based user interfaces (TUIs) with rich widgets, themes, and full Unicode support—an alternative to ncurses and other terminal UI frameworks.
✨ Features
- multiple out-of-the-box controls (buttons, labels, text boxes, check boxes, radio buttons, list views, tree views, combo boxes, date/time pickers, color pickers, tabs, accordeons, etc.). A full list of controls can be found here
- powerful layout system that allows you to position controls using absolute coordinates, relative coordinates, docking, alignment, anchors or pivot positioning (see more here)
- menus and toolbars
- multi-platform support (Windows via API and virtual terminal, Linux via ncurses, MacOS via termios)
- multi-threading support to allow background tasks
- timers
- mouse support
- clipboard support
- color themes
- support for Unicode characters
- predefined dialogs (message box, input box, color picker, save & open dialogs, folder navigator, etc)
- true colors support (24 bits per pixel) for terminals that supports it.
📸 Screenshots
👉 Check out the Gallery for full demos of all controls!
🖥️ Backends
AppCUI supports various backends based on the operating system it is being used for:
- Windows Console - based on Win32 low level API, design for clasical windows console
- Windows VT - based on ANSI sequances, designed for modern windows virtual terminals
- NCurses - based on NCurses API for linux envinronments
- Termios - based on ANSI sequances and low level APIs for MAC OSX
- Web Terminal - designed for Web implementation (based on webgl)
- CrossTerm - based on the
crosstermcrate, but enabled via a feature flag
More on the supported backends can be found here
🚀 Quick Start
Add the following to your Cargo.toml:
[dependencies]
appcui = "*"
Then create a new Rust project and add the following code:
use appcui::prelude::*;
fn main() -> Result<(), appcui::system::Error> { let mut app = App::new().build()?; let mut win = Window::new( "Test", LayoutBuilder::new().alignment(Alignment::Center).width(30).height(9).build(), window::Flags::Sizeable, ); win.add(Label::new( "Hello World !", LayoutBuilder::new().alignment(Alignment::Center).width(13).height(1).build(), )); app.add_window(win); app.run(); Ok(()) }
or a more compact version using proc-macros:
use appcui::prelude::*;
fn main() -> Result<(), appcui::system::Error> { let mut app = App::new().build()?; let mut win = window!("Test,a:c,w:30,h:9"); win.add(label!("'Hello World !',a:c,w:13,h:1")); app.add_window(win); app.run(); Ok(()) }
Then run the project with cargo run. You should see a window with the title Test and the text Hello World ! in the center.
🧪 Examples
AppCUI-rs comes with a set of examples to help you get started. You can find them in the examples folder, including:
- Games such as Tic Tac Toe, Snake, Flappy Bird, Minesweeper, Ram it, PacMan, Chees, Connect Four, 2048 or Tetris
- Utilities such as Calculator, CSV Viewer, Temperature Converter or a Timer
- Animations such as Matrix, Fractals or Spiral
- Controls/Widgets such as Button, CheckBox, ComboBox, DatePicker, ListView, TreeView and many more.
- Dialogs such as Notification or Input
🛠️ A more complex example
Am example that creates a window with a button that when pressed increases a counter.
use appcui::prelude::*;// Create a window that handles button events and has a counter #[Window(events = ButtonEvents)] struct CounterWindow { counter: i32 }
impl CounterWindow { fn new() -> Self { let mut w = Self { // set up the window title and position base: window!("'Counter window',a:c,w:30,h:5"), // initial counter is 1 counter: 1
}; // add a single button with the caption "1" (like the counter) w.add(button!("'1',d:b,w:20")); w } } impl ButtonEvents for CounterWindow { // When the button is pressed, this function will be called // with the handle of the button that was pressed // Since we only have one button, we don't need to store its handle // in the struct, as we will receive the handle via the on_pressed method fn on_pressed(&mut self, handle: Handle<Button>) -> EventProcessStatus { // increase the counter self.counter += 1; // create a text that containe the new counter let text = format!("{}",self.counter); // aquire a mutable reference to the button using its handle if let Some(button) = self.control_mut(handle) { // set the caption of the button to th new text button.set_caption(&text); } // Tell the AppCUI framework that we have processed this event // This allows AppCUI to repaint the button EventProcessStatus::Processed } }
fn main() -> Result<(), appcui::system::Error> { // create a new application let mut a = App::new().build()?; // add a new window (of type CounterWindow) to the application a.add_window(CounterWindow::new()); // Run AppCUI framework (this wil start the window loop and messaage passing) a.run(); Ok(()) }
🛣️ Roadmap
- Basic set of widgets and support for Windows, Linux and MacOS
- WebGL support
- OpenGL / SDL / Vulkan support
- TextArea support for code highlighting
🤝 Contributing
Contributions, issues, and feature requests are welcome!
Check out CONTRIBUTING.md to get started.
Join the discussion in GitHub Discussions.