docs(rewrite): status update
This commit is contained in:
1 parent
7b408257c4
commit
0b31fd81e8
4 files changed
+175
-1
No files matched your search
@@ -22,7 +22,8 @@ Legend: ⬜ todo · 🟨 in progress · ✅ done (gate passed, committed) · ⚠
|
||||
| A0 | apprt contract types | sonnet | ✅ | |
|
||||
| G1 | apprt-gtk (GTK4/libadwaita app) | sonnet | 🟨 | against CoreApp/CoreSurface traits |
|
||||
| T3 | terminal: Terminal + stream_readonly + StringMap | sonnet | 🟨 | |
|
||||
| F2 | font: run.zig, SharedGridSet, config integration, terminal shaper tests | sonnet | 🟨 | |
|
||||
| F2 | font: run.zig, SharedGridSet, config integration, terminal shaper tests | sonnet | ✅ | |
|
||||
| K1 | terminal: kitty graphics image/storage/unicode/render/exec | sonnet | 🟨 | |
|
||||
|
||||
## Log
|
||||
- 2026-10-11: Phase 0 complete; Phase 1 launched.
|
||||
@@ -31,3 +32,4 @@ Legend: ⬜ todo · 🟨 in progress · ✅ done (gate passed, committed) · ⚠
|
||||
- 2026-10-11: termio IO1 + font F1 committed. T1 partial (snapshot reflow, head-walking pins) → Codex round 2 in worktree. T2, R1 launched.
|
||||
- 2026-10-11: cli, apprt contract, renderer base committed. G1 (GTK) launched.
|
||||
- 2026-10-11: Screen committed. T3, F2 launched.
|
||||
- 2026-10-11: F2 committed; K1 launched.
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
## F3: dialogs + config object (class/{dialog,config,config_errors_dialog,close_confirmation_dialog,clipboard_confirmation_dialog,title_dialog,debug_warning}.rs)
|
||||
|
||||
Libadwaita >= 1.5 is assumed, so `Dialog` is always an `adw::AlertDialog` subclass (no `MessageDialog` fallback) and DebugWarning uses the `adw::Banner` (1.3) template; the clipboard dialog always uses the 1.4 template (remember switch). GType names, property names, signals and template children match the Zig classes.
|
||||
|
||||
Public API (all `&self` methods on `glib::wrapper!` types; signals via `connect_*`):
|
||||
- `config::Config` (GhosttyConfig; props `diagnostics-buffer`, `has-diagnostics` -> generated getters `diagnostics_buffer() -> Option<gtk::TextBuffer>`, `has_diagnostics() -> bool`): `new(&CoreConfig)` (clones), `from_arc(Arc<CoreConfig>)`, `new_default()`, `get() -> Arc<CoreConfig>`, `get_mut(|&mut CoreConfig| ..)` (Arc::make_mut), `clone_config() -> CoreConfig`. Test `ghostty_config` ported.
|
||||
- `dialog::Dialog` (GhosttyDialog, parent adw::AlertDialog): `present(Option<&impl IsA<Widget>>)`, `close()` (force_close); subclass via `DialogImpl: AdwAlertDialogImpl` (unsafe `IsSubclassable` impl, SAFETY-commented). Override `response` through `AdwAlertDialogImpl`.
|
||||
- `config_errors_dialog::ConfigErrorsDialog`: `new(&Config)`, prop `config`, `present(Option<&W>)`, `close()`, `connect_reload_config(Fn(&Self))`.
|
||||
- `close_confirmation_dialog::{CloseConfirmationDialog, Target{App,Tab,Window,Surface}}`: `new(Target)`, prop `target`, `present(Option<&W>)` (sets heading/body), `close()`, `connect_close_request(Fn(&Self))`, `connect_cancel(Fn(&Self))`. `Target::title()/body()` use ghostty_os::i18n::tr.
|
||||
- `clipboard_confirmation_dialog::{ClipboardConfirmationDialog, ClipboardRequestBoxed(pub ClipboardRequest)}`: `new()`, props `request` (boxed, nullable), `clipboard-contents` (TextBuffer), `blur`, `can-remember` (generated getters/setters: `set_request(Option<ClipboardRequestBoxed>)`, `set_clipboard_contents(Option<TextBuffer>)`, `set_blur(bool)`, `set_can_remember(bool)`), helpers `set_request_value(ClipboardRequest)`, `get_request() -> Option<ClipboardRequest>`, `get_clipboard_contents()`, `present(Option<&W>)`, `connect_confirm(Fn(&Self, remember: bool))`, `connect_deny(Fn(&Self, bool))`.
|
||||
- `title_dialog::{TitleDialog, Target{Surface,Tab}}` (parent adw::AlertDialog directly, as in Zig): `new(Target, Option<&str>)`, props `target`, `initial-value`, `present(&W)` (anchors to ancestor adw::ApplicationWindow/Window, async `choose`), `connect_set(Fn(&Self, &str))`.
|
||||
- `debug_warning::DebugWarning`: `new()`.
|
||||
|
||||
Status: all type-check and are clippy-clean; runtime (template instantiation, notify callbacks) NOT yet exercised because the crate did not fully compile when F3 finished. Also added `#![allow(clippy::unwrap_used)]` to build.rs.
|
||||
|
||||
## F4: overlays, child-exited banner, scrolled window, css (done)
|
||||
|
||||
Files: `src/css.rs`, `src/class/{resize_overlay,key_state_overlay,search_overlay,surface_child_exited,surface_scrolled_window}.rs`.
|
||||
Verified in an isolated scratch crate (compiles, clippy -D warnings, instantiated on a live display with no GTK criticals).
|
||||
All GType names match Zig (note `GhostttySurfaceScrolledWindow` keeps Zig's 3-t typo); templates from the bundled gresource.
|
||||
|
||||
- `ResizeOverlay` (`GhosttyResizeOverlay`): props `duration`(u32, 750), `first-delay`(250), `label`(Option<String>), `overlay-halign/valign`. API: `new()`, `set_label(Option<&str>)`, `label()`, `schedule()`.
|
||||
- `KeyStateOverlay`: props `tables`/`sequence` are **GStrv (`Vec<String>`)** instead of `ext.StringList`; read-only `has-tables`/`has-sequence`; `valign-target`. API: `set_tables(Vec<String>)`, `set_sequence(Vec<String>)`.
|
||||
- `SearchOverlay`: props `active` (rw), `search-total`/`search-selected` (u64 ro), `has-search-total/selected`, `halign-target`, `valign-target`. API: `set_search_total(Option<usize>)`, `set_search_selected(Option<usize>)`, `set_search_contents(&str)`, `grab_focus_entry()` (Zig `grabFocus`; renamed to avoid clashing with `Widget::grab_focus`), `set_active(bool)`, `connect_{stop_search,search_changed(Fn(&Self, Option<String>)),next_match,previous_match}`.
|
||||
- `SurfaceChildExited`: prop `data` (boxed `ChildExitedBoxed`), signal `close-request`. API: `set_child_exited(Option<&ChildExited>)`, `connect_close_request`. The Zig Noop variant (adw < 1.3) is omitted (crate requires adw 1.5).
|
||||
- `SurfaceScrolledWindow`: `SurfaceScrolledWindow::new(Option<&impl IsA<Widget>>)`, props `surface` (typed `GtkWidget`, accepts the `Surface` class), `config` (typed `GObject`; the scrollbar-policy closure downcasts to `class::config::Config` and calls `.get().scrollbar` - needs `Config::get() -> impl Deref<Target = ghostty_config::config::Config>`). Binds `surface.config` -> own `config`, so Surface must expose a `config` property holding a `class::config::Config`.
|
||||
- `css::CssProviders`: `new(&Display)` (installs runtime provider at APPLICATION+3), `load_all(&Config)`, `load_runtime`, `load_custom` (gtk-custom-css, 5MB limit, USER priority), `set_color_scheme(dark)` (sets `prefers-color-scheme` on providers, GTK >= 4.20, dynamic property). `css::runtime_css(&Config, gtk_416) -> String` is pure and tested. Static style*.css come from the gresource: the Application must set `resource_base_path` = `/com/mitchellh/ghostty` so AdwApplication loads them automatically.
|
||||
- Template signal handlers receive the emitter (not the template) in gtk-rs, so shared handlers locate the overlay with `ancestor()`.
|
||||
- build.rs fix: blueprint `.ui` files are bundled with `alias="<ver>/<name>.ui"` so resource paths are `/com/mitchellh/ghostty/ui/<ver>/<name>.ui` (previously doubled `ui/ui/`).
|
||||
|
||||
## F1: utilities, key, ipc (files: key, gtk_version, adw_version, weak_ref, ext/*, gsettings, cgroup, flatpak, pre_exec, post_fork, ipc/*)
|
||||
|
||||
Ported (Zig -> Rust): key.zig -> key.rs (`accel_from_trigger`, `xdg_shortcut_from_trigger`, `label_from_trigger` return `Option<String>`; `translate_mods`, `keyval_unicode_unshifted(&Widget, &gdk::KeyEvent, keycode) -> u32`,
|
||||
`event_mods(&gdk::Event, Key, ModifierType, Action, winproto_event_mods: impl FnOnce(Option<&gdk::Device>, ModifierType)->Mods) -> Mods`, `key_from_keyval(u32)`, `keyval_from_key(Key)`; 132-entry KEYMAP).
|
||||
gtk_version/adw_version -> `get_runtime_version() -> (u32,u32,u32)`, `at_least/runtime_at_least/runtime_until`, `log_version`, adw `supports_*`. "Comptime" version is the cargo feature level (4.14 / 1.5).
|
||||
weak_ref.zig -> thin `WeakRef<T>` over `glib::WeakRef`. ext -> `ext::actions::{Action, add, add_to_map, add_as_group}`, `ext::StringList` (glib Boxed `GhosttyStringList`), `get_ancestor`, `g_value_holds` (boxedCopy/boxedFree/listFind not needed).
|
||||
gsettings -> `get_bool/get_int/get_string(Key)`. cgroup -> `fmt_scope(pid)`, `create_scope(&gio::DBusConnection, pid, Options)`. flatpak -> `resources_dir()`.
|
||||
pre_exec/post_fork -> `PreExecInfo::new(&Config)`/`pre_exec(&info) -> Option<u8>`; `PostForkInfo::new(&Config)`/`post_fork(&info, Option<pid>) -> Result<(), PostForkError>` (uses `gio::Application::default()` dbus connection; ghostty-termio's Command also has its own copy of the cgroup wait loop).
|
||||
ipc -> `ipc::perform_ipc(&Target, &Action) -> Result<bool, ipc::Error>` (org.gtk.Actions.Activate, `new-window` / `new-window-command`), `ipc::dbus::DBus`.
|
||||
|
||||
Tests: Zig ported 11 (key 3, gtk_version 2, adw_version 1, weak_ref 1, gsettings 4 (the comptime ones became 2), ext/actions 2, ext/slice 3); extra 8. The ext/actions GTK-display test and adw test are skipped at runtime when GTK cannot init (not main thread / no display).
|
||||
Deviations: only unsafe is `FromGlib` for `gdk::Key` in key.rs (annotated). `many keycode` media keys remain a TODO as upstream.
|
||||
|
||||
## winproto (F2) — src/winproto/{mod,noop,x11,wayland}.rs
|
||||
|
||||
Ported winproto.zig, noop.zig, x11.zig, wayland.zig. Deps added: gdk4-x11 (x11, xlib; Xlib via its re-exported dlopen `x11` = x11-dl), gdk4-wayland (wayland_crate), wayland-client/-backend(client_system)/-protocols(client,staging)/-protocols-plasma(client).
|
||||
|
||||
### Public API (consumed by class/window.rs, class/application.rs)
|
||||
```rust
|
||||
pub trait WindowHost { // implemented by window.rs using a *weak* ref to the Window gobject
|
||||
fn gtk_window(&self) -> Option<gtk::Window>; // as(gtk.Window)/Native
|
||||
fn is_quick_terminal(&self) -> bool;
|
||||
fn window_decoration(&self) -> ghostty_config::types_b::WindowDecoration;
|
||||
fn config(&self) -> Option<Arc<Config>>; // getConfig()?.get()
|
||||
}
|
||||
pub enum App { None(noop::App), Wayland(wayland::App), X11(x11::App) }
|
||||
App::init(&gdk::Display, app_id:&str, &Config) -> Result<App> // wayland, then x11, else None
|
||||
App::protocol() -> Protocol; App::event_mods(Option<&gdk::Device>, gdk::ModifierType) -> Mods // falls back to crate::key::translate_mods
|
||||
App::supports_quick_terminal() -> bool
|
||||
App::init_quick_terminal(&mut self, >k::Window) -> Result<()> // call BEFORE the window is realized (layer-shell init)
|
||||
pub enum Window { None, Wayland, X11 }
|
||||
Window::init(&App, Rc<dyn WindowHost>) -> Result<Window> // window must be realized (needs gdk::Surface)
|
||||
Window::{resize_event, sync_appearance, set_urgent(bool)}(&mut self) -> Result<()>
|
||||
Window::client_side_decoration_enabled(&self) -> bool
|
||||
Window::add_subprocess_env(&mut self, &mut Vec<(String,String)>) -> Result<()> // X11: WINDOWID
|
||||
```
|
||||
Zig `deinit` = `Drop` (Wayland releases blur/decoration/slide/token objects, disconnects enter-monitor).
|
||||
`noop::Window::update_config_event` (unused in Zig union) was not ported.
|
||||
|
||||
### Behaviour notes / deviations
|
||||
* Wayland uses gdk4-wayland's shared `wayland_client::Connection` (no unsafe). We keep a private event queue; blocking roundtrips at init; while an xdg-activation token is outstanding a 50 ms glib timeout dispatches the queue. KDE blur / server-decoration / slide / xdg-activation implemented; xdg_wm_dialog_v1 presence + layer-shell < 1.0.4 check ported. Registry changes after init (global_remove) are not tracked.
|
||||
* Quick terminal via `gtk4-layer-shell` crate (`LayerShell` trait). Upstream requires libgtk4-layer-shell to be loaded before libwayland-client; Rust link order is not controllable, so the final binary should link it first or run with `LD_PRELOAD=libgtk4-layer-shell.so` (else `is_supported()` is false and the quick terminal is disabled).
|
||||
* X11: Xlib (dlopen'd via x11-dl) for XGet/Change/DeleteWindowProperty, XEventsQueued/XPeekEvent; `XkbQueryExtension`/`XkbSelectEventDetails` declared in a small `extern "C"` block (`#[link(name="X11")]`). `unsafe` is confined to x11.rs (`#![allow(unsafe_code)]`, SAFETY comments).
|
||||
* Tests: Zig has none for winproto; 2 added (noop defaults, X11 property struct layouts). Not runtime-tested on a live X11/Wayland compositor in this fork.
|
||||
* Depends on `crate::key::translate_mods(gdk::ModifierType) -> Mods` (F1).
|
||||
|
||||
## Application / App / GlobalShortcuts / demo (F8)
|
||||
|
||||
Files: `src/app.rs` (App.zig), `src/class/application.rs` (application.zig),
|
||||
`src/class/global_shortcuts.rs` (global_shortcuts.zig), `src/gl.rs` (GL proc loader),
|
||||
`examples/demo.rs`.
|
||||
|
||||
### Public API
|
||||
* `app::App { pub app: Application }`: `App::new(Rc<dyn CoreApp>)`, `run()` (-> `Result<(), RunError>`),
|
||||
`terminate()`, `wakeup()`, `perform_action(Target<SurfaceId>, Action) -> bool`,
|
||||
`App::perform_ipc(&ipc::Target, &ipc::Action)` (static). `app::waker() -> Arc<dyn Waker>`
|
||||
(thread-safe, `MainContext::wakeup`) - create it before the core app and give it to core.
|
||||
`app::MUST_DRAW_FROM_APP_THREAD = true`.
|
||||
* `class::application::Application` (GType `GhosttyApplication`, extends `AdwApplication`, property `config`
|
||||
(read-only `Config` object, notify on change)):
|
||||
`Application::default()`, `new(core_app)`, `core() -> Rc<dyn CoreApp>`, `rt() -> Rc<dyn RtApp>`,
|
||||
`get_config() -> class::config::Config` (object), `core_config() -> Arc<ghostty_config::Config>`,
|
||||
`winproto() -> Ref<winproto::App>` / `winproto_mut()`, `saved_language()`, `surfaces() -> Vec<Surface>`,
|
||||
`perform_action(...)`, `new_window(parent: Option<&Surface>, WindowOverrides)`, `quit()`, `wakeup()`,
|
||||
`run_loop()`, `deinit()`. `AppRt` is the `RtApp` impl (forwards to the default app; main thread only).
|
||||
* The giant action switch is `Application::perform_action`. Surface targets are resolved with
|
||||
`Surface::from_id(id)` (F5); actions use the Zig mechanisms (`activate_action("tab.close"/"win.close"/
|
||||
"split-tree.*")`, `ancestor::<SplitTree/Window/Tab>`). `inspector` actions go to `Surface::control_inspector`
|
||||
(inspector deferred; no-op). Unimplemented actions (`secure_input`, `close_all_windows`, ...) log + return false.
|
||||
* Startup mirrors Zig: log writer funnel (`glib::log_set_writer_func` -> `log`), version logging, `Config::load`
|
||||
(errors become a diagnostic), LANG/`language`, i18n, `GDK_DEBUG`/`GDK_DISABLE` env (`set_gtk_env`), `adw::init`,
|
||||
single-instance flag, app-id (`class`), winproto init (noop fallback), CSS via `css::CssProviders`,
|
||||
`setlocale(LC_ALL,"")` (`init_locale`, closes the INTEGRATION_TODO item for locale), style-manager <-> core color scheme
|
||||
sync (`color_scheme_event` + each `CoreSurface::color_scheme_callback`), `app.*` GActions
|
||||
(`new-window`, `new-window-command` (`as`: `-e`, `--command=`, `--working-directory=`, `--title=`), `open-config`,
|
||||
`present-surface` (u64 surface id), `quit`, `reload-config`), accelerator sync, config errors dialog, quit timer,
|
||||
`run_loop` (own `MainContext` iteration + `CoreApp::tick` + quit conditions), `quit()` with close confirmation dialog.
|
||||
* `SIGUSR2` reload: glib-rs has no `g_unix_signal_add`; a helper thread (`signal-hook`) hops to the main context.
|
||||
* Global shortcuts: portal `CreateSession`/`BindShortcuts` over gio D-Bus (deprecated `signal_subscribe` allowed);
|
||||
`GlobalShortcuts` signal `trigger(String)` carries the action in keybind syntax; `connect_trigger` parses it.
|
||||
* `gl::proc_address(name)`: dlsym on libepoxy (works for EGL and GLX); use as the loader for glow /
|
||||
`ghostty-renderer::prepare_context`.
|
||||
|
||||
### Changes to `core.rs` (trait spec)
|
||||
Added `AppMessage::NewWindow`, `CoreSurface::color_scheme_callback`, `CoreSurface::update_config`;
|
||||
`CoreApp::perform_all_action` takes a `ghostty_input::binding::Action` (as in Zig).
|
||||
|
||||
### Demo
|
||||
`cargo run -p ghostty-apprt-gtk --example demo` (env: `DEMO_QUIT_AFTER_MS`, `DEMO_CONFIRM=1`). Dummy core:
|
||||
keybindings from the user config drive window/tab/split/palette actions; `draw_frame` clears with `background`.
|
||||
|
||||
### Known gaps
|
||||
* `toggle_visibility`/`float_window`/`secure_input`/`close_all_windows` etc.: unimplemented like upstream.
|
||||
* Open URL uses `xdg-open` (OpenURI portal is a TODO upstream too).
|
||||
* `async-backend` (libxev) is meaningless in Rust and ignored.
|
||||
@@ -9,3 +9,7 @@
|
||||
6. **Resize reflow / no-reflow fewer rows** must drop trailing blank rows, including rows holding only bg-color cells (Zig `resizeCols`/`resizeWithoutReflow`). Three Screen tests are `#[ignore = "pagelist: ..."]`:
|
||||
`screen_resize_no_reflow_less_rows_trims_blank_lines`, `screen_resize_less_cols_with_reflow_but_row_space`, `screen_resize_less_cols_to_wrap_wide_char`.
|
||||
7. `PageList::reset` and `erase_rows` return `Result`; `erase_rows` with an empty history start point returns `InvalidCoordinate` (Zig would assert). Screen guards/ignores.
|
||||
- (T3/p4) **`erase_row_bounded` must reset row flags on the blanked row**: after rotating, the final row is cleared with `Page::clear_cells`, which leaves `row.hyperlink`/`styled`/`grapheme` set. Zig's row is left with the flags cleared (test `Terminal: index bottom of scroll region clear hyperlinks` expects `!row.hyperlink`; ignored as `terminal_index_bottom_of_scroll_region_clear_hyperlinks`).
|
||||
- (T3/p8) **Reflow to fewer cols with a pending-wrap cursor**: 4x2 screen printed "0123", `resize(2,2)` with reflow gives screen contents "01\n23" but the active area/viewport dump is only "23" (active top is one row too low; Zig yields "01\n23"). Ignored test: `terminal_resize_with_wraparound_on`.
|
||||
- (T3/p1) **`Page::set_graphemes` / `Page::append_grapheme` must not mark the row dirty** (Zig `Page.appendGrapheme` leaves dirty untouched; callers like `Terminal.print` mark dirty explicitly). Terminal works around it for the zero-width path (test `terminal_ignored_vs16_doesnt_mark_dirty`).
|
||||
- (T3/terminal) `PageList::clone_partial_row_between(src_pin, dst_pin, left, right)`: Terminal `insert_lines`/`delete_lines` need Zig's `Page.clonePartialRowFrom` between two different page nodes of one list (needs two page borrows). `terminal.rs::clone_partial_row_between` re-implements it via `export_cell`/`import_cell` (now `pub(crate)` use) plus the row-metadata merge from `Page::clone_partial_row_from`.
|
||||
@@ -0,0 +1,42 @@
|
||||
# ghostty-terminal: Terminal, stream_readonly, StringMap
|
||||
|
||||
## Ported
|
||||
| Zig | Rust | tests |
|
||||
|---|---|---|
|
||||
| Terminal.zig | `terminal.rs` (+ `terminal/tests/p1..p8.rs`, helpers in `tests/mod.rs`) | 372 of 372 (370 pass, 2 `#[ignore = "pagelist: ..."]`) |
|
||||
| stream_readonly.zig | `stream_readonly.rs` | 33 of 33 |
|
||||
| StringMap.zig | `string_map.rs` (uses the `onig` crate; `ghostty-config` is a dev-dependency for the URL regex tests; `Screen`'s stand-in `StringMap` is now a re-export) | 3 of 3 |
|
||||
|
||||
Ignored tests (PageList gaps, see `ghostty-terminal-pagelist-requests.md`):
|
||||
`terminal_index_bottom_of_scroll_region_clear_hyperlinks` (erase_row_bounded keeps the row hyperlink flag) and
|
||||
`terminal_resize_with_wraparound_on` (reflow to fewer cols loses a row in the active dump).
|
||||
|
||||
Small non-test deviations: `glitch.txt` copied next to the tests (used by the glitch-text test); zero-width attach in
|
||||
`print` restores the row dirty flag because `Page::append_grapheme` marks rows dirty (Zig does not; request in the pagelist file).
|
||||
|
||||
## API overview (for termio / renderer / core)
|
||||
```rust
|
||||
use ghostty_terminal::terminal::{Terminal, Options};
|
||||
let mut t = Terminal::new(Options::new(80, 24))?; // Options{cols,rows,max_scrollback=10_000,colors,default_modes}
|
||||
{
|
||||
let mut s = t.vt_stream(); // ghostty_vt::stream::Stream<stream_readonly::Handler<'_>> (new_alloc)
|
||||
s.next_slice(b"hello\r\n\x1b[31mred\x1b[0m")?; // applies every state-changing action; queries are ignored
|
||||
} // s.handler.terminal gives &mut Terminal while the stream lives
|
||||
t.resize(100, 30)?; // Zig resize(alloc, cols, rows); primary reflows (if wraparound mode), alt does not
|
||||
t.print(cp)?; t.print_string("text\n")?; t.full_reset();
|
||||
let text = t.plain_string()?; // viewport as text (plain_string_unwrapped respects wrap)
|
||||
```
|
||||
- `t.screens` is a `ScreenSet`: `t.screen()` / `t.screen_mut()` (= `screens.active()/active_mut()`), `t.screens.active_key`, `get(Key)`.
|
||||
- Reading cells: `scr.pages.get_cell(Point::Viewport(Coordinate{x,y}))` -> `Cell` (Copy); rows/pages via `scr.pages.pin(pt)` + `pin.row_and_cell(&scr.pages)`; page data `scr.page(node)`; style of a cell `page.style(cell)`; graphemes `page.lookup_grapheme(page.cell_index(x,y)?)`.
|
||||
- Cursor: `t.screen().cursor` (x, y, pending_wrap, style, `cursor_style`, hyperlink_id, semantic_content). Selection: `screen.select(..)`, `screen.selection_string(..)` (Screen API).
|
||||
- State: `t.modes` (`ModeState`), `t.flags` (mouse_event/format, focused, `dirty` renderer flags, shell_redraws_prompt, ...), `t.colors` (DynamicRgb fg/bg/cursor + DynamicPalette), `t.scrolling_region`, `t.tabstops`, `t.pwd`/`get_pwd()`, `t.mouse_shape`, `t.status_display`, `t.width_px/height_px`.
|
||||
- Viewport: `t.scroll_viewport(ScrollViewport::{Top,Bottom,Delta(n)})`. Screen switching: `switch_screen(Key) -> Option<old Key>`, `switch_screen_mode(SwitchScreenMode::{M47,M1047,M1049}, enabled)`.
|
||||
- `print_attributes()` returns a `String` (DECRQSS SGR reply body) instead of writing into a buffer; `set_pwd(&[u8])`.
|
||||
- Termio's own handler can call the same `Terminal` methods; it should handle side-effect actions (queries, title, clipboard, bell, APC/DCS) itself and delegate the rest, mirroring `stream_readonly::Handler::vt`.
|
||||
- Tests: Zig tests that mixed `s.nextSlice` and direct `t.` calls use `feed(&mut t, bytes)` (fresh stream per call) or `t.vt_stream()` + `s.handler.terminal`.
|
||||
|
||||
## TODO(integration)
|
||||
- `Terminal::kitty_graphics(cmd)` is a stub returning `None` (Zig `kitty.graphics.execute`); `kitty_images_delete_all` (erase display complete/scroll complete) only sets `kitty_images.dirty`; kitty image storage limit on lazily-created screens uses `Options::DEFAULT`. `kitty_images.dirty = true` hooks are in place at every Zig location (index, scroll_up, insert/delete lines, switch_screen, Screen::scroll).
|
||||
- tmux control-mode viewer: not required by Terminal/stream_readonly; not ported here.
|
||||
- `clone_partial_row_between` local helper (pagelist request).
|
||||
- Oniguruma: `onig` crate lacks the retry-limit-in-search setter; only retry-limit-in-match is set.
|
||||
Reference in new issue
Block a user