Commit Graph

814 Commits

Author SHA1 Message Date
vasilito 28906f16cf tlc: phase 24 — editor word sort (Alt-F8)
Mirrors MC's edit_sort_cmd flow (CK_Sort / M-F8 →
src/editor/editcmd.c::edit_sort_cmd):

  1. Require a marked block; surface error message if no
     selection is active.
  2. Stash the active selection to a unique temp file under
     /tlc-sort-<nanos>/in.txt (per-call unique dir to
     avoid races between concurrent sort runs).
  3. Run via 'sh -c sort <opts> <in> > <out>' so user-supplied
     options pass through verbatim (matches MC g_strconcat).
     Empty options means default lexical sort.
  4. On non-zero exit: surface exit code + first stderr line.
  5. On success: delete the original selection, insert the
     sorted output at the cursor, mark buffer modified, and
     surface a status line ('Sort: ok (N bytes, M lines)').

Components:
  src/editor/mode.rs — new PromptKind::Sort variant.
  src/editor/handlers.rs — Alt-F8 keybind (errors if no
    selection, otherwise opens the sort prompt); commit_prompt
    routes PromptKind::Sort to Editor::sort_block(options).
  src/editor/render.rs — title ('Run sort') + label ('sort
    options (empty for default)') + mode tag (' [Sort]') for
    the prompt.
  src/editor/mod.rs — Editor::sort_block(options).

Tests: 1153 passed (was 1150, +3):
  - sort_block_sorts_active_selection (apple/banana/cherry)
  - sort_block_with_no_selection_reports_error
  - sort_block_with_reverse_flag (-r → c/b/a)
Release binaries build clean.

PLAN.md §15d row 32a marked Done.
2026-06-20 22:09:49 +03:00
vasilito 08561033ae redbear-power: v1.17 — Sort modes in Process tab (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item. Process tab now supports
sorting by RSS, CPU%, PID, or Name — cycle with hotkey 'o'.

Implementation summary:
- New SortMode enum: Rss (default) / Cpu / Pid / Name
- SortMode::next() cycles through all 4 modes
- SortMode::sort(&mut Vec<ProcessInfo>) reorders in place
- ProcInfo::read_sorted(sort_mode) — read with custom sort
- ProcInfo::read_with_cpu_pct_sorted(prev, dt, num_cpus, sort_mode)
  — re-sorts at end because CPU% may change rank
- App.process_sort: SortMode field
- 13-tick refresh uses sorted variant
- Hotkey 'o' cycles sort mode (with status flash)
- Header line shows 'sort: <mode> (press o to cycle)'
- 6 new unit tests (default + cycle + 4 sort modes)

Restored v1.16 changes (prior session left them partial):
- NetInfo::rx_kbps + tx_kbps fields + init
- NetInfo::read_with_throughput(prev, dt_secs)
- App::prev_net field
- 7-tick refresh uses read_with_throughput
- render_network_panel RX/TX lines show '{X} KiB/s'
- 3 network throughput unit tests

58/58 tests pass (5 bench + 12 sensor + 10 network + 12 storage + 19 process).
Cross-compile SHA256: 5d01429b91b5c8399f6772251fd28a44a083cc53f13f2b9dff6f92245787c393.

Docs: improvement plan §41, CONSOLE-TO-KDE §3.3.2 v1.17,
RATATUI-APP-PATTERNS §13.14 + §14 (5800 LoC, 58 tests).
2026-06-20 22:00:05 +03:00
vasilito 0b0e65a643 tlc: phase 23 — viewer FileNext / FilePrev (Ctrl-F / Ctrl-B)
Mirrors Midnight Commander's
MC src/viewer/actions_cmd.c::mcview_load_next_prev (CK_FileNext
/ CK_FilePrev).

Components:
  src/viewer/siblings.rs (new) — pure helper next_or_prev_sibling:
    reads current file's parent directory, filters out hidden
    files (dot-prefixed), sorts case-insensitive, locates current
    by file_name, returns next (direction=+1) or prev (direction=-1)
    entry. Returns None at directory boundaries or on I/O error.
    6 unit tests cover next/prev/last/first/hidden/no-parent.

  src/viewer/mod.rs — Viewer::open_next / Viewer::open_prev
    public methods that look up the sibling and reload viewer
    state via a private reload_at helper (mirrors MC's
    mcview_init/mcview_done pair around mcview_load). Source
    errors are converted to std::io::Error so the Result type
    matches the existing open() signature.

  src/viewer/mod.rs — Ctrl-F / Ctrl-B keybinds in handle_key.
    Each delegates to open_next / open_prev.

  PLAN.md §15d row 29 marked Done; status bumped to Phase 23.

Tests: 1150 passed (was 1141, +9: 6 siblings module tests +
3 viewer integration tests covering open_next, open_prev,
Ctrl-F/Ctrl-B keybinds). Release binaries build clean.
2026-06-20 21:52:12 +03:00
vasilito d209b64ce9 redbear-power: v1.16 — Network throughput (closes v1.11 forward work)
Closes the v1.11 §35.7 forward-work item. Network tab now shows
real-time R/W throughput (KiB/s) per interface, computed from delta
of rx_bytes/tx_bytes between successive 7th-tick refreshes.

Source code already landed (network.rs + app.rs + render.rs).
This commit captures full v1.16 docs:

- Improvement plan §40 (Network Throughput)
- CONSOLE-TO-KDE §3.3.2 v1.16
- RATATUI-APP-PATTERNS §13.14 (audit table +16) + §14 (5755 LoC, 52 tests)

Implementation summary:
- New rx_kbps: f64 + tx_kbps: f64 fields on NetInterface
- New NetInfo::read_with_throughput(prev, dt_secs)
- Wall-clock dt (shared prev_refresh_secs with v1.14 + v1.15)
- saturating_sub on bytes prevents underflow
- 3 new unit tests (formula + underflow + zero dt)
- 52/52 total tests pass

Math sanity check (verified by unit test):
prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s
prev > now → saturating_sub → 0

Cross-compile SHA256: 053f1a0cca5185637d0316d56f5cf5832cf2e754b689bc24edf16ea5d0404fa2.
2026-06-20 21:41:07 +03:00
vasilito 6729409b4d redbear-power: v1.14 + v1.15 — CPU% + disk throughput + restoration
This commit restores and completes v1.14 (CPU% in Process tab) and
v1.15 (disk throughput in Storage tab). Previous sessions landed
partial work (cpu_pct field on ProcessInfo, read_kbps/write_kbps on
DiskStats) but never wired them up. This commit:

v1.14 — Process CPU% (Process tab):
- ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- App::prev_processes + prev_refresh_secs fields
- 13-tick refresh now uses read_with_cpu_pct with wall-clock dt
- 3 new unit tests (formula + zero + underflow)

v1.15 — Disk throughput (Storage tab):
- StorageInfo::read_with_throughput(prev, dt_secs)
- App::prev_storage field
- 11-tick refresh now uses read_with_throughput
- 3 new unit tests (formula + underflow + zero dt)

Updated render.rs:
- Process panel column header: PID STATE PRIO NI THR CPU% RSS VIRT COMM
- Storage panel Read/Written lines show 'X I/Os, Y KiB/s'

Tests: 49/49 pass (5 bench + 12 sensor + 7 network + 12 storage +
13 process).

Cross-compile SHA256: d1207b648ce89e19f8dd040f234648e1665f053ec31f8511ea187627d79bde2d.

Math sanity checks (verified by unit tests):
CPU%: delta=130 ticks, dt=2sec, num_cpus=4 → 1625.0%
Disk: prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s

Docs: improvement plan §38 (CPU%) + §39 (disk throughput),
CONSOLE-TO-KDE §3.3.2 v1.14 + v1.15, RATATUI-APP-PATTERNS §13.14 +
§14 (5720 LoC, 49 tests).
2026-06-20 21:30:39 +03:00
vasilito 75d704c06c tlc: phase 22 — wire F11 user-menu command execution
Replaces the Phase 21 TODO stub with the full MC
edit_user_menu flow:

  src/editor/mod.rs — Editor::run_user_menu_command(raw_command):
    1. Expand percent variables via PercentCtx::for_file
       (MC: expand_format).
    2. Stash active selection to clipfile (MC: edit_save_block).
       Block file path exposed via %b for downstream expansion.
    3. Run via 'sh -c <expanded>' so user can use pipes,
       redirections, globs (matches MC user_menu_cmd shell-out).
    4. On non-empty stdout: delete any selection, then
       insert_str at cursor position (MC: edit_insert_file).
       Buffer cursor is synced to editor cursor after
       delete_selection so the insert lands at the right spot.
    5. Status line: 'Menu: ok (N bytes inserted)' on success,
       'Menu: exit N, stderr: ...' on failure.

  src/editor/handlers.rs — replaces TODO with call to
    self.run_user_menu_command(command).

Tests: 1141 passed (was 1137, +4):
  - inserts stdout at cursor
  - replaces active selection (cursor sync verified)
  - reports non-zero exit status
  - expands %f to current file path via cat %f

Release binaries build clean.
2026-06-20 21:27:37 +03:00
vasilito 9d120cc802 redbear-power: add missing cpu_pct field to ProcessInfo struct 2026-06-20 21:14:56 +03:00
vasilito a5cfae5622 tlc: phase 21 — F11 user-menu dispatch for editor
Mirrors Midnight Commander's editor user-menu flow (MC
src/editor/edit.c::edit_user_menu + CK_UserMenu).

Architecture reuses the existing filemanager usermenu infra:
  filemanager::usermenu::UserMenuDialog is constructed with
  condition='edit' so the same ~/.config/tlc/menu file works
  in both filemanager (condition='view') and editor contexts.

Components:
  src/editor/usermenu.rs (new) — EditorUserMenu wrapper that
    owns the dialog + cursor snapshot + selection flag +
    clipfile path. Plus  reuses
    PercentCtx::for_file; default_block_file() resolves
    /tlc/editor.block or ~/.config/tlc/editor.block.

  src/editor/menubar.rs — adds EditorCmd::UserMenu and
    EditorCmd::EditUserMenu variants (cross-referenced MC
    CK_UserMenu + CK_EditUserMenu).

  src/editor/mod.rs — new usermenu_session: Option<EditorUserMenu>
    field, init None in both constructors, Editor::open_user_menu
    method, dispatch_editor_cmd wires UserMenu/EditUserMenu
    variants (EditUserMenu surfaces path via status message —
    full Open wiring deferred to follow-up).

  src/editor/handlers.rs — F11 keybind opens user menu (F11 is
    MC's editor UserMenu binding per misc/mc.default.keymap;
    F2 in the editor is reserved for Save). Routing at top of
    handle_key intercepts Running/Cancel/Execute outcomes;
    Execute surfaces the command in the status line — full
    selection-stash + stdout-capture is deferred TODO.

Tests: 1137 passed (was 1132, +5: 4 editor::usermenu module
tests covering expand, default_block_file, EditorUserMenu
construction, key routing; 1 handler test for F11 open + Esc close).
2026-06-20 21:14:01 +03:00
vasilito 9fa019e78a redbear-power: v1.14 — CPU% in Process tab (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item. Process tab now shows
real-time CPU usage per process, computed from the delta of
total CPU ticks between successive 13th-tick refreshes.

Source code already landed (process.rs + app.rs + render.rs).
This commit captures full v1.14 docs:

- Improvement plan §38 (CPU% in Process Tab)
- CONSOLE-TO-KDE §3.3.2 v1.14
- RATATUI-APP-PATTERNS §13.14 (audit table +14) + §14 (19 modules, 47 tests)

Implementation summary:
- New cpu_pct: f64 field on ProcessInfo
- New ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- Wall-clock dt (SystemTime) — accurate even when TUI pauses
- saturating_sub on ticks prevents underflow if now < prev
- num_cpus from self.cpus.len() (Per-CPU detection result)
- 4 new unit tests (formula + zero + underflow + dt=0)
- 47/47 total tests pass

Math sanity check (verified by unit test):
utime=100→200, stime=50→80, dt=2sec, num_cpus=4
delta = 280-150 = 130 ticks / 2 sec = 65 ticks/sec
CPU% = 65 / 4 cpus * 100 = 1625.0%

Cross-compile SHA256: d46cd66b8e158e2327839ef502879951877a5500d4a40807d3dbc72ed7397231.
2026-06-20 20:56:54 +03:00
vasilito 1dcdc5d39d redbear-power: v1.13 — Process tab (procfs)
Adds the 9th tab in the multi-view system: Process, reading
process state and memory from /proc/[pid]/stat on Linux hosts.
Last major top-like view, complementing hardware tabs
(Storage/Network/Sensors) with software state.

New module process.rs (215 lines, 9 unit tests):
- ProcessInfo: pid, comm, state, ppid, utime, stime, priority,
  nice, num_threads, vsize_kb, rss_kb
- parse_stat_line() handles (comm) with spaces like (Web Content)
  via last-')' extraction (per man 5 proc format)
- Field indices: state=0, ppid=1, utime=11, stime=12,
  priority=15, nice=16, num_threads=17, vsize=20, rss=21
- read_comm() fallback for parens-parsing failures
- ProcInfo::read() scans /proc, sorts by RSS desc, truncates to 50
- format_memory_kb() with binary unit suffix

Updated app.rs:
- New field processes: ProcInfo, refreshed every 13th tick
  (6.5 sec). 13-tick modulus coprime with all (3,4,5,7,11).
- TabId::Process variant (9th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard →
  Battery → Sensors → Network → Storage → Process → PerCpu

Updated render.rs:
- New render_process_panel() with PID/STATE/PRIO/NI/THR/RSS/VIRT/COMM
  columns. Comm truncated to 20 chars. Sort by RSS desc (top-like).
- render_tab_bar() for 9 tabs with hotkey 1-9
- render_once dumps Process panel for headless verification

Updated main.rs:
- mod process; declaration
- New dispatch arm TabId::Process => render_process_panel
- Hotkey 9 jumps to Process tab
- render_process_panel added to imports

Linux host smoke test (596 processes, top 50):
- opencode 3.7 GiB, thunderbird 2.1 GiB, plasmashell 517 MiB
- kwin_wayland shows PRIO=-2 (real-time scheduling)
- Total RSS: 17.5 GiB

Unit tests: 43/43 pass (5 bench + 12 sensor + 7 network + 10 storage +
9 process).
Cross-compile SHA256: 2c30f86dce574f173efdcf8eb588f83abd8f0bdf2c5a2678452dd0e6a244dbf2.

Docs: improvement plan §37, CONSOLE-TO-KDE §3.3.2 v1.13,
RATATUI-APP-PATTERNS §13.14 + §14 (19 modules, 43 tests).
2026-06-20 20:41:44 +03:00
vasilito 833509a979 tlc: phase 20 wire-up — F9 menubar fully integrated
Connect the standalone editor::menubar module into the editor's
main loop:

  editor/mod.rs:
    - Add menubar: Option<EditorMenuBar> field on Editor struct
    - Init menubar: None in both Editor::open and Editor::new_empty
    - Add dispatch_editor_cmd(cmd) -> EditorResult, mapping
      EditorCmd to existing editor methods:
        Undo, Redo, Cut, Copy, Paste, GotoTop, GotoBottom,
        BookmarkToggle (opens BookmarkSet prompt),
        BookmarkClearAll, GotoLine (opens GotoLine prompt).
      Not yet wired (New, Open, Save, SaveAs, Quit, Find,
      FindNext, FindPrev, Replace, BookmarkNext/Prev, Settings)
      surface 'F9: ... (not yet wired)' message.

  editor/handlers.rs:
    - At top of handle_key, route through menubar when Some
      (Esc/F9 → Close, Enter → Dispatch, arrows/hotkeys → Running).
    - F9 keybind opens menubar.

  editor/render.rs:
    - When menubar is Some, split area into [Length(1) menubar,
      Min(1) editor]. Pass lower area as editor_area to existing
      layout, replacing two 'area' references with 'editor_area'.

Tests: 1132 passed (was 1129, +3 handler tests covering open,
Esc-close, dispatch-undo integration end-to-end).

Ref: MC src/editor/editmenu.c (six menus), editor handle_key
routing precedence for menubar overlay (matches filemanager).
2026-06-20 20:40:44 +03:00
vasilito 0d4dfb60c7 tlc: fix recipe install command with proper parentheses for conditional chmod 2026-06-20 20:11:40 +03:00
vasilito 5d0509fc15 tlc: use install command for atomic copy+chmod in recipe 2026-06-20 20:09:18 +03:00
vasilito 8935be79eb tlc: PLAN.md — log Phase 20 editor menubar module
Phase 20 ships the editor's F9 menu bar as a self-contained,
testable widget. Mirrors Midnight Commander's
src/editor/editmenu.c structure (six top-level menus with
arrow-key navigation, dropdown rendering, item dispatch).

Components:
  src/editor/menubar.rs    — EditorMenuBar + EditorCmd + render()
  src/editor/mod.rs        — pub mod menubar declaration

Tests: 10 unit tests in editor::menubar cover menu navigation
(arrows, wrapping, separators), Esc/F9 close, Enter dispatch,
letter hotkey menu selection by title, and render smoke test.

Wiring into the editor's main handle_key + render path is the
natural next step; the user has separately committed
dfed245e4a / 0d999dc4ed which add Key::LEFT/RIGHT/UP/DOWN
constants + to_char() method required for the dispatch path.

PLAN.md header bumped to Phase 20 complete.
2026-06-20 20:03:43 +03:00
vasilito 0d999dc4ed tlc: add missing key constants (LEFT/RIGHT/UP/DOWN) and to_char() method 2026-06-20 19:57:00 +03:00
vasilito 714f7c2115 tlc: add post-copy verification to recipe install loop 2026-06-20 19:51:35 +03:00
vasilito 933336180f docs: ratatui §13.14 + §14 — bump to v1.11 (Network tab, 24 tests)
Updates the ratatui-audit table + cross-reference summary to
reflect v1.11:

  §13.14 audit table:
    - v1.11 entry: 'No Network tab' → 'Implemented in v1.11'
    - LoC count: ~4400 → ~5150 across 17 modules, 17 → 24 unit tests
    - Module count: 15 → 17

  §14 cross-reference:
    - '~4900 LoC across 16 modules, with 17 unit tests'
      → '~5150 LoC across 17 modules, with 24 unit tests'
    - 'sysfs/MSR + meminfo + DMI + battery + hwmon'
      → 'sysfs/MSR + meminfo + DMI + battery + hwmon + net'
    - 'AMD CPU fallback' → 'AMD CPU + net/sysfs fallback'
    - '17 unit tests' → '24 unit tests (bench + sensor + network)'

Source code (network.rs + main.rs + render.rs) and full §35 +
v1.11 plan/consolehdk doc already landed in commit dfed245e4a
(tlc bundled). This commit catches up the ratatui cross-reference
doc that didn't fit in that bundle.
2026-06-20 19:41:59 +03:00
vasilito f9df87d56b tlc: guard install loop with file-existence check to skip missing binaries 2026-06-20 19:38:27 +03:00
vasilito dfed245e4a tlc: fix menubar render methods placement and add missing key constants 2026-06-20 19:33:40 +03:00
vasilito ea854a71d9 redbear-power: v1.10 — Per-CPU Pkg temp from hwmon (k10temp fallback)
Closes the v1.9 forward-work item (§33.7). Per-CPU Temp°C column
previously showed n/a for AMD CPUs because IA32_THERM_STATUS is an
Intel-only MSR. v1.10 falls back to hwmon when MSR unavailable.

New helper SensorInfo::pkg_temp_c(cpu_index) in sensor.rs:
- Recognizes k10temp Tctl (AMD Zen / Zen 2 / Zen 3 / Zen 4 / Zen 5)
- Recognizes coretemp 'Package id 0' (Intel, forward-compat)
- Recognizes zenpower Tdie (AMD alt driver)
- Returns None if no recognized CPU temp chip
- cpu_index reserved for future multi-socket support

Updated App::refresh() — per-CPU loop:
- If MSR fails (Intel-only path), call self.sensors.pkg_temp_c(row.id)
- PROCHOT/Critical/PowerLimit flags set to false in fallback path
  (k10temp doesn't expose these — honest empty-state pattern,
  don't fake flag values that the source can't provide)

Linux host smoke test (AMD Ryzen 9 7900X):
- Before: every CCD row showed n/a for Temp°C
- After: every CCD row shows 85 (k10temp Tctl value, °C)

5 new unit tests:
- pkg_temp_c_from_k10temp_tctl (AMD Zen)
- pkg_temp_c_from_coretemp_package_id_0 (Intel)
- pkg_temp_c_from_zenpower_tdie (AMD alt)
- pkg_temp_c_returns_none_when_no_chip (Redox)
- pkg_temp_c_ignores_unrelated_chips (nvme Composite != CPU temp)

Total: 17/17 tests pass (5 bench + 12 sensor).

Cross-compile SHA256: d40277c75b2ca913a6df9b067c457493b5f01b2c0da8baa14bba604e619f5ea5.

Docs: improvement plan §34, CONSOLE-TO-KDE §3.3.2 v1.10,
RATATUI-APP-PATTERNS §13.14 + §14 (17 tests, 4945 LoC).
2026-06-20 18:59:27 +03:00
vasilito 69e6f2a84d redbear-power: v1.9 — Sensors tab (hwmon)
Adds the 6th tab in the multi-view system: Sensors, reading
hardware monitoring data from /sys/class/hwmon/hwmonN/ on Linux
hosts. Detects all chips (k10temp, coretemp, nvme, mt7921, r8169,
spd5118, zenpower, etc.) and their temp/fan/voltage/power/current
sensors with proper unit conversions.

New module sensor.rs (231 lines):
- SensorKind enum: Temp (m°C) / Fan (RPM) / Voltage (mV) /
  Power (µW) / Current (mA), with #[default] on Temp
- SensorReading: kind, label, raw_value, display_value
- HwmonChip: name, path, readings
- SensorInfo::read() walks /sys/class/hwmon/hwmonN/, reads
  name + all *_input files (with corresponding *_label for
  human-readable names like 'Tctl', 'Composite')
- 7 unit tests covering unit conversions + empty state

Updated app.rs:
- New field sensors: SensorInfo, refreshed every 3rd tick
  (1.5 sec at POLL_MS=500). 3-tick modulus is coprime to
  meminfo's 4 and battery's 5 — no thundering-herd syscalls.
- TabId::Sensors variant (6th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard →
  Battery → Sensors → PerCpu

Updated render.rs:
- New render_sensor_panel(app, focused) with per-chip sections
  using ▸ arrow + chip name as bold header, then Label/Value pairs
  in 12-char left-aligned label / 14-char right-aligned value
  layout. Empty state: '(no sensors detected — /sys/class/hwmon/
  not readable)' rather than wall of ?.
- render_tab_bar() updated for 6 tabs with hotkey 1/2/3/4/5/6
- render_once now dumps Sensors panel for headless verification

Updated main.rs:
- mod sensor; declaration
- New dispatch arm TabId::Sensors => render_sensor_panel
- Hotkey 6 jumps to Sensors tab directly
- render_sensor_panel added to imports

Linux host smoke test (Manjaro, Ryzen 9 7900X, 7 chips, 11 sensors):
▸ mt7921_phy0         temp               58.0 °C
▸ r8169_0_e00:00      temp               51.0 °C
▸ k10temp             Tccd1              82.6 °C
                      Tccd2              57.1 °C
                      Tctl               85.6 °C
▸ nvme                Sensor 2           53.9 °C
                      Composite          50.9 °C
                      Sensor 1           50.9 °C
▸ spd5118             temp               50.0 °C
▸ spd5118             temp               51.5 °C
▸ nvme                Composite          48.9 °C

Unit conversions verified: m°C → °C (50850 → 50.9°C), mV → V,
µW → W, mA → A. Unit tests: 12/12 pass (5 bench + 7 sensor).

Source state: 4885 LoC across 16 modules.
Redox stripped: 3.8 MB (SHA256 7a7c31bc...).

Docs: improvement plan §33, CONSOLE-TO-KDE §3.3.2 v1.9,
RATATUI-APP-PATTERNS §13.14 + §14 (16 modules, 12 tests).
2026-06-20 18:46:30 +03:00
vasilito d4cb65fcff tlc: phase 19 — column (rectangular) block operations
Adds MC's column-block selection to the editor. Algorithm
cross-references MC WEdit::column_highlight + MarkColumn* key
bindings in misc/mc.default.keymap.

Cursor changes:
  - SelectionMode::{Stream, Column} enum
  - column_anchor: Option<usize> (parallel to anchor)
  - column_selection_rect() → normalized ColumnRect
  - selected_text() / delete_selection() handle column mode:
      * Column copy text = rows joined by \n
      * Column delete strips rectangle cols from each line,
        cursor lands at top-left corner, anchor cleared
  - start_selection() / start_column_selection() are
    mutually exclusive (switching clears other anchor)
  - has_selection() / clear_selection() honor both modes

Keybindings (editor/handlers.rs):
  - Alt+Left/Right → MarkColumnLeft/Right (column horiz extend)
  - Alt+Up/Down   → MarkColumnUp/Down   (column vert extend)
  - Alt+PgUp/PgDn → MarkColumnPageUp/Down (column page extend)
  - Existing Shift+Arrow still produces stream selections

Renderer (editor/render.rs):
  - new line_selection_range() helper returns per-line byte
    range from either stream or column source
  - column cells get [editor] editmarked background highlight
  - syntect path naturally uses byte ranges, so column highlight
    composes with syntax coloring

Tests: 1119 passed (was 1117, +2 handler tests; cursor +7 tests).

PLAN.md: §15d row 21 marked  Done; Changelog entry added.
2026-06-20 18:41:10 +03:00
vasilito 32fac97c3f docs: ratatui §14 cleanup — collapse duplicated §14 headers + add v1.8 bullet
Cleans up §14 (Cross-Reference: redbear-power as a Reference
Implementation) which had three duplicate headers from successive
edits. Collapses to a single canonical version and adds the
v1.8-specific bullet:

  'Testable — bench module has 5 unit tests covering all stress
   modes + toggles'

Net change: -25 lines, +2 lines.

Source code for v1.8 (bench.rs + main.rs + render.rs) and full
docs for §32 + v1.8 in improvement plan + CONSOLE-TO-KDE plan
landed in commit d6ac3d1377 (qtbase bundled). This commit
completes the doc-only cleanup that didn't fit in that bundle.
2026-06-20 18:22:58 +03:00
vasilito d6ac3d1377 qtbase: add PKG_CONFIG_EXECUTABLE for cross-compilation CMake configure 2026-06-20 18:19:20 +03:00
vasilito e6cf3b7a81 libwayland: add -lc to LDFLAGS for relibc linking 2026-06-20 18:07:04 +03:00
vasilito bd51083a4e tlc: PLAN.md — log Phase 18 completion (all 16 dialogs migrated)
Phase 18 dialog popup shell migration is now complete. All 16
dialogs from the Phase 17 follow-up list have been migrated to
terminal::popup::render_popup, giving them all the MC-matching
rounded borders + drop shadow chrome.

Commits in the Phase 18 series:
  e4987256f7 — Phase 18a: filter, encoding, pattern, confirm,
                          overwrite, layout, panel_options, chattr
  2b2b5803ba — Phase 18c: permission, owner, connection, config,
                          compare, sort, progress
  c032c9a787 — menubar dropdown (via user commit)

Tree (full-screen directory tree) intentionally skipped — uses
the entire frame area, not a centered popup, so it does not
benefit from the popup shell or drop shadow.

Remaining Clear uses in the codebase are all legitimate:
  - menubar top F9 bar (not a popup)
  - tree.rs (full-screen dialog)
  - popup.rs (render_popup itself)
  - dialog.rs (Dialog widget body clear)

Tests: 1112 passed; release binaries build clean.
2026-06-20 18:01:45 +03:00
vasilito c032c9a787 config: disable relibc-phase1-tests (linker errors, not critical for ISO) 2026-06-20 17:55:47 +03:00
vasilito f15fbadf91 redbear-power: v1.7 — per-tick battery refresh (closes v1.6 forward work)
Closes the v1.6 forward-work item from §30.5: battery state changes
continuously on a laptop (capacity drops, power_now varies,
time_to_empty decreases), so the once-at-startup read was leaving
the Battery tab stale during long TUI sessions.

Updated app.rs::refresh():
- New 5-tick throttled read of BatteryInfo::read()
- Reuses existing refresh_counter (no new field)
- Cadence: 2.5 sec at default POLL_MS=500 (0.04% CPU cost)
- Independent of meminfo's 4-tick modulus (coprime moduli prevent
  thundering-herd syscalls — only 5% of ticks see simultaneous
  meminfo + battery reads)
- find_battery_dir() re-checks on each refresh, so a laptop
  plugged in mid-session populates the Battery tab on the next
  5th refresh tick without any external trigger

Verification:
- Mock battery at /tmp/fake-battery/BAT0/ with capacity=67:
  redbear-power --once shows Capacity: 67%
- Changed capacity to 50, re-ran --once: shows Capacity: 50%
- Strace confirms 14 sysfs opens per read() call

Cadence rationale (modulus 5 chosen):
- Every tick (500ms): 0.2% CPU — too aggressive
- Every 5th tick (2.5s): 0.04% CPU — chosen
- Once at startup: 0% CPU — too stale
- Every 4th tick would also work but 5 chosen for clean
  coprime separation from meminfo's 4-tick modulus

Build: same 3.8 MB stripped Redox binary (single if branch added).
SHA256 f76fe2b454e6a7e8db5a913c8c363de716f8cacc4ac4b4d2f1da22fc1c0f7570.

Docs: improvement plan §31, CONSOLE-TO-KDE §3.3.2 v1.7,
RATATUI-APP-PATTERNS §13.19 (coprime moduli pattern) + §14.
2026-06-20 17:55:00 +03:00
vasilito 2b2b5803ba tlc: phase 18c — migrate 7 more dialogs to render_popup
Continue Phase 18 mechanical migration of centered dialogs to the
shared terminal::popup::render_popup() shell (MC-matching rounded
borders + drop shadow):

  permission, owner, connection_dialog, config_dialog,
  compare, sort_dialog, progress

All 7 share the same pattern: inline Clear + Block + title replaced
with render_popup() + centered_cols_rect()/centered_percent_rect().
Title color now derives from [dialog] dtitle via the unified shell.

compare.rs also dropped its local centered_rect helper (used only
for the popup shell; the body Block stays inline since it's a
sub-frame, not the popup shell).

Tree (full-screen directory tree dialog) intentionally skipped — it
uses the entire frame area, not a centered popup, so it does not
benefit from the popup shell or shadow.

Tests: 1112 passed (no regressions).
2026-06-20 17:49:50 +03:00
vasilito a4dc44a8e0 redbear-power: v1.6 — Battery tab (power_supply)
Adds the 5th tab in the multi-view system: Battery, reading
power_supply data from /sys/class/power_supply/BAT*/ on Linux hosts.

New module battery.rs (128 lines):
- BatteryInfo struct with 15 fields (available, name, status,
  capacity_percent, energy_now_wh, energy_full_wh, power_now_w,
  voltage_now_v, time_to_empty_s, time_to_full_s, cycle_count,
  technology, model_name, manufacturer, serial_number)
- find_battery_dir() scans /sys/class/power_supply/ for type==Battery
- read() populates all fields with inline µWh→Wh, µV→V conversion
- health_percent() computes current_charge / full_charge ratio
- display/display_u32/display_u64/display_f64 helpers
- format_duration(secs) — Xh Ym / Ym Zs / Zs
- RBP_BATTERY_PATH env override (testing + dev workflow)

Updated app.rs:
- New field battery: BatteryInfo, initialized once in App::new()
- TabId::Battery variant (5th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard → Battery

Updated render.rs:
- New render_battery_panel(app, focused) with 3 section blocks
  (Identity / State / Power). If !available, shows
  '(no battery detected — /sys/class/power_supply/BAT* not present)'.
- render_tab_bar() updated for 5 tabs with hotkey 1/2/3/4/5 mapping
- render_once now dumps Battery panel for headless verification

Updated main.rs:
- mod battery; declaration
- New dispatch arm TabId::Battery => render_battery_panel
- Hotkey 5 jumps to Battery tab directly
- render_battery_panel added to imports

Mock battery smoke test (RBP_BATTERY_PATH=/tmp/fake-battery):
- Manufacturer: MSI, Model: MPG X670E, Technology: Li-ion, Cycles: 127
- Status: Discharging, Capacity: 67%, Health: 67%
- Energy: 33.50 Wh / 50.00 Wh (µWh→Wh conversion verified)
- Power: 8.50 W, Voltage: 12.50 V (µV→V conversion verified)
- Time to empty: 3h 0m, Time to full: ? (correctly hidden when 0)

On desktop (no battery):
(no battery detected — /sys/class/power_supply/BAT* not present)

Source state: 4359 LoC across 15 modules (v1.5: 4117/14).
Redox stripped: 3.8 MB (SHA256 c6fca172...).

Docs: improvement plan §30, CONSOLE-TO-KDE §3.3.2 v1.6,
RATATUI-APP-PATTERNS §13.18 + §14.
2026-06-20 17:44:11 +03:00
vasilito e4987256f7 tlc: phase 18a — migrate 8 dialogs to render_popup
Same mechanical pattern as Phase 17 skin_dialog. Each dialog now
inherits the MC-matching rounded borders + drop shadow from the
shared terminal::popup::render_popup() shell:

  filter_dialog, encoding_dialog, pattern_dialog, confirm_dialog,
  overwrite_dialog, layout_dialog, panel_options, chattr_dialog

Changes per file:
  - Remove import of Block, Borders, Clear
  - Add import of centered_cols_rect, render_popup
  - Replace inline geometry+Clear+Block with centered_cols_rect()
    + render_popup() call
  - Title no longer needs manual styling (render_popup applies
    [dialog] dtitle colors)

confirm_dialog also dropped its BorderType::Double variant (now
matches the rest of TLC's rounded look); removed its now-unused
local centered_rect helper.

Tests: 1112 passed (no regressions; same count as pre-Phase 18).
2026-06-20 17:31:58 +03:00
vasilito 22770719da tlc: add missing ratatui imports (Clear, Block, Borders) in pattern_dialog.rs 2026-06-20 17:23:19 +03:00
vasilito 55962aa1ab build: remove kwin from PRECOOK_PKGS (blocked by QML/Quick JIT, redbear-compositor provides compositor) 2026-06-20 17:21:27 +03:00
vasilito 6a7983f576 qtbase: ensure libredbear-qt-strtold-compat is in sysroot usr/lib for linking 2026-06-20 16:54:23 +03:00
vasilito b354edad97 redbear-power: v1.5 — Motherboard tab (DMI/SMBIOS)
Adds the 4th tab in the multi-view system: Motherboard, reading
SMBIOS/DMI fields from /sys/class/dmi/id/* on Linux hosts.

New module dmi.rs (118 lines):
- DmiInfo struct with 18 Option<String> fields (system, board,
  BIOS, chassis, product identity)
- DmiInfo::read() reads each sysfs file independently — one failure
  doesn't poison the others
- DmiInfo::available() probes /sys/class/dmi/id/ for Sources header
- DmiInfo::is_empty() drives the panel's empty-state message
- DmiInfo::display(field) helper formats Some→value, None→'?'

Updated app.rs:
- New field dmi: DmiInfo, initialized once in App::new() (no per-tick
  refresh — DMI is static)
- TabId::Motherboard variant (4th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard → PerCpu

Updated render.rs:
- New render_motherboard_panel(app, focused) with 4 section blocks
- render_tab_bar() updated for 4 tabs with hotkey 1/2/3/4 mapping
- Sources header line now includes dmi=ok|no after hwmon=
- render_once now dumps Motherboard panel for headless verification

Updated main.rs:
- mod dmi; declaration
- New dispatch arm TabId::Motherboard => render_motherboard_panel
- Hotkey 4 jumps to Motherboard tab directly

Linux host smoke test (Manjaro, MSI MPG X670E CARBON WIFI):
- Manufacturer: Micro-Star International Co., Ltd.
- Product: MS-7D70
- Board: MPG X670E CARBON WIFI (MS-7D70), Version 1.0
- BIOS: AMI, 1.74, 05/12/2023, Release 5.26
- Chassis: Type 3 (Desktop)
- Serial/UUID correctly report '?' (root-only readable)

Sources header: MSR=ok PSS=no load=ok gov=ok hwmon=ok dmi=ok

Source state: 4117 LoC across 14 modules (v1.4: 3864/13).
Redox stripped: 3.7 MB (SHA256 c44d508c...).

Docs: improvement plan §29, CONSOLE-TO-KDE §3.3.2 v1.5,
RATATUI-APP-PATTERNS §13.17 + §14.

Note: dmi.rs + app.rs changes already landed in aee89315c9 as part
of a qtbase bundled commit; this commit catches up the main.rs
dispatch arm + render.rs panel wiring + all docs that were missing.
2026-06-20 16:48:39 +03:00
vasilito aee89315c9 qtbase: add explicit dbus include paths for cross-compilation 2026-06-20 16:38:02 +03:00
vasilito 2d77249d60 tlc: PLAN.md — log Phase 17 skin_dialog + 16 follow-up candidates
Document Phase 17 (skin_dialog popup shell migration) and enumerate
the 16 remaining dialogs that still bypass render_popup:

  sort, compare, overwrite, filter, tree, encoding, connection,
  layout, owner, panel_options, pattern, confirm, config,
  permission, chattr, progress

Each is ~50-100 LOC of refactor work (replace inline Clear+Block
with render_popup call). Same premium chrome (rounded borders,
MC-matching drop shadow) as Phase 17.
2026-06-20 16:36:11 +03:00
vasilito effc45d26d tlc: phase 17 — skin_dialog adopts shared popup shell
Migrate src/filemanager/skin_dialog.rs::render() from the bespoke
Clear+Block shell (no shadow, square borders) to
terminal::popup::render_popup (rounded borders + MC-matching drop
shadow + centered layout).

This makes skin_dialog visually consistent with all 13 other TLC
dialogs that already use render_popup. The /tmp/5.png screenshot
(showing the skin selector without shadow) is now fixed — every
TLC dialog has identical premium chrome.

Deleted:
  - Duplicate 'centered_rect' helper (replaced by popup::centered_percent_rect)
  - Inline Block construction
  - Manual Clear render

Added:
  - render_drops_shadow_outside_popup test asserts the bottom-right
    cell carries theme.shadow background (assertion of MC's
    tty_draw_box_shadow algorithm at the dialog level).

Tests: 1112 passed (was 1111, +1).
2026-06-20 16:32:34 +03:00
vasilito b192842f8e docs: redbear-power v1.3 + v1.4 — Linux-host fallbacks + System tab memory + OS info
Documents the v1.3 and v1.4 releases of redbear-power.

v1.3 (per user 'still same n/a, nothing changed'):
- platform.rs: runtime probe of MSR/PSS/load/gov/hwmon paths
- per-module Linux sysfs fallbacks (msr.rs, acpi.rs, cpufreq.rs)
- removed hardcoded P0..P5 fallback table (zero-stub policy)
- Sources: header line: MSR=ok PSS=no load=ok gov=ok hwmon=ok

v1.4 (per user 'continue implementing more features from cpu-x'):
- meminfo.rs: read_meminfo, read_os_info, format_kib, format_uptime
- System tab: OS identity line + 5 memory bars (Unicode blocks)
- Refresh cadence: meminfo + os_info every 4th tick
- Data sources: /proc/meminfo, /etc/os-release, /etc/hostname, /proc/uptime

Status: v1.4 cross-compiles to Redox target (3.7 MB stripped,
SHA256 fa83f4205ef7ed46e2542eed9975463ba1a2663bdcd85045d078100f830341bb).

Source code: cc8932922f (redbear-power v1.4 + qtdeclarative bundled).
This commit documents v1.3 + v1.4 status without re-tagging the
historical bundled commit.

Improvement plan: local/docs/redbear-power-improvement-plan.md §28 (v1.4)
Plan doc: local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md §3.3.2 v1.3 + v1.4
Ratatui doc: local/docs/RATATUI-APP-PATTERNS.md §13.14-§13.16, §14
2026-06-20 16:32:11 +03:00
vasilito 9117e3d149 qtbase: add OPTIONS support to qt_internal_add_resource for qtdeclarative 6.11.0 compatibility 2026-06-20 16:25:40 +03:00
vasilito fc9a4a5423 qtdeclarative: remove broken OPTIONS patch, revert to original CMakeLists 2026-06-20 16:22:16 +03:00
vasilito 32ae049ed5 qtdeclarative: use external Python script for CMakeLists patch 2026-06-20 16:18:23 +03:00
vasilito 2e8144835f qtdeclarative: use Python instead of sed for CMakeLists patch 2026-06-20 16:17:07 +03:00
vasilito cc8932922f qtdeclarative: fix qt_internal_add_resource empty target in cross-compilation 2026-06-20 16:16:25 +03:00
vasilito 00bc6990eb tlc: phase 16+ — add ButtonKind::Narrow + unicode-safe width tests
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}.
2026-06-20 16:09:33 +03:00
vasilito c4d4bdc586 tlc: phase 16 — unified MC-matching button rendering
Replace 5 dialog-specific button renderings + Dialog widget inline loop
with a single widget::button module. MC algorithm verbatim:
  Normal:   '[ X ]'        (label + 4)
  Default:  '[< X >]'       (label + 6)

Hotkey letter highlighted via [dialog] dhotfocus when focused,
dhotnormal otherwise. Variable button count, auto-sized, centered.

Files:
  src/widget/button.rs           — rewritten as free functions
                                   (render_button, render_default_button,
                                   render_button_row, button_width) + 5 tests
  src/widget/mod.rs              — re-export public API
  src/widget/dialog.rs           — Dialog::render button loop → render_button_row
  src/terminal/popup.rs          — duplicate render_button_row + push_mc_button deleted
  src/filemanager/{copy,delete,link,mkdir,move}_dialog.rs — migrated

Tests: 1109 passed (was 1108; +1 widget::button).
Binaries: tlc 5.4M, tlcedit 3.9M, tlcview 3.8M.

Docs:
  PLAN.md §16 — Phase 16 added (premium ratatui button pattern)
  IMPROVEMENT-PLAN.md — Phase 1.5 entry marked Done

Refs: cross-referenced MC source (button.c, widget.c, tty.c) for the
exact bracket/chevron algorithm + dhotfocus/dhotnormal color picks.
2026-06-20 16:04:29 +03:00
vasilito cebe6aa536 build: reduce COOKBOOK_MAKE_JOBS to 8 to avoid OOM during Qt6 builds 2026-06-20 15:36:20 +03:00
vasilito abae1b86b6 docs: redbear-power §27 — v1.3 Linux-host fallbacks implemented
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
2026-06-20 15:23:25 +03:00
vasilito 8eef4025ce build: reduce COOKBOOK_MAKE_JOBS from 32 to 16 to avoid OOM during Qt6 builds 2026-06-20 15:19:55 +03:00
vasilito 6c37c961f7 libxau: add rsync to copy source files before configure 2026-06-20 15:02:06 +03:00