diff --git a/local/recipes/tui/tlc/PLAN.md b/local/recipes/tui/tlc/PLAN.md index 5ca8fb2b3f..6f64ccba5a 100644 --- a/local/recipes/tui/tlc/PLAN.md +++ b/local/recipes/tui/tlc/PLAN.md @@ -230,7 +230,7 @@ All previously deferred items are now resolved: - 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: +**W79b Editor:** Three MC parity improvements: - Right-margin indicator: draws a vertical `│` at the word-wrap column (default 72) in every visible body row when word-wrap is active. Uses `word_wrap_line_length: usize` field (new in Editor struct, @@ -239,6 +239,10 @@ All previously deferred items are now resolved: displayable char) at cursor position between Bytes and mode tag, mirroring MC's `editdraw.c` status-line char display. Falls back to `.` for non-printable characters. +- Removed line number gutter — MC editor has no gutter or line numbers. + This was a TLC-only addition incompatible with MC parity. Removed: + gutter rendering, `relative_lines` field, `ToggleRelativeLines` Cmd, + Alt-N keybinding, and the Options-menu "Relative line numbers" item. **Documented intentional divergences:** - Viewer encoding: TLC is UTF-8 native; MC's codepage display does not diff --git a/local/recipes/tui/tlc/source/src/editor/handlers.rs b/local/recipes/tui/tlc/source/src/editor/handlers.rs index 087090224c..cf2694b991 100644 --- a/local/recipes/tui/tlc/source/src/editor/handlers.rs +++ b/local/recipes/tui/tlc/source/src/editor/handlers.rs @@ -287,15 +287,6 @@ impl Editor { }); return Some(EditorResult::Running); } - 0x6E => { - self.relative_lines = !self.relative_lines; - self.message = Some(if self.relative_lines { - "Line numbers: ON".to_string() - } else { - "Line numbers: OFF".to_string() - }); - return Some(EditorResult::Running); - } 0x74 => { let new_width = self.cycle_tab_width(); self.message = Some(format!("Tab width: {new_width}")); diff --git a/local/recipes/tui/tlc/source/src/editor/menubar.rs b/local/recipes/tui/tlc/source/src/editor/menubar.rs index 0900691449..8166feb2f1 100644 --- a/local/recipes/tui/tlc/source/src/editor/menubar.rs +++ b/local/recipes/tui/tlc/source/src/editor/menubar.rs @@ -75,8 +75,6 @@ pub enum EditorCmd { ToggleWordWrap, /// Toggle syntax highlighting (Ctrl-S). ToggleSyntax, - /// Toggle relative line numbers (Alt-N). - ToggleRelativeLines, /// Edit the user menu file (MC `CK_EditUserMenu`). EditUserMenu, /// Alt-P — reformat the paragraph at the cursor. @@ -277,7 +275,6 @@ impl EditorMenuBar { MenuItem::item("Show whitespace", 'w', EditorCmd::ToggleShowWhitespace), MenuItem::item("Word wrap", 'p', EditorCmd::ToggleWordWrap), MenuItem::item("Syntax highlight", 'h', EditorCmd::ToggleSyntax), - MenuItem::item("Relative line numbers", 'r', EditorCmd::ToggleRelativeLines), MenuItem::separator(), MenuItem::item("Insert/Overwrite", 'i', EditorCmd::ToggleOverwrite), MenuItem::item("Spell check", 's', EditorCmd::SpellCheck), diff --git a/local/recipes/tui/tlc/source/src/editor/mod.rs b/local/recipes/tui/tlc/source/src/editor/mod.rs index 91b1b81518..c9d04c3aa4 100644 --- a/local/recipes/tui/tlc/source/src/editor/mod.rs +++ b/local/recipes/tui/tlc/source/src/editor/mod.rs @@ -20,7 +20,7 @@ //! //! All rendering goes through [`Editor::render`], which writes to a //! ratatui `Frame` at the given `Rect`. The view is a simple -//! top-line/left-column scroller with line numbers in the gutter. +//! top-line/left-column scroller. //! //! All key handling goes through [`Editor::handle_key`], which //! dispatches to [`Editor::handle_key_normal`], @@ -188,9 +188,6 @@ pub struct Editor { history_popup_selected: Option, /// Visual shape of the editing cursor (Block/Bar/Underline). cursor_shape: CursorShape, - /// When true, the gutter shows each non-cursor line's distance - /// from the cursor line instead of its absolute number. - relative_lines: bool, /// When false, syntax highlighting is disabled even if a /// highlighter exists. Toggled by Ctrl-S (MC parity). syntax_enabled: bool, @@ -219,8 +216,7 @@ pub struct Editor { last_macro: Vec, /// Code-fold state. `Ctrl-F1` toggles a fold at the cursor /// line; the renderer hides lines covered by collapsed folds - /// and shows a `+` marker in the gutter on the fold's start - /// line. + /// and shows a `+` marker on the fold's start line. folds: folding::FoldSet, /// Tag-stack: positions saved before each `Ctrl-]` jump so /// `Ctrl-T` can pop back. Each entry is `(byte_offset, line)`. @@ -299,7 +295,6 @@ impl Editor { search: SearchState::new(), history_popup_selected: None, cursor_shape: CursorShape::default(), - relative_lines: false, syntax_enabled: true, auto_indent: true, show_whitespace: false, @@ -352,7 +347,6 @@ impl Editor { search: SearchState::new(), history_popup_selected: None, cursor_shape: CursorShape::default(), - relative_lines: false, syntax_enabled: true, auto_indent: true, show_whitespace: false, @@ -1433,22 +1427,13 @@ impl Editor { "Syntax: OFF".to_string() }); } - EditorCmd::ToggleRelativeLines => { - self.relative_lines = !self.relative_lines; - self.message = Some(if self.relative_lines { - "Relative line numbers: ON".to_string() - } else { - "Relative line numbers: OFF".to_string() - }); - } EditorCmd::Settings => { let ai = if self.auto_indent { "ON" } else { "OFF" }; let ww = if self.word_wrap { "ON" } else { "OFF" }; let ws = if self.show_whitespace { "ON" } else { "OFF" }; let sy = if self.syntax_enabled { "ON" } else { "OFF" }; - let rl = if self.relative_lines { "ON" } else { "OFF" }; self.message = Some(format!( - "Settings: auto-indent={ai} wrap={ww} whitespace={ws} syntax={sy} relative-lines={rl} (Alt-A/Alt-W/Alt-E/Ctrl-S toggle)" + "Settings: auto-indent={ai} wrap={ww} whitespace={ws} syntax={sy} (Alt-A/Alt-W/Alt-E/Ctrl-S toggle)" )); } EditorCmd::New => { @@ -2895,11 +2880,11 @@ mod tests { }) .unwrap(); let buffer = terminal.backend().buffer(); - assert_eq!(buffer.cell((4, 1)).expect("a cell").symbol(), "a"); - assert_eq!(buffer.cell((5, 1)).expect("space cell").symbol(), "·"); - assert_eq!(buffer.cell((6, 1)).expect("tab cell").symbol(), "→"); - assert_eq!(buffer.cell((7, 1)).expect("b cell").symbol(), "b"); - assert_eq!(buffer.cell((8, 1)).expect("caret cell").symbol(), "^"); + assert_eq!(buffer.cell((1, 1)).expect("a cell").symbol(), "a"); + assert_eq!(buffer.cell((2, 1)).expect("space cell").symbol(), "·"); + assert_eq!(buffer.cell((3, 1)).expect("tab cell").symbol(), "→"); + assert_eq!(buffer.cell((4, 1)).expect("b cell").symbol(), "b"); + assert_eq!(buffer.cell((5, 1)).expect("caret cell").symbol(), "^"); } #[test] @@ -2928,7 +2913,7 @@ mod tests { }) }) .expect("must find 'b' from beta"); - let cell = buffer.cell((4, beta_y)).expect("beta line cell"); + let cell = buffer.cell((1, beta_y)).expect("beta line cell"); assert_eq!(cell.symbol(), "b"); assert_eq!(cell.fg, bookmarkfound.fg); assert_eq!(cell.bg, bookmarkfound.bg); @@ -3214,8 +3199,8 @@ mod tests { fg: theme.marked_fg, bg: theme.marked_bg, }); - let f_cell = buffer.cell((4, 1)).expect("'f' cell"); - let n_cell = buffer.cell((5, 1)).expect("'n' cell"); + let f_cell = buffer.cell((1, 1)).expect("'f' cell"); + let n_cell = buffer.cell((2, 1)).expect("'n' cell"); assert_eq!(f_cell.symbol(), "f"); assert_eq!(n_cell.symbol(), "n"); assert_eq!(f_cell.bg, marked_pair.bg, "selected 'f' cell bg"); diff --git a/local/recipes/tui/tlc/source/src/editor/render.rs b/local/recipes/tui/tlc/source/src/editor/render.rs index 57dc127544..a1f258a328 100644 --- a/local/recipes/tui/tlc/source/src/editor/render.rs +++ b/local/recipes/tui/tlc/source/src/editor/render.rs @@ -2,7 +2,7 @@ //! //! [`Editor::render`] writes the editor into a ratatui `Frame` at //! the given `Rect`. The view is a simple top-line/left-column -//! scroller with line numbers in the gutter. The status line shows +//! scroller. The status line shows //! position, modification state, and active mode. use ratatui::layout::{Constraint, Direction, Layout, Rect}; @@ -21,7 +21,7 @@ use super::Editor; impl Editor { /// Render the editor into a ratatui frame at the given area. /// - /// `theme` supplies the title, gutter, body, prompt-overlay, and + /// `theme` supplies the title, body, prompt-overlay, and /// status-line colours so the editor follows the active skin. pub(crate) fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme) { // When the F9 menu bar is open, reserve the top row for it @@ -89,7 +89,7 @@ impl Editor { }; let marked_fg = editor_marked.map(|p| p.fg).unwrap_or(theme.marked_fg); let marked_bg = editor_marked.map(|p| p.bg).unwrap_or(theme.marked_bg); - let linestate_fg = editor_linestate.map(|p| p.fg).unwrap_or(theme.cursor_fg); + let cur_line_fg = editor_linestate.map(|p| p.fg).unwrap_or(theme.cursor_fg); let frame_fg = editor_frameactive.map(|p| p.fg).unwrap_or(theme.title_fg); let margin_fg = editor_rightmargin.map(|p| p.fg).unwrap_or(frame_fg); let margin_bg = editor_rightmargin.map(|p| p.bg).unwrap_or(body_bg); @@ -119,23 +119,7 @@ impl Editor { frame.render_widget(block, editor_area); let line_count = self.buffer.line_count(); - let gutter_chars = line_count.max(1).to_string().len().max(3) as u16; - let body_area = if gutter_chars < inner.width { - Rect::new( - inner.x + gutter_chars, - inner.y, - inner.width - gutter_chars, - inner.height, - ) - } else { - inner - }; - let gutter_area = Rect::new( - inner.x, - inner.y, - gutter_chars.min(inner.width), - inner.height, - ); + let body_area = inner; self.view.ensure_cursor_visible( &self.buffer, @@ -205,7 +189,7 @@ impl Editor { Style::default().fg(bookmark_fg).bg(bookmark_bg) } } else if cursor_line == line_idx { - Style::default().fg(linestate_fg).bg(cur_line_bg) + Style::default().fg(cur_line_fg).bg(cur_line_bg) } else { Style::default().fg(body_fg).bg(body_bg) }; @@ -319,38 +303,6 @@ impl Editor { } frame.render_widget(Paragraph::new(body_lines), body_area); - if gutter_chars < inner.width { - let gutter_lines: Vec = visible_wrapped - .iter() - .copied() - .map(|(line_idx, wrap_row)| { - if line_idx >= line_count { - return Line::from(Span::styled( - "~", - Style::default().fg(frame_fg).bg(body_bg), - )); - } - let text = if wrap_row > 0 { - " ".repeat(gutter_chars as usize) - } else { - let num = if self.relative_lines { - (line_idx as i64 - cursor_line as i64).unsigned_abs() - } else { - line_idx as u64 + 1 - }; - format!("{:>w$}", num, w = gutter_chars as usize) - }; - let style = if line_idx == cursor_line { - Style::default().fg(linestate_fg).bg(cur_line_bg) - } else { - Style::default().fg(frame_fg).bg(body_bg) - }; - Line::from(Span::styled(text, style)) - }) - .collect(); - frame.render_widget(Paragraph::new(gutter_lines), gutter_area); - } - if body_area.width > 0 { let margin_area = Rect::new( body_area.x + body_area.width - 1, @@ -712,7 +664,6 @@ impl Editor { ]), ("View", &[ ("Ctrl-S", "Toggle syntax highlight"), - ("Alt-N", "Toggle line numbers"), ("Ctrl-F1", "Toggle code fold"), ("Alt-R", "Redo"), ("Alt-Tab", "Word completion"), @@ -1114,7 +1065,7 @@ fn visual_width(ch: char, col: usize, tab_width: usize) -> usize { /// mid-word at the current column. /// /// Tabs are counted as their visual width (next `tab_width` boundary). -/// Empty lines always count as 1 visual row (so the gutter shows `~`). +/// Empty lines always count as 1 visual row. fn count_wrapped_rows(line_bytes: &[u8], body_width: usize, tab_width: usize) -> usize { if body_width == 0 { return 1; diff --git a/local/sources/relibc b/local/sources/relibc index fc158b3611..01807f6fa7 160000 --- a/local/sources/relibc +++ b/local/sources/relibc @@ -1 +1 @@ -Subproject commit fc158b36111fe199447aa2176d7b526c4453ad67 +Subproject commit 01807f6fa7d26f51fa163996fd6e78dc80137721 diff --git a/local/sources/syscall b/local/sources/syscall index c59951c038..9fad5e653c 160000 --- a/local/sources/syscall +++ b/local/sources/syscall @@ -1 +1 @@ -Subproject commit c59951c03842e0bfc0b2027e2c572c4c1d7ec802 +Subproject commit 9fad5e653c839d5d19fb0265cc6023f04a820ec7