After cross-referencing MC's button.c (lib/widget/button.c) and the
ratatui button pattern survey, two gaps remained in Phase 16:
1. MC defines NARROW_BUTTON ([X], no inner padding) — adds for
future compact toolbar/dialog use. Width formula: label + 2.
2. While width was already chars().count() (Unicode-safe CJK), no
test asserted this. Added explicit assertion: '日本語' Normal = 7,
Default = 9 cells.
Tests: 1111 passed (was 1109, +2).
Binaries rebuild clean.
Ref: MC lib/widget/button.c button_flags_t {NORMAL,DEFPUSH,NARROW,HIDDEN}.
Implements the three gaps from §26:
- Phase A: new platform.rs (291 lines) with runtime probes for
MSR, ACPI PSS, /proc/stat, cpufreq sysfs, hwmon — emits one
eprintln! diagnostic per source at startup
- Phase B: msr.rs reads /dev/cpu/{cpu}/msr on Linux via lseek+pread;
acpi.rs read_load falls back to /proc/stat; acpi.rs read_acpi_pss
reads /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies;
cpufreq.rs reads/writes /sys/.../scaling_governor. Removed the
hardcoded P0..P5 fallback table (violates zero-stub policy).
- Phase C: replaced misleading "MSR: not available (QEMU?)" with a
"Sources: MSR=ok PSS=no load=ok gov=ok hwmon=ok" header line
that shows per-source availability at a glance.
Verified on AMD Ryzen 9 7900X (24 threads, AMD-pstate driver):
- /dev/cpu/0/msr detected (probes ok; reads blocked by CAP_SYS_RAWIO
for non-root users — kernel-level permission, not a code issue)
- /proc/stat readable (load populated after second refresh tick)
- /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor readable
(governor shows "powersave")
- hwmon2 (k10temp) detected (not yet wired into per-CPU temp column —
requires per-driver hwmon→tempX_input mapping, deferred to v1.4)
- PSS=no (amd-pstate driver does not expose scaling_available_frequencies)
v1.3 source: 3501 LoC across 12 modules. Cross-compiled Redox binary
3.3 MB stripped, SHA256 cbc0a6d04e9d9252314dd71a1c411d4c488417e25f8d860970f718990864431a.
What is NOT yet wired (deferred to v1.4):
- Hwmon→per-CPU temp mapping (k10temp Tdie is package-level only)
- MSR reads without root (CAP_SYS_RAWIO required)
- zenpower / zen 5+ per-driver logic
- Add x11proto to redbear-full.toml package list
- libxau recipe updated with x11proto dependency and custom build script
- Fixes libxau build failure: 'Package xproto was not found'
Adds comprehensive analysis answering the user's "no per-core info"
question. Documents:
§26.1 Why every per-CPU column is empty on Linux (root cause)
- 6-column trace (Freq, PkgW, Temp, P-state, State, Flags) + Load%
- Maps Redox scheme paths to Linux equivalents (where they exist)
- Identifies that two paths already have Linux fallbacks (detect_cpus,
read_cpu_id) and four do not
§26.2 cpu-x patterns reviewed
- 6-row comparison table: missing-MSR / daemon / per-source UI /
refresh logic / CLI flags / temperature fallback
- Concludes: redbear-power's "n/a" placeholder is already better UX
than cpu-x's empty cells; daemon broker pattern is NOT applicable;
retry-cache and per-source logging ARE worth adopting
§26.3 Recommended Phase A/B/C (v1.3)
- Phase A: new platform.rs with /dev/cpu/*/msr + /proc/stat +
/sys/devices/system/cpu/cpu*/cpufreq/ fallbacks, ~80-120 LoC
- Phase B: replace hardcoded P0..P5 fallback (acpi.rs:101-108) with
real sysfs reads; generalize read_load to /proc/stat
- Phase C: header per-source availability badge
§26.4 AMD-specific concerns (separate from Linux fallback)
- msr.rs reader is Intel-only by design (file comment)
- AMD Zen uses 0xC0010063/0xC0010064 for P-states and k10temp for
temp, not Intel MSR 0x19c
- Recommended: vendor detection branch + Linux hwmon fallback
§26.5 Conclusion
- Screenshot is NOT a bug — TUI is working as designed
- Three substantive gaps: no Linux fallbacks, no per-source
startup logging, no header availability summary
- All three addressable without violating zero-stub policy
Source: cpu-x v4.7 at /tmp/cpu-x-src/ (cloned in earlier session).
All and references updated to deref the LazyLock (). 1103 tests pass.
Editor render test now reads [editor] editlinestate from the MC .ini (with cursor_fg fallback) so the cursor-line color assertion matches the actual rendering.
Viewer match-highlight test reads [viewer] viewselected from the MC .ini (with warning fallback) — the test now matches the actual highlight bg color from julia256 (yellow on cyan).
FileManager.skin_name now stores the canonical MC skin name (e.g. "julia256") rather than the user-config alias (e.g. "default-dark"). When by_name() resolves a legacy alias to a real .ini skin, the resulting theme.name is what gets persisted.
apply_skin_selection follows the same rule.
Skin dialog tests use real MC skin names (dark, nicedark) and verify the catalog contains no TLC hardcoded presets (no more "default-dark", "mc-classic", etc. in the list).
Removes every hand-coded Theme constant. julia256 is the new default; sand256 is the light fallback. All 39 bundled MC skins are now reachable by name, and legacy aliases (default-dark, mc-classic, nord, etc.) resolve to real .ini skins.
Architecture:
- DEFAULT_THEME / LIGHT_THEME are LazyLock<Theme> initialised on first use.
- parse_theme now reads ALL MC sections: core, statusbar, buttonbar, dialog, error, filehighlight, viewer.
- shadow field comes from [core] shadow (MC's gray;black pattern).
- render_drop_shadow matches MC's tty_draw_box_shadow algorithm exactly: two background-recolor rectangles (2-col right strip + 1-row bottom strip offset by 2 cols), no glyph change.
Removes redbear_tui_theme import — TLC no longer has its own palette.
Completes the remaining plan §24 deferred items:
- Config file (TOML): new config.rs module loaded from
/etc/redbear-power.toml and ~/.config/redbear-power.toml (with
--config <path> override). Sections: display, theme, keybindings,
benchmark. --help documents the full schema.
- AMD Zen CCD topology: cpuid.rs detect_hybrid now parses leaf
0x8000001E NC field (cores per CCX) and Zen 4+ leaf 0x80000026
(CCD count + cores per CCD). Linux host with 24 AMD cores now
shows CCD0..CCD5 grouping instead of all-Unknown.
- Multi-view tab system: Per-CPU / System / Info tabs via ratatui
Tabs widget. Hotkeys 1/2/3 jump directly; T cycles. System tab
shows aggregate CPU stats (avg freq, max temp, total pkg power,
aggregate flags, bench status). Info tab shows detailed CPU
identification (family/model/stepping hex, full flags list,
per-level cache hierarchy with KB+way+line size). New
render_tab_bar / render_system_panel / render_info_panel render
functions in render.rs. TabId enum added to app.rs.
- D-Bus methods: added CycleGovernor, SetGovernor(name),
ToggleThrottle, ForceMinPstate, ForceMaxPstate, SetPstate(target)
methods to org.redbear.Power. PowerCommand enum + command
channel back to main thread for MSR-bound actions. New App
methods set_governor(Governor) and set_selected_pstate(i32)
enable D-Bus clients to set governor/P-state without sending
keystrokes.
- Mouse sub-panel navigation: refined hit-test so left-click on
header/controls cycles governor, right-click toggles throttle,
middle-click on table expands P-state. Header now has two
distinct actions (governor + throttle) reachable via different
mouse buttons without per-label x hit-test.
New dependencies in Cargo.toml: toml = "0.8", dirs = "5",
serde = { version = "1", features = ["derive"] }.
Verification:
- cargo build --release (host): 0 errors.
- ./redbear-power --once: shows tab bar + Per-CPU view.
- ./redbear-power --config /tmp/rp-test/config.toml: respects
refresh_ms override (50ms minimum enforced).
- AMD CCD labels visible: '▶ CCD0' / 'CCD1' / etc.
- cook redbear-power (Redox target): 3.2 MB stripped binary at
local/recipes/system/redbear-power/target/x86_64-unknown-redox/stage/usr/bin/redbear-power.
SHA256: 58b7812a5f673e227753c01e93a05678bd9e8f28101d8a447d70d4943170c40a.
ISO rebuild status: still blocked by pre-existing upstream nix-0.30.1
vs Redox relibc SaFlags incompatibility in uutils. v1.2 binary
is staged and will be packaged into the next successful ISO build
once that issue is resolved.
Source size: 2758 LoC across 11 modules (was 2376/10 in v1.1).
Filepos DB reveals canonical paths of opened files. Use 0600 instead of default umask (0644) so other users cannot read it.
Reindent the HomeGuard struct / scoped_home function inside the #[cfg(test)] mod tests block (functionally correct, just hard to read before).
Reverts F5/F6/F8 from operating on current line (TLC extension) to MC behavior: do nothing when no selection is active. MC's eval_marks returns false when mark1==mark2, so F5/F6/F8 in MC are no-ops without a selection.
Removes the now-dead copy_line/cut_line/delete_line_no_sel helpers and their tests. Replaces with MC-parity no-op tests.
Extracts current_line_range() helper from select_current_line and duplicate_line_or_selection (also covers unindent_selection pattern). Removes ~50 lines of duplicated line-range computation.
F5 (Copy), F6 (Move/Cut), F8 (Delete) now operate on the current line when no selection is active, matching MC semantics.
New bindings:
Alt-Shift-L — select current line (incl. trailing newline)
Ctrl-Shift-D — duplicate current line or selected block
New methods on Editor: select_current_line, copy_line, cut_line, delete_line_no_sel, duplicate_line_or_selection. 6 new tests cover both with-selection and without-selection paths.
Adds P4a (Ctrl-Insert, Shift-Delete, Ctrl-N, Shift-Tab) and P4b (filepos) rows. Updates the binding table to mark them as completed. Bumps total parity estimate from ~90% to ~93%.
Adds per-file cursor position persistence (MC ~/.mc/filepos parity).
Storage: ~/.config/tlc/filepos as a tab-separated canonical-path database. Wired into editor/viewer open+close in both standalone binaries and the in-TLC file manager. CursorPos struct, save/load functions, restore_cursor_position() and save_cursor_position() methods on Editor and Viewer.
buttonbar.rs: add module-level doc to satisfy missing_docs lint.
Both binaries support MC-style +N positional: 'tlcedit +42 file.txt' opens at line 42. tlcview gains line support for the first time. main.rs updated for new open_file(file, start_line) signature.
FindOutcome::View/Edit now carry Option<u64> line number from FindHit. FileManager gains open_editor_at_line() and open_viewer_at_line() that jump to the target line after opening.
Editor gains goto_line(), viewer gains jump_to_line() + open_file(start_line). Both editor and viewer now render the F-key buttonbar at the bottom (1Help 2Save... / 1Help 2Wrap...).
Status bar now shows wall clock (HH:MM UTC) and spinner character
right-aligned. Native ratatui scrollbars added to Help, Jobs, and Find
dialogs when content overflows visible area.
Current-line highlight (bg lightened by 12 per channel on cursor line),
bracket-match tracking (forward/backward search for ()[]{}<> pairs),
modified-line gutter mark (▌ in warning color when buffer is dirty).
bracket_flash field + find_matching_forward/backward methods on Editor.
Rounded panel borders (BorderType::Rounded), native ratatui scrollbars
on file lists, alternating row colors (even rows lightened), file-size
inline bar in panel footer (█ proportional to largest file), 3D button
effect (▔ top + ▁ bottom rows when focused), and panel switch border
flash (cyan info color for 4 frames on Tab).
Blocking events.next() caused the app to hang indefinitely when the
terminal was resized without any key press — no data arrived on stdin
to wake the blocking read.
Fix: use rustix::event::poll() with 200ms timeout on stdin fd. On
timeout, check terminal size and redraw if changed. On data available,
read events as before.
Added rustix 'stdio' feature for rustix::stdio::stdin() BorrowedFd.
- Remove two dead pub fn render free functions (render.rs + mod.rs)
- Remove debug_raw_event/should_log_raw_event (always-on /tmp logging)
- Move use std::sync::Arc to top of dispatch.rs
- Fix unused imports from dead code removal
The poll-based event loop (rustix::event::poll with 200ms timeout) broke
terminal size detection on Redox. When tui.size() returned (0,0) via
unwrap_or_default() after a failed dup(1,"winsize"), the size-change
check would clear the screen and render nothing.
Ratatui's draw() already calls autoresize() on every frame, which queries
backend.size() and resizes buffers automatically. The manual size check
and poll-based wake-up were redundant and harmful.
Reverted to the original blocking-read approach that worked on Redox:
stdin.lock().events_and_raw().next() → process key → render()
Resize is detected on the next keypress via ratatui's built-in autoresize.
MC uses SIGWINCH→self-pipe→select(stdin+pipe) for resize detection.
In safe Rust (#![deny(unsafe_code)]), the equivalent is polling stdin
with a 200ms timeout via rustix::event::poll. This wakes the main loop
every 200ms even without key input, allowing terminal size check and
full redraw on resize. Same result as MC's signal-driven approach
without requiring unsafe signal handlers.
Previously the event loop blocked indefinitely on events.next() —
terminal resize was only detected on the next keypress.
- Split filemanager/mod.rs into dispatch.rs, render.rs, dialog_ops.rs,
format_utils.rs (3567→~1200 lines in mod.rs)
- Comment out mc in redbear-mini.toml and redbear-full.toml per user request
- Enable tlc in redbear-full.toml (was temporarily disabled)
- 1022 tests pass, zero behavior changes
Both open_file() functions were stubs that opened the file but never
launched the terminal interface. tlcedit/tlcview would silently exit
without displaying anything.
- editor::open_file(): create Tui, render editor, run key event loop,
handle Save/Close/SaveThenClose/DiscardThenClose results
- viewer::open_file(): create Tui, render viewer, run key event loop,
exit when handle_key returns true