Daily Tech Briefing
AI 科技速览

每天 5 分钟内学习 AI。获取最新的人工智能新闻,理解其重要性,并学习如何将其应用于您的工作。

AI 快讯
Hacker News · 2026/7/28 14:15:49
Rio-vt and librio: Rio's terminal engine, now embeddable

Rio-vt and librio: Rio's terminal engine, now embeddable

AI 中文解读
核心亮点:Rio终端把核心引擎拆成两个可嵌入的组件,让开发者不用重复造轮子,就能轻松给自家应用加上终端功能。 通俗解读:以前想做个带终端界面的软件,开发者得从零开始写一堆复杂代码,就像想开餐厅得先自己种菜、养猪。现在Rio把“后厨”打包好了,一个叫rio-vt的版本给懂Rust的开发者直接用,另一个叫librio的版本则像万能插座,任何编程语言都能插上。这相当于把整套成熟的终端技术——包括命令解析、屏幕显示、文字搜索、图片支持——都做成了标准零件,谁需要谁拿。 实际影响:对普通用户来说,这意味着未来会有更多好用的终端类应用出现,比如更智能的代码编辑器、更流畅的服务器管理工具,甚至手机上的终端模拟器。因为开发者省下了最难的底层开发时间,就能把精力放在打磨界面和功能上,最终我们能用上更顺手、更稳定的工具,而且这类应用的价格也可能更亲民。
rio-vt and librio: Rio's terminal engine, now embeddableJuly 27, 2026 · 7 min readRaphael AmorimAccidentally built a terminalHey folks! For a while now Rio's terminal core has been tangled up with its renderer, its config, and the app around it. That made it hard for anyone (including me) to reuse the parts that took years to get right: the VT state machine, the grid, scrollback, selection, search, and the image protocols. With Rio 0.5 that changes. The engine is now split into clean, embeddable layers, and I want to walk you through them: rio-vt and librio. Two layers​ The idea is simple. Most projects that want a terminal don't want a whole terminal app, they want the engine. So the engine now ships as two layers you can pick from: rio-vt is a safe Rust crate. The VT state machine, ANSI/escape parser, grid with scrollback, selection, search, PTY driver, and the sixel / Kitty / iTerm2 image protocols. No rendering, no GPU, no font shaping. If you write Rust, you depend on this directly. Think of it as a modern alternative to alacritty_terminal. librio is the same core behind a C ABI, in the spirit of libghostty. If you're writing Swift, C, Go, Python, or anything that speaks C, you link this: it ships as a prebuilt static library, no Rust toolchain required. All the unsafe lives here and rio-vt itself stays safe Rust. Both are lean by default. Building rio-vt with no features pulls in no renderer, GPU, or font-shaping dependencies, it's just the terminal. rio-vt in practice​ The core is driven the way a real terminal is: feed it bytes, then pull the grid state back out. Here's the whole loop, no PTY, no renderer, no threads: use rio_vt::ansi::CursorShape;use rio_vt::crosswords::grid::Dimensions;use rio_vt::crosswords::pos::Column;use rio_vt::crosswords::{Crosswords, CrosswordsSize};use rio_vt::event::{VoidListener, WindowId};use rio_vt::performer::handler::Processor;// An 80x24 terminal with 10k lines of scrollback.let size = CrosswordsSize::new(80, 24);let cols = size.columns();let mut term = Crosswords::new( size, CursorShape::Block, VoidListener, WindowId::from(0), 0, 10_000,);// Feed raw PTY bytes: SGR red "hello", reset, then " world".let mut parser = Processor::default();parser.advance(&mut term, b"\x1b[31mhello\x1b[0m world");// Pull the visible grid and read the first row.let rows = term.visible_rows();let line: String = (0..cols).map(|x| rows[0][Column(x)].c()).collect();assert!(line.starts_with("hello world")); Since rio-vt never draws anything, you decide what happens with the grid: pair it with any renderer, or none at all. Selection and search come for free​ use rio_vt::crosswords::pos::{Column, Line, Pos, Side};use rio_vt::selection::{Selection, SelectionType};let mut selection = Selection::new( SelectionType::Simple, Pos::new(Line(0), Column(0)), Side::Left,);selection.update(Pos::new(Line(0), Column(4)), Side::Right);term.selection = Some(selection);assert_eq!(term.selection_to_string().as_deref(), Some("hello")); // columns 0..=4 Images, too​ Sixel, Kitty, and iTerm2 image transmissions are decoded by the core and surfaced through an event, so a frontend records them the way it records anything else. Here's a Kitty graphics-protocol transmission captured headless: impl EventListener for ImageSink { fn event(&self) -> (Option<RioEvent>, bool) { (None, false) } fn send_event(&self, event: RioEvent, _: WindowId) { if let RioEvent::UpdateGraphics { queues, .. } = event { for (id, g) in &queues.pending_images { // id, g.width, g.height, g.pixels (RGBA) ... } } }}// f=32 RGBA, 2x2 px, a=T transmit+display, base64 pixels:parser.advance(&mut term, b"\x1b_Gf=32,s=2,v=2,a=T;/wAA//8AAP//AAD//wAA/w==\x1b\\");// -> kitty image: id=..., 2x2px, 16 rgba bytes librio: the same core, from any language​ librio wraps that engine in a small C ABI: create an engine, create a surface (which spawns a PTY under the hood), write to it, and pull a render state that tel
分享
阅读原文