Non-blocking dialogs and interactive programs#28
Merged
Conversation
Port the upstream fixes that ruf4 actually exercises: - xterm mouse decoding + macOS touchpad horizontal scroll (#819, #794): new parse_xterm_mouse, Point::as_array, #[repr(C)] on Point/Size/Rect, InputMouse.drag field. - clippy `as *mut _` -> `.cast()` (#730) across tui, stdext. - stdext: loongarch64 feature gate; memset .cast() refactor. - lsh: language-id `_`->`-`; doc wording. Skip fixes that target tui machinery ruf4 bypasses (no-op buffer.paste stub, own scroll handling): #818 multi-line paste, #812 modal scroll, #810 redirected-stdin, #835 localization. Preserve the two local TUI patches (InputKey visibility, Ctrl+Space remap; pub mod tables). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Long operations no longer block the UI. A single Job runs on a worker thread (crates/ruf4/src/job.rs), communicating with the UI thread via channels plus an atomic cancel flag; it never touches State, the terminal, or the arena. The pure fileops primitives are reused. - Dialog::Progress shows a gauge, N/M files, bytes, and Esc=Cancel. - Copy/move pre-scan the source tree for accurate totals and copy per-file so a large copy stays cancellable. - The per-file overwrite prompt is preserved via a worker<->UI handshake (NeedOverwrite -> Decision), reusing the overwrite dialog. - Commands spawn with piped stdout/stderr drained on reader threads to avoid pipe-buffer deadlock; cancel kills the child. - main.rs polls the job and uses a 50ms read timeout while one runs; no tui/sys changes needed. Tests: worker-level (delete/copy/move/overwrite skip+replace/command) and State-level (delete flow spawns a job, completes, refreshes panel). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scan_dir(path, show_hidden) -> Vec<FileEntry> performs only filesystem and platform calls, so it can run on a worker thread. refresh() now calls it then sorts and clamps the cursor. Behaviour is unchanged; this is the reusable enumeration primitive for off-thread directory scans. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Five hand-synced match tables collapse to single sources of truth: - KEY_NAMES drives both key_display_name and parse_key_name. - action_meta is one exhaustive match for an action's settings string and its label; action_str/action_label read from it. - parse_action is derived from action_str over ALL_ACTIONS, so the string<->action directions cannot drift. Removes the "added a variant, forgot to update table N" bug class. Round-trip tests (tests/test_action.rs) lock every action and key name, and check that ALL_ACTIONS covers the default bindings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy/move/overwrite now run entirely through the background job, so the synchronous resume machinery is unreachable. Drop continue_copy_move and execute_file_op, collapse handle_overwrite_dialog to the job handshake, and trim the now-vestigial pending/errors fields from Dialog::ConfirmOverwrite. Panel::navigate_to(path) replaces the repeated "path = ...; cursor = 0; scroll_offset = 0; refresh()" sequence at the three navigation sites (choose_root, dir history, cd). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both the command line and the text-input dialogs duplicated the same
char-index cursor arithmetic (insert / backspace / delete / left / right
/ home / end). Extract a TextField { text, cursor } helper that owns that
logic; both handlers now select the target field and delegate. Behaviour
is unchanged (command-line backspace still falls through at the start of
the line). New tests cover mid-string insert/delete and cursor motion for
both the command line and a dialog field.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The preview already rendered a scrollbar and clamped preview_scroll, but nothing drove it. Route a wheel event over the quick view (the inactive side while quick view is on) to preview_scroll; the file list keeps the wheel on its own side. Reset preview_scroll to 0 when the previewed file changes so the offset does not leak between files. Tests cover wheel-over-preview scrolling, wheel-over-file-list leaving the preview untouched, and the reset on file change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Backgrounding commands with piped stdout/stderr left the TUI holding the terminal in raw mode, so a REPL or full-screen program (python, vim, less, ssh) could never receive keystrokes. Capturing output and interactivity are mutually exclusive without a pty, so switch to the foreground model used by mc/FAR: suspend the TUI, run the command with the real terminal inherited, then resume. - sys (unix + windows): add suspend()/resume() to toggle cooked/raw terminal modes; factor the unix raw-termios computation out of switch_modes so resume reuses it. - platform::run_interactive: leave the alternate screen, suspend, run `sh -c`/`cmd /C` with inherited stdio in cwd, wait for Enter so output stays readable, resume, re-enter the alternate screen, and inject a resize to force a full repaint. execute_command now calls it. - Remove the now-obsolete captured-output machinery: JobKind::Command and its worker, Dialog::ShellOutput, last_output, and the F12/LastOutput action. Output scrolls the real terminal instead. Verified via a pty harness: a command reading stdin receives interactive input (`read line; echo GOT-$line` echoes the typed text) and the return prompt appears. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Running a command leaves and re-enters the alternate screen. The framebuffer's incremental diff then compared the new frame against the identical pre-command frame and emitted nothing, so the panels stayed blank until the next content change (e.g. F5) forced a redraw. flip() only forced a full redraw on a size change. Add Framebuffer::request_full_redraw()/Tui::request_full_redraw() to force the next frame to re-emit unconditionally. execute_command sets a repaint request after run_interactive; the main loop consumes it before render. Tested: framebuffer unit test (unchanged frame is quiet, is re-emitted after request_full_redraw, flag is one-shot) and a pty check that the panels repaint after a command with no further keypress. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.