{"id":47300592,"url":"https://github.com/ratatui/mousefood","last_synced_at":"2026-04-01T21:53:56.716Z","repository":{"id":283058148,"uuid":"950531141","full_name":"ratatui/mousefood","owner":"ratatui","description":"embedded-graphics backend for Ratatui","archived":false,"fork":false,"pushed_at":"2026-03-30T21:00:36.000Z","size":7517,"stargazers_count":1211,"open_issues_count":25,"forks_count":39,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-03-31T06:43:13.583Z","etag":null,"topics":["embedded-graphics","ratatui","rust","tui"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ratatui.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["j-g00da","ratatui"],"buy_me_a_coffee":"j.g00da"}},"created_at":"2025-03-18T10:00:47.000Z","updated_at":"2026-03-30T21:00:35.000Z","dependencies_parsed_at":"2026-03-31T06:01:14.408Z","dependency_job_id":null,"html_url":"https://github.com/ratatui/mousefood","commit_stats":null,"previous_names":["j-g00da/mousefood","ratatui/mousefood"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/ratatui/mousefood","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ratatui%2Fmousefood","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ratatui%2Fmousefood/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ratatui%2Fmousefood/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ratatui%2Fmousefood/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ratatui","download_url":"https://codeload.github.com/ratatui/mousefood/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ratatui%2Fmousefood/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292619,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["embedded-graphics","ratatui","rust","tui"],"created_at":"2026-03-17T01:38:19.994Z","updated_at":"2026-04-01T21:53:56.694Z","avatar_url":"https://github.com/ratatui.png","language":"Rust","funding_links":["https://github.com/sponsors/j-g00da","https://github.com/sponsors/ratatui","https://buymeacoffee.com/j.g00da"],"categories":["Rust"],"sub_categories":[],"readme":"# ![Mousefood](https://github.com/ratatui/mousefood/blob/599f1026d37c8d6308a6df64a234dbefaedc0c6f/assets/logo/mousefood.svg?raw=true)\n\n[![Crate](https://img.shields.io/crates/v/mousefood?logo=rust\u0026style=flat-square\u0026color=ebe94f)](https://crates.io/crates/mousefood)\n[![Docs](https://img.shields.io/docsrs/mousefood?logo=rust\u0026style=flat-square)](https://docs.rs/mousefood)\n[![CI](https://img.shields.io/github/actions/workflow/status/ratatui/mousefood/ci.yml?style=flat-square\u0026logo=github)](https://github.com/ratatui/mousefood/blob/main/.github/workflows/ci.yml)\n[![Deps](https://deps.rs/crate/mousefood/latest/status.svg?style=flat-square)](https://deps.rs/crate/mousefood)\n\n**Mousefood** - a no-std\n[embedded-graphics](https://crates.io/crates/embedded-graphics) backend\nfor [Ratatui](https://crates.io/crates/ratatui)!\n\n\u003cdiv align=\"center\"\u003e\n\n![demo](https://github.com/ratatui/mousefood/blob/599f1026d37c8d6308a6df64a234dbefaedc0c6f/assets/demo.jpg?raw=true)\n![animated demo](https://github.com/ratatui/mousefood/blob/599f1026d37c8d6308a6df64a234dbefaedc0c6f/assets/demo.gif?raw=true)\n\n\u003c/div\u003e\n\n## Quickstart\n\nAdd mousefood as a dependency:\n\n```shell\ncargo add mousefood\n```\n\nExemplary setup:\n\n```rust\nuse mousefood::embedded_graphics::{mock_display::MockDisplay, pixelcolor::Rgb888};\nuse mousefood::prelude::*;\nuse ratatui::widgets::{Block, Paragraph};\nuse ratatui::{Frame, Terminal};\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // replace this with your display driver\n    // e.g. ILI9341, ST7735, SSD1306, etc.\n    let mut display = MockDisplay::\u003cRgb888\u003e::new();\n\n    let backend = EmbeddedBackend::new(\u0026mut display, EmbeddedBackendConfig::default());\n    let mut terminal = Terminal::new(backend)?;\n\n    terminal.draw(draw)?;\n    Ok(())\n}\n\nfn draw(frame: \u0026mut Frame) {\n    let block = Block::bordered().title(\"Mousefood\");\n    let paragraph = Paragraph::new(\"Hello from Mousefood!\").block(block);\n    frame.render_widget(paragraph, frame.area());\n}\n```\n\n### Special characters\n\nEmbedded-graphics includes bitmap fonts that have a very limited\nset of characters to save space (ASCII, ISO 8859 or JIS X0201).\nThis makes it impossible to draw most of Ratatui's widgets,\nwhich heavily use box-drawing glyphs, Braille,\nand other special characters.\n\nMousefood by default uses [`embedded-graphics-unicodefonts`](https://crates.io/crates/embedded-graphics-unicodefonts),\nwhich provides embedded-graphics fonts with a much larger set of characters.\n\n#### Alternatives\n\nIn order to save space and [speed up rendering](#performance-and-hardware-support),\nthe `fonts` feature can be disabled by turning off the default crate features.\n[`ibm437`](https://crates.io/crates/ibm437) is a good alternative that includes\nsome drawing characters, but is not as large as embedded-graphics-unicodefonts.\n\n### Bold and italic fonts\n\nBold and italic modifiers are supported, but this requires providing fonts\nthrough `EmbeddedBackendConfig`.\nIf only regular font is provided, it serves as a fallback.\nAll fonts must be of the same size.\n\n```rust\nuse mousefood::embedded_graphics::{mock_display::MockDisplay, pixelcolor::Rgb888};\nuse mousefood::{EmbeddedBackend, EmbeddedBackendConfig, fonts};\nuse ratatui::Terminal;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut display = MockDisplay::\u003cRgb888\u003e::new();\n    let config = EmbeddedBackendConfig {\n        font_regular: fonts::MONO_6X13,\n        font_bold: Some(fonts::MONO_6X13_BOLD),\n        font_italic: Some(fonts::MONO_6X13_ITALIC),\n        ..Default::default()\n    };\n    let backend = EmbeddedBackend::new(\u0026mut display, config);\n    let _terminal = Terminal::new(backend)?;\n    Ok(())\n}\n```\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg alt=\"Bold and Italic fonts\"\n     src=\"https://github.com/ratatui/mousefood/blob/6640da9402794ea8f9370e0dc2b4bd1ebf2c6356/assets/bold_italic.png?raw=true\"\n     style=\"max-width: 640px\"/\u003e\n\u003c/div\u003e\n\n### Color theme\n\nColors can be remapped using `color_theme` on `EmbeddedBackendConfig`.\nBy default the ANSI palette is used.\n\n```rust\nuse mousefood::{ColorTheme, EmbeddedBackend, EmbeddedBackendConfig};\nuse mousefood::embedded_graphics::{mock_display::MockDisplay, pixelcolor::Rgb888};\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut display = MockDisplay::\u003cRgb888\u003e::new();\n    let theme = ColorTheme {\n        background: Rgb888::new(5, 5, 5),\n        foreground: Rgb888::new(240, 240, 240),\n        yellow: Rgb888::new(255, 200, 0),\n        ..ColorTheme::ansi()\n    };\n\n    let config = EmbeddedBackendConfig {\n        color_theme: theme,\n        ..Default::default()\n    };\n    let backend = EmbeddedBackend::new(\u0026mut display, config);\n    Ok(())\n}\n```\n\n#### Built-in themes\n\nMousefood includes popular color themes that can be used directly:\n\n- `ColorTheme::ansi()` - Standard ANSI colors (default)\n- `ColorTheme::tokyo_night()` - Tokyo Night dark theme with blue/purple tones\n\n### Cursor and blink\n\nMousefood supports configurable cursor styles and text blinking.\n\nThe cursor style can be set to `Inverse` (default), `Underline`, `Outline`, or `Japanese`.\nInverse mode requires the `framebuffer` feature and falls back to underline without it.\n\n```rust,ignore\nlet config = EmbeddedBackendConfig {\n    cursor: CursorConfig {\n        style: CursorStyle::Japanese,\n        blink: true,\n        color: Rgb888::WHITE,\n\n    },\n    ..Default::default()\n};\n```\n\nText blink modifiers (`SLOW_BLINK`, `RAPID_BLINK`) and cursor blinking are\nbehind the `blink` feature flag to avoid unnecessary computation and memory\nusage when not needed:\n\n```toml\n[dependencies]\nmousefood = { version = \"*\", features = [\"blink\"] }\n```\n\nBlink timing is configurable:\n\n```rust,ignore\nlet config = EmbeddedBackendConfig {\n    #[cfg(feature = \"blink\")]\n    blink: BlinkConfig {\n        fps: 30,\n        slow: BlinkTiming { blinks_per_sec: 1, duty_percent: 15 },\n        fast: BlinkTiming { blinks_per_sec: 3, duty_percent: 50 },\n    },\n    ..Default::default()\n};\n```\n\nWithout the `blink` feature, blink modifiers are silently ignored and the\ncursor is always visible.\n\n### Simulator\n\nMousefood can be run in a simulator using\n[embedded-graphics-simulator](https://crates.io/crates/embedded-graphics-simulator) crate.\n\n![GIF of a window running the simulator with a mousefood application](assets/blink.gif)\n\nRun simulator example:\n\n```shell\ngit clone https://github.com/ratatui/mousefood.git\ncd mousefood/examples/simulator\ncargo run\n```\n\nFor more details, view the [simulator example](examples/simulator).\n\n### EPD support\n\n#### WeAct Studio\n\n\u003cdiv align=\"center\"\u003e\n\n![WeAct epd demo](https://github.com/ratatui/mousefood/blob/fa70cdd46567a51895caf10c44fff4104602e880/assets/epd-weact.jpg?raw=true)\n\n\u003c/div\u003e\n\nSupport for EPD (e-ink displays) produced by WeAct Studio\n(`weact-studio-epd` driver) can be enabled using `epd-weact` feature.\n\nThis driver requires some additional configuration.\nFollow the [`weact-studio-epd`](https://docs.rs/weact-studio-epd)\ncrate docs and apply the same `flush_callback` pattern used in the [Waveshare example below](#waveshare).\n\n\u003cdetails\u003e\n  \u003csummary\u003eSetup example\u003c/summary\u003e\n\nEPD drivers include their own internal buffers, so the mousefood framebuffer\nadds memory overhead with no benefit. Disable default features to turn it off:\n\n```toml\n[dependencies]\nmousefood = { version = \"*\", default-features = false, features = [\"epd-weact\"] }\n```\n\n```rust,ignore\nuse mousefood::prelude::*;\nuse weact_studio_epd::graphics::Display290BlackWhite;\nuse weact_studio_epd::WeActStudio290BlackWhiteDriver;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Configure SPI + GPIO + delay provider for your board.\n    // let (spi_interface, busy, rst, delay) = ...;\n\n    let mut driver = WeActStudio290BlackWhiteDriver::new(spi_interface, busy, rst, delay);\n    let mut display = Display290BlackWhite::new();\n\n    driver.init()?;\n\n    let config = EmbeddedBackendConfig {\n        flush_callback: Box::new(move |d| {\n            driver.full_update(d).expect(\"epd update failed\");\n        }),\n        ..Default::default()\n    };\n\n    let backend = EmbeddedBackend::new(\u0026mut display, config);\n    let _terminal = Terminal::new(backend)?;\n    Ok(())\n}\n```\n\n\u003c/details\u003e\n\n#### Waveshare\n\nSupport for EPD (e-ink displays) produced by Waveshare Electronics\n(`epd-waveshare` driver) can be enabled using `epd-waveshare` feature.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSetup example\u003c/summary\u003e\n\nEPD drivers include their own internal buffers, so the mousefood framebuffer\nadds memory overhead with no benefit. Disable default features to turn it off:\n\n```toml\n[dependencies]\nmousefood = { version = \"*\", default-features = false, features = [\"epd-waveshare\"] }\n```\n\n```rust,ignore\nuse mousefood::prelude::*;\nuse epd_waveshare::{epd2in9_v2::*, prelude::*};\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Configure SPI + GPIO + delay provider for your board.\n    // let (mut spi_device, busy, dc, rst, mut delay) = ...;\n\n    let mut epd = Epd2in9::new(\u0026mut spi_device, busy, dc, rst, \u0026mut delay, None)?;\n    let mut display = Display2in9::default();\n\n    let config = EmbeddedBackendConfig {\n        flush_callback: Box::new(move |d| {\n            epd.update_and_display_frame(\u0026mut spi_device, d.buffer(), \u0026mut delay)\n                .expect(\"epd update failed\");\n        }),\n        ..Default::default()\n    };\n\n    let backend = EmbeddedBackend::new(\u0026mut display, config);\n    let _terminal = Terminal::new(backend)?;\n    Ok(())\n}\n```\n\n\u003c/details\u003e\n\nSee the full embedded example at [`examples/epd-waveshare-demo`](https://github.com/ratatui/mousefood/tree/main/examples/epd-waveshare-demo).\n\n#### Lilygo T5 e-paper\n\nSupport for the lilygo T5 e-paper produced by Lilygo with an esp32s3 and the EDO47TC1 panel driver.\n(`lilygo-epd47` driver) can be enabled using `lilygo-epd47` feature.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSetup example\u003c/summary\u003e\n\nThe lilygo-epd47 driver include its own internal buffers, so the mousefood framebuffer\nadds memory overhead with no benefit. Disable default features to turn it off:\n\n```toml\n[dependencies]\nmousefood = { version = \"*\", default-features = false, features = [\"lilygo-epd47\"] }\n```\n\n```rust,ignore\nuse mousefood::prelude::*;\n\n#[main]\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Setup all that is required for your board and get the peripherals.\n    // let peripherals = ...;\n\n    let mut display = Display::new(\n        pin_config!(peripherals),\n        peripherals.DMA_CH0,\n        peripherals.LCD_CAM,\n        peripherals.RMT,\n    )?;\n\n    let theme = ColorTheme {\n        background: Rgb888::WHITE,\n        foreground: Rgb888::BLACK,\n        ..ColorTheme::ansi()\n    };\n\n    // setup mousefood\n    let backend = EmbeddedBackendConfig {\n        color_theme: theme,\n        font_regular: mousefood::fonts::mono_10x20_atlas(),\n        flush_callback: Box::new(move |display: \u0026mut Display| {\n            display\n                .flush(DrawMode::BlackOnWhite)\n                .expect(\"to flush to the display\")\n        }),\n        ..Default::default()\n    };\n\n    let backend = EmbeddedBackend::new(\u0026mut display, backend);\n    let _terminal = Terminal::new(backend)?;\n    Ok(())\n}\n```\n\n\u003c/details\u003e\n\nSee the full embedded example at [`examples/lilygo-epd47-demo`](https://github.com/ratatui/mousefood/tree/main/examples/lilygo-epd47-demo).\n\n## Performance and hardware support\n\nFlash memory on most embedded devices is very limited. Additionally,\nto achieve high frame rate when using the `fonts` feature,\nit is recommended to use `opt-level = 3`,\nwhich can make the resulting binary even larger.\n\nMousefood is hardware-agnostic.\nSuccessfully tested on:\n\n### Microcontrollers\n\n- ESP32 (Xtensa)\n- ESP32-S3 (Xtensa)\n- ESP32-C6 (RISC-V)\n- STM32\n- RP2040\n- RP2350\n\n### Display drivers\n\nFor every driver, the list of displays is not exhaustive.\n\n- [ssd1306](https://crates.io/crates/ssd1306) for SSD1306\n- [mipidsi](https://crates.io/crates/mipidsi) for ILI9341, ST7735, etc.\n- [epd-waveshare](https://crates.io/crates/epd-waveshare) for e-paper displays from Waveshare\n  (requires enabling `epd-waveshare` feature)\n- [weact-studio-epd](https://crates.io/crates/weact-studio-epd) for e-paper displays\n  from WeAct Studio (requires enabling `epd-weact` feature)\n- [lilygo-epd47](https://crates.io/crates/lilygo-epd47) for the Lilygo T5 e-paper\n  from Lilygo (requires enabling `lilygo-epd47` feature)\n\nSend a pull request to add your microcontroller or display driver here!\n\n## Docs\n\nFull API docs are available on [docs.rs](https://docs.rs/mousefood).\n\n## Contributing\n\nAll contributions are welcome!\n\nBefore opening a pull request, please read the [contributing guidelines](./CONTRIBUTING.md).\n\n## Built with Mousefood\n\nHere are some projects built using Mousefood:\n\n- [AirSniffer](https://github.com/nebelgrau77/airsniffer-esp32c6) - Get information about your indoor\n  climate at a glance.\n- [Tuitar](https://github.com/orhun/tuitar) - A portable guitar training tool.\n- [Mnyaoo32](https://github.com/intuis/mnyaoo32) - An eccentric way to consume IRC messages using ESP32.\n- [Phone-OS](https://github.com/Julien-cpsn/Phone-OS) - A modern phone OS for ESP32 CYD.\n\nSend a pull request to add your project here!\n\n## License\n\n[![License MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square\u0026color=8d97b3)](LICENSE-MIT)\n[![License Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square\u0026color=8d97b3)](LICENSE-APACHE)\n\nMousefood is dual-licensed under\n[Apache 2.0](LICENSE-APACHE) and [MIT](LICENSE-MIT) terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fratatui%2Fmousefood","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fratatui%2Fmousefood","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fratatui%2Fmousefood/lists"}