Add a 6-cell mini-gauge at the right edge of the cursor row that
shows the cursor file's size as a fraction of the largest file
in the current directory. Uses block characters (filled/empty)
in the accent colour over the cursor background. Only renders
for non-directory entries on the active panel, so directories
and the '..' parent entry skip the gauge.
This gives an instant visual sense of relative file sizes
without needing to read the numeric size column.
Tests: 1388 pass, zero warnings.
Show the free-space percentage next to the disk indicator dot
so the user can quickly assess remaining capacity without doing
mental math from the size string.
Tests: 1388 pass, zero warnings.
Add a bright accent-coloured 1-column bar on the inner left edge
of the active panel. This is a premium TUI pattern (also used by
bottom, lazygit, btop) that gives a much clearer visual focus
indicator than a border colour change alone.
The bar uses the same active_border_color as the panel border so
it stays thematically consistent. The panel inner content shifts
right by one column to accommodate the bar without losing content.
Tests: 1388 pass, zero warnings.
When a critical operation fails (chmod/chown/rmdir/view), the status
line pulses its background between status_bg and theme.error for 400ms.
This gives the user immediate visual confirmation that something went
wrong, even if the message text is short or they aren't looking at
the status bar.
- StatusLine::set_error() — sets message + triggers flash
- StatusLine::error_flash_progress() — remaining fraction (0.0..=1.0)
- blend_bg() — RGB linear interpolation between two Color values
- rgb() — named-color → RGB tuple for interpolation
Wired into 4 critical error paths in dialog_ops.rs (chmod, chown,
rmdir, view). Other transient messages continue to use set_message().
Tests: 1388 pass (was 1384), zero warnings.
MC parity audit found 4 semantic bugs in dispatch_ctrl_x_followup:
l -> Link (hard link, was Cmd::Symlink)
s -> Symlink (absolute symlink, was Cmd::SymlinkRelative)
v -> SymlinkRelative (relative symlink, was Cmd::SymlinkEdit)
Added 2 ctrl+letter chord entries:
ctrl-s -> SymlinkEdit (edit symlink)
ctrl-p -> InsertOtherPath (insert other panel path)
Added 3 chord aliases for MC-compatibility:
p -> InsertCurPath (MC's PutCurrentPath)
r -> InsertCurFile (MC's PutCurrentLink)
ctrl-d, ctrl-s, ctrl-p handled via modifier check
Tests: 1381 pass, zero warnings.
Add 'Charset: UTF-8' to the editor status bar (TLC is UTF-8 native).
Upgrade status bar from a single-styled Span to a multi-segment Line
with per-segment accent colours so the status reads at a glance:
- modified flag: warning colour (bold)
- filename: accent colour
- position (Ln/Col): info colour
- tab/charset/eol labels: dim shadow colour
- mode tag: warning colour
Tests: 1381 pass, zero warnings.
Spawn file operations on background threads and show the existing
ProgressDialog (gauge, sparkline, ETA, cancel button) while the
operation runs. The event loop polls the result channel every frame
and applies the outcome when the thread finishes.
- DialogState::Progress variant added
- PendingProgressOp tracks kind/sources/destination/result channel
- spawn_op_with_progress() spawns thread + shows modal progress
- tick_progress() polls channel, handles Ok/Err/Empty/Disconnected
- ProgressDialog Cancel key (Enter) cancels the OpHandle
- Tab toggles focus on the cancel button
- Wired into app.rs event loop (re-render every tick while running)
Tests: 1381 pass, zero warnings.
W1: Fix 3 dead dialogs (DisplayBits/VfsSettings/LearnKeys) that could never close
- Capture handle_key() return value, close on Cancel/Confirm
W2: Implement Cmd::Suspend with actual SIGTSTP via kill -TSTP 4035172
- Add want_suspend field, ExternalAction::Suspend variant
- Drop TUI, send SIGTSTP, recreate TUI on resume
W3: Wire Connection dialog to Panel::navigate_to_vfs()
- Parse VFS URL, look up backend, redirect active panel
- Store Encoding dialog selection on FileManager.display_encoding
W4: Wire CK_EditUserMenu (EditorCmd::EditUserMenu)
- Opens user menu storage_path in editor via Editor::open()
- Fix unreachable!() in SaveBeforeClose prompt rendering
W5: Add ErrorOutcome::SkipAll variant + Shift-S keybinding
- Fix misleading doc comment about non-existent 'All' variants
- Add SkipAll button in error dialog render
Also: Fix all 41 compiler warnings (unused imports/vars, missing docs on
public API, remove dead SPECIAL_LABELS constant, remove unused viewer_bold)
1381 tests pass, zero warnings.
The getty binary opens a PTY via /scheme/pty during startup. Adding an
explicit requires_weak on 00_ptyd.service avoids races where getty runs
before the pseudo-terminal daemon is fully ready, which could delay or
prevent the login prompt from appearing.
G1: Error dialog Retry now re-invokes the stored file operation (copy/move/
delete) using the PendingErrorOp parameters. Previously Retry just logged
'Retry not yet wired'. Copy/move/delete error paths now create a
PendingErrorOp + ErrorDialog instead of silently setting a status message.
Skip/Ignore/Abort outcomes produce appropriate status messages.
G2: SftpVfs::open_write now returns a working SftpWriter that buffers writes
and flushes to the remote SFTP server via session.write(). Previously
returned VfsError::Unsupported. The SftpWriter buffers in memory and
writes on flush/drop, matching the existing open_read buffer pattern.
1369 tests pass (default and --features sftp).
- relibc: variadic sem_open and local fork path deps
- base: already at latest RedBear-OS submodule/base
- bootloader/kernel/libredox/userutils: pushed local path-dep fixes
- installer/redoxfs: diverged from remote submodule/*; local commits saved,
divergence to be resolved after build
- driver-manager: add syscall path dependency
- AGENTS.md: document +rb build metadata and no-patches-for-local-forks rule
- remove dead patch symlinks from recipes/core/relibc (path-source local fork)
F1: Remove stale 'Phase N' / 'not yet wired' comments from vfs/local.rs,
vfs/traits.rs, editor/usermenu.rs — the functionality they described as
future work is already implemented.
F2: Replace placeholder stubs in viewer/hex.rs and viewer/text.rs with actual
rendering for Chunked sources (files >= 1 MiB). hex.rs reads viewport-sized
chunks via read_at(); text.rs reads up to 64 MiB cap for line offset mapping.
check_growing() in viewer/mod.rs also reads Chunked content instead of
returning empty Vec.
F3: Editor Settings dialog now shows actual toggle state (auto-indent,
word-wrap, show-whitespace, save-on-quit) instead of '(TBD)' placeholder.
F4: Add xz2 crate dependency and TarKind::Xz decompression support.
Feature-gated as 'xz2' (optional, follows bzip2 pattern). Uses
XzDecoder::new_multi_decoder for multi-stream .tar.xz files.
1369 tests pass. Default build (without optional features) verified.
- Update AGENTS.md single-repo rule to explicitly forbid creating any new
Gitea repositories and to require deleting per-component repos.
- Change version suffix policy from pre-release -rb to build-metadata +rb
in AGENTS.md, sync-versions.sh, apply-rb-suffix.sh, verify-fork-versions.sh.
- Update migration instructions to push to existing submodule/<component>
branches inside RedBear-OS, not create new repos.
- Update BUILD-SYSTEM-IMPROVEMENTS.md and SLEEP-IMPLEMENTATION-PLAN.md to
reference submodule/* branches instead of defunct per-component repos.
- Fix delete-per-component-repos.sh example to use a real historical repo.
SpellChecker with ~300 common English words + programming terms.
Word tokenizer handles apostrophes, digits, underscores.
Editor integration: toggle_spell_check(), find_next_misspelled().
MC uses libaspell; TLC embeds dictionary for zero external deps.
17 new tests: check_word, check_line, case insensitive, editor
integration (toggle, find_next, disabled, correct text).
Mirrors MC's panel.c:4080-4197 mouse handling. Wraps the
Tui screen in termion's MouseTerminal (enables GPM on Linux /
xterm mouse on others — without it mouse events never reach
ratatui). The translate_mouse function maps termion MouseEvent
to a MouseAction enum that the FileManager dispatches as
cursor moves / entries / scroll (deferring HistoryPrev/Next/
List and ToggleHidden which need dedicated Cmds not yet in
the keymap).
New APIs:
- terminal::event::translate_mouse(event, panel_top,
panel_height, panel_width) -> MouseAction
- terminal::event::MouseAction (Click, DoubleClick,
ScrollUp/Down, HistoryPrev/Next/List, ToggleHidden,
Unhandled)
- FileManager::handle_mouse_event(m, size) routes
MouseAction to existing cursor_up_n / cursor_down_n /
Panel::enter / Panel::set_cursor helpers.
- app.rs routes TermEvent::Mouse through handle_mouse_event
before the keyboard-dispatch path.
Tests (9 new in terminal::event::mouse_tests):
- click_on_file_row_emits_click_action
- click_below_panel_is_unhandled
- click_on_header_history_prev_button (col 1)
- click_on_header_history_next_button (col width-2)
- click_on_header_toggle_hidden_button (col width-6)
- scroll_up_emits_scroll_up
- scroll_down_emits_scroll_down
- click_on_column_name_row_is_unhandled (sort-by-column
not yet wired)
- click_respects_panel_top_offset (panel_top parameter
works for menu-bar offset)
1345 passing (was 1336; +9 new).
Mirrors MC's src/learn.c::learn_keys (mc/source/src/learn.c:393-422).
MC shows a grid of buttons; TLC is simpler: scrollable list of
captured keys with their resolved Cmd.
New file: src/filemanager/learn_keys_dialog.rs (LearnKeysDialog,
CapturedKey, 6 unit tests).
New DialogState::LearnKeys variant wired into dispatch, render,
is_finished, title. Keymap is stored at construction so the
dispatcher doesn't thread it through every key event.
Tests: 1336 passing (was 1330; +6 new).
Mirrors MC's boxes.c::configure_vfs_box
(mc/source/src/filemanager/boxes.c:1120-1198). MC's dialog has
VFS timeout plus FTP options (anonymous password, directory
cache timeout, proxy host, passive mode); TLC has no FTP/SFTP in
the active build, so we expose the relevant 1-field subset:
- Timeout for freeing VFSs (sec): 0..=10000, default 10
(out-of-range falls back to 10 — matches MC's
boxes.c:1193-1194 validation)
New file: src/filemanager/vfs_settings_dialog.rs
- VfsSettings struct (free_timeout: u32)
- parse_timeout() (handles negative as 0, > 10000 as None)
- VfsSettingsDialog with Edit-keyed text input
- 12 unit tests
New DialogState variant:
DialogState::VfsSettings(Box<VfsSettingsDialog>)
Wired into dispatch, render, is_finished, title.
Tests: 1330 passing (was 1318; +12 new).
Mirrors MC's boxes.c::display_bits_box
(mc/source/src/filemanager/boxes.c:955-1004). MC exposes 4 modes
(UTF-8, Full 8 bits, ISO 8859-1, 7 bits); TLC is UTF-8 throughout
so we expose the relevant 3-state subset:
- Full 8 bits: bytes pass through verbatim
- 7 bits: high bit stripped (parity-stripped serial consoles)
- UTF-8 (validated): pass through UTF-8, ? for invalid
New file: src/filemanager/display_bits_dialog.rs
- DisplayBits enum with 3 variants
- DisplayBitsDialog (radio-list, mirrors SortDialog)
- from_config() / map_byte() / is_valid_utf8() helpers
- 12 unit tests
New DialogState variant:
DialogState::DisplayBits(Box<DisplayBitsDialog>)
Wired into dispatch (handle_key), render, is_finished (false;
the dispatcher captures Confirm/Cancel from handle_key), title.
Tests: 1318 passing (was 1306; +12 new).
Co-Authored-By: Claude <noreply@anthropic.com>
Mirrors MC's filegui.c::file_progress_real_query_replace and the
FileProgressStatus enum (filegui.h:45-54): FILE_CONT, FILE_RETRY,
FILE_SKIP, FILE_ABORT, FILE_IGNORE.
New file: src/filemanager/error_dialog.rs
- ErrorDialog with path + error message
- R / S / I / A shortcuts (MC letter bindings)
- Esc maps to Abort
- 7 unit tests (one per shortcut + an 'other keys don't finish' guard)
New FileManager state:
- pending_error_op: Option<PendingErrorOp>
stores kind + sources + dst + flags for the in-flight op so
the user can Retry / Skip / Ignore / Abort
- PendingErrorOp struct (parallel to existing PendingFileOp)
- pending_error_op initialized to None
New DialogState variant:
DialogState::Error(Box<error_dialog::ErrorDialog>)
Wired into dispatch (handle_key), render, is_finished, title.
Retry is currently a stub (logs a message) because the copy
engine's batch step resumption would require threading the
operation index into copy_many/move_many/delete_many. The dialog
scaffolding is complete and tested; the retry can be wired in a
follow-up sprint when the batch step API is added.
Tests: 1306 passing (was 1299; +7 new).
Adds regression tests for Sprint 3 items that were verified
already-done during recon but had no dedicated test coverage:
- viewer::tests::hex_edit_apply_nibble_at_eof_is_safe_noop
Locks in the C8 contract: apply_nibble at cursor past EOF
is a safe no-op (no panic, no spurious modified flag).
- viewer::tests::move_cursor_clamps_to_size
Locks in the C8 cursor bounds invariant at move_cursor
level: positive deltas clamp to file size, negative deltas
clamp to 0 with no underflow.
- filemanager::panel::tests::history_dedups_consecutive_entries
Locks in the C11 contract: refreshing the same directory
N times grows the history by 1 entry (consecutive dedup),
not N.
- filemanager::panel::tests::sort_field_mtime_round_trips_through_config
Locks in the C12 contract: 'mtime' and 'time' config
strings both resolve to the Mtime sort field, and the
Panel reports the human-readable name 'Mtime'.
Tests (4 new, total 1299 passing):
+hex_edit_apply_nibble_at_eof_is_safe_noop
+move_cursor_clamps_to_size
+history_dedups_consecutive_entries
+sort_field_mtime_round_trips_through_config