W79: MC visual/behavioral parity — viewer Enter/F3, editor margin, char info, remove viewer ruler
Viewer (2 fixes + 1 removal): - Enter key bound to cursor-down (MC parity, same as j/Down) - F3 key bound to quit (MC CK_Quit parity, same as Esc/q) - Removed column ruler (Alt-R/ToggleRuler) — CK_Ruler is MC editor-only, not present in MC viewer at all Editor (2 fixes): - Right-margin indicator: vertical '│' at word_wrap_line_length (default 72) when word-wrap is active, drawn via direct buffer mutation - Character info in status bar: '0x41 065 A' format between Bytes and mode tag, mirroring MC editdraw.c status display Added word_wrap_line_length: usize field to Editor struct (default 72). Documented encoding and search dialog as intentional divergences. Updated PLAN.md: test counts 1381→1433, MC parity marked 100%.
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
- Visual/UX gap fixes (W6a–W6d): CJK width, bracket flash, search wrap, tab indicator
|
||||
|
||||
**Branch:** `0.3.0`
|
||||
**Tests:** 1434 passing (+53 across W-series polish)
|
||||
**Tests:** 1433 passing (+52 across W-series polish)
|
||||
**Codebase:** 143 .rs files, ~59k lines
|
||||
**Binaries:** `tlc` (file manager), `tlcedit`, `tlcview`
|
||||
**MC parity:** 100% complete (all behavioral + visual divergences resolved)
|
||||
@@ -129,7 +129,7 @@ zero code changes. No `target_os = "redox"` or `target_os = "linux"` gates.
|
||||
|---|---|
|
||||
| Cargo build (host Linux x86_64) | ✅ Clean, 3.0 MB binary |
|
||||
| Cargo build (`--target x86_64-unknown-redox`) | ✅ 3.3 MB statically-linked ELF |
|
||||
| `cargo test --lib` | ✅ **1434 / 1434 pass** |
|
||||
| `cargo test --lib` | ✅ **1433 / 1433 pass** |
|
||||
| Clippy warnings | ✅ 0 lib warnings (2 pre-existing bin warnings: bitflags macro artifact + manual case-insensitive glob) |
|
||||
| `#![deny(unsafe_code)]` | ✅ Zero `unsafe` in any `.rs` file |
|
||||
| `unwrap()`/`expect()` in non-test code | ✅ Audit complete — all `Mutex::lock` use poisoning recovery |
|
||||
@@ -224,11 +224,11 @@ All previously deferred items are now resolved:
|
||||
|
||||
### 2026-07-08 — W79 — MC visual/behavioral parity polish
|
||||
|
||||
**W79a Viewer:** Three MC parity improvements:
|
||||
- Column ruler now renders visually (was only a toggle flag). When toggled
|
||||
via Alt-R, displays column position marks at 10-char intervals above text.
|
||||
**W79a Viewer:** Two MC parity improvements:
|
||||
- Enter key bound to cursor-down navigation (MC parity, same as `j`/Down).
|
||||
- F3 key bound to quit viewer (MC CK_Quit parity, same as Esc/q).
|
||||
- Removed column ruler (Alt-R/ToggleRuler) — CK_Ruler is an MC editor-only
|
||||
feature, not present in MC viewer at all.
|
||||
|
||||
**W79b Editor:** Two MC parity improvements:
|
||||
- Right-margin indicator: draws a vertical `│` at the word-wrap column
|
||||
@@ -238,7 +238,7 @@ All previously deferred items are now resolved:
|
||||
- Character info in status bar: shows `0x41 065 'A'` (hex, decimal,
|
||||
displayable char) at cursor position between Bytes and mode tag,
|
||||
mirroring MC's `editdraw.c` status-line char display. Falls back
|
||||
to `<EOF>` or `.` for non-printable characters.
|
||||
to `.` for non-printable characters.
|
||||
|
||||
**Documented intentional divergences:**
|
||||
- Viewer encoding: TLC is UTF-8 native; MC's codepage display does not
|
||||
|
||||
@@ -34,8 +34,6 @@ pub enum ViewerCmd {
|
||||
ToggleWrap,
|
||||
/// Toggle growing buffer (tail -f style).
|
||||
ToggleGrowing,
|
||||
/// Toggle column ruler.
|
||||
ToggleRuler,
|
||||
/// Toggle hex column navigation (hex↔ASCII text column).
|
||||
ToggleHexNavigation,
|
||||
/// Toggle whole-word search.
|
||||
@@ -158,7 +156,6 @@ impl ViewerMenuBar {
|
||||
MenuItem::item("Magic", 'm', ViewerCmd::ToggleMagic),
|
||||
MenuItem::item("Wrap", 'w', ViewerCmd::ToggleWrap),
|
||||
MenuItem::item("Growing buffer", 'g', ViewerCmd::ToggleGrowing),
|
||||
MenuItem::item("Ruler", 'r', ViewerCmd::ToggleRuler),
|
||||
MenuItem::item("Hex nav.", 'h', ViewerCmd::ToggleHexNavigation),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -107,8 +107,6 @@ pub struct Viewer {
|
||||
/// If true, wrap the search pattern in \b boundaries to match
|
||||
/// whole words only. Toggled via the search options.
|
||||
pub search_whole_words: bool,
|
||||
/// Whether to show the column ruler (MC CK_Ruler / Alt-R).
|
||||
pub ruler: bool,
|
||||
/// True when the cursor navigates the ASCII text column in
|
||||
/// hex mode (MC hexview_in_text). Toggled by Tab.
|
||||
pub hexview_in_text: bool,
|
||||
@@ -201,7 +199,6 @@ impl Viewer {
|
||||
marker: 0,
|
||||
last_search_forward: true,
|
||||
search_whole_words: false,
|
||||
ruler: false,
|
||||
hexview_in_text: false,
|
||||
nroff_enabled: false,
|
||||
show_help: false,
|
||||
@@ -252,7 +249,6 @@ impl Viewer {
|
||||
marker: 0,
|
||||
last_search_forward: true,
|
||||
search_whole_words: false,
|
||||
ruler: false,
|
||||
hexview_in_text: false,
|
||||
nroff_enabled: false,
|
||||
show_help: false,
|
||||
@@ -807,40 +803,7 @@ impl Viewer {
|
||||
frame.render_widget(block, chunks[1]);
|
||||
self.last_height = inner.height;
|
||||
match self.mode {
|
||||
ViewMode::Text => {
|
||||
let text_area = if self.ruler && inner.height >= 2 {
|
||||
let ruler_area =
|
||||
Rect::new(inner.x, inner.y, inner.width, 1);
|
||||
let ruler_spans: Vec<Span> = (0..inner.width as usize)
|
||||
.map(|col| {
|
||||
if col % 10 == 0 {
|
||||
Span::styled(
|
||||
format!("{}", (col / 10) % 10),
|
||||
Style::default().fg(body_fg).bg(body_bg),
|
||||
)
|
||||
} else {
|
||||
Span::styled(
|
||||
" ",
|
||||
Style::default().fg(body_fg).bg(body_bg),
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(ruler_spans)),
|
||||
ruler_area,
|
||||
);
|
||||
Rect::new(
|
||||
inner.x,
|
||||
inner.y + 1,
|
||||
inner.width,
|
||||
inner.height - 1,
|
||||
)
|
||||
} else {
|
||||
inner
|
||||
};
|
||||
crate::viewer::text::render(self, frame, text_area, theme)
|
||||
}
|
||||
ViewMode::Text => crate::viewer::text::render(self, frame, inner, theme),
|
||||
ViewMode::Hex => hex::render(self, frame, inner, theme),
|
||||
ViewMode::HexEdit => hex_edit::render(self, frame, inner, theme),
|
||||
}
|
||||
@@ -1131,11 +1094,6 @@ impl Viewer {
|
||||
self.wrap = !self.wrap;
|
||||
return false;
|
||||
}
|
||||
// Alt-R — toggle column ruler (MC CK_Ruler).
|
||||
if code == b'r' as u32 && mods == crate::key::Modifiers::ALT {
|
||||
self.ruler = !self.ruler;
|
||||
return false;
|
||||
}
|
||||
// Alt-Shift-E — cycle through file history (MC CK_History).
|
||||
if code == b'e' as u32 && mods == crate::key::Modifiers::ALT | crate::key::Modifiers::SHIFT {
|
||||
if !self.file_history.is_empty() {
|
||||
@@ -1293,9 +1251,6 @@ impl Viewer {
|
||||
ViewerCmd::ToggleGrowing => {
|
||||
let _ = self.toggle_growing();
|
||||
}
|
||||
ViewerCmd::ToggleRuler => {
|
||||
self.ruler = !self.ruler;
|
||||
}
|
||||
ViewerCmd::ToggleHexNavigation => {
|
||||
self.hexview_in_text = !self.hexview_in_text;
|
||||
}
|
||||
@@ -2048,17 +2003,6 @@ mod tests {
|
||||
assert!(v.wrap, "F2 should toggle wrap back on");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ruler_toggle_cycles() {
|
||||
let p = make_text("ruler.txt", b"hello\n");
|
||||
let mut v = Viewer::open(&p).unwrap();
|
||||
assert!(!v.ruler);
|
||||
let _ = v.handle_key(Key { code: b'r' as u32, mods: crate::key::Modifiers::ALT });
|
||||
assert!(v.ruler);
|
||||
let _ = v.handle_key(Key { code: b'r' as u32, mods: crate::key::Modifiers::ALT });
|
||||
assert!(!v.ruler);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_accepts_percent_and_offset() {
|
||||
// Use a 100-line file so 50% = line 50.
|
||||
|
||||
+1
-1
Submodule local/sources/base updated: 98c43529e7...7abd45bf2e
Reference in New Issue
Block a user