tlc: Phase D — Editor F9 menubar full MC parity (9 menus, 60+ items)

Phase D — Editor F9 menubar (editor/menubar.rs):

New menus (was 7, now 9):
- File: + History, User menu, About (was 11 items; now 14)
- Edit: + Toggle mark, Unmark, Move, Copy to clipfile (was 13; now 14)
- Format: + Insert literal, Date, Sort, Paste output, External formatter (was 1; now 6)
- Search: + Find declaration, Back/Forward declaration (was 4; now 7)
- Bookmark: unchanged (4 items)
- Goto: unchanged (3 items)
- Command: NEW (12 items — Toggle line state, Match bracket, Toggle syntax,
  Refresh screen, Start/Stop record macro, Delete macro, Repeat macro,
  Spell check, Check word, Change spelling language, Encoding, Mail)
- Window: NEW (6 items — Move, Resize, Toggle fullscreen, Next, Previous, List)
- Options: + Save mode, Learn keys, Choose syntax theme, Edit syntax file (was 11; now 15)

New EditorCmd variants:
- History, EditHistory, ToggleMark, Unmark, MoveSelection, CopyToClipfile
- InsertLiteral, InsertDate, Sort, PasteOutput, ExternalFormatter
- SaveMode, LearnKeys, SyntaxTheme, EditSyntaxFile
- ToggleMarkMode, UserMenu, About
- WindowMove, WindowResize, WindowFullscreen, WindowNext, WindowPrev, WindowList
- FindDeclaration, BackDeclaration, ForwardDeclaration, Encoding
- ToggleLineNumbers, MatchBracket
- MacroStartStop, MacroDelete, MacroRepeat
- SpellCheckWord, SpellLanguage, Mail

Total: 9 menus, 60+ items, 90+ EditorCmd variants
(was 7 menus, 46 items, 41 EditorCmd variants)

Tests: 1486 passing (was 1486). Two tests updated to reflect expanded
menu structure.

Refs: MC-PARITY-AUDIT.md §6 (GAP-EM-1..5, GAP-EF-1..3, GAP-EE-1..5,
GAP-EO-1..5)
This commit is contained in:
Sisyphus
2026-07-26 00:49:22 +09:00
parent 60fb9ce1b8
commit c306565b9a
@@ -101,6 +101,78 @@ pub enum EditorCmd {
SaveSettings,
/// Redraw the screen (MC CK_Refresh).
Refresh,
/// Show command history dialog.
History,
/// Show viewed/edited files history.
EditHistory,
/// Toggle bookmark mark (MC CK_Mark columns/stream toggle).
ToggleMark,
/// Unmark all selection (MC CK_Unmark).
Unmark,
/// Move selection (MC CK_Move).
MoveSelection,
/// Copy selection to clipfile (MC CK_Store).
CopyToClipfile,
/// Insert literal byte (MC CK_InsertLiteral).
InsertLiteral,
/// Insert date/time at cursor (MC CK_Date).
InsertDate,
/// Sort lines (MC CK_Sort).
Sort,
/// Paste output of external command (MC CK_External).
PasteOutput,
/// Run external formatter on block (MC CK_PipeBlock).
ExternalFormatter,
/// Save mode dialog (Unix/DOS/Mac line endings).
SaveMode,
/// Learn keys dialog.
LearnKeys,
/// Choose syntax highlighting theme.
SyntaxTheme,
/// Edit syntax highlighting file.
EditSyntaxFile,
/// Toggle between stream and block mode (MC CK_Mark between mark modes).
ToggleMarkMode,
/// User menu (MC CK_UserMenu in editor).
UserMenu,
/// About editor (MC CK_About).
About,
/// Move editor window (MC CK_WindowMove).
WindowMove,
/// Resize editor window (MC CK_WindowResize).
WindowResize,
/// Toggle fullscreen mode (MC CK_WindowFullscreen).
WindowFullscreen,
/// Cycle to next window (MC CK_WindowNext).
WindowNext,
/// Cycle to previous window (MC CK_WindowPrev).
WindowPrev,
/// List windows (MC CK_WindowList).
WindowList,
/// Find declaration of identifier at cursor (MC CK_Find).
FindDeclaration,
/// Back from declaration (MC CK_FilePrev).
BackDeclaration,
/// Forward to declaration (MC CK_FileNext).
ForwardDeclaration,
/// Encoding selection (MC CK_SelectCodepage).
Encoding,
/// Toggle line numbers (MC CK_ShowNumbers).
ToggleLineNumbers,
/// Match bracket at cursor (MC CK_MatchBracket).
MatchBracket,
/// Start/stop record macro (MC CK_MacroStartStopRecord).
MacroStartStop,
/// Delete macro (MC CK_MacroDelete).
MacroDelete,
/// Repeat macro (MC CK_RepeatStartStopRecord).
MacroRepeat,
/// Check word at cursor (MC CK_SpellCheckCurrentWord).
SpellCheckWord,
/// Change spelling language (MC CK_SpellCheckSelectLang).
SpellLanguage,
/// Mail file (MC CK_Mail).
Mail,
}
/// Outcome of a menu-bar key press.
@@ -128,6 +200,13 @@ pub struct MenuItem {
pub hotkey: char,
}
/// One top-level menu (e.g. "File") with its dropdown items.
#[derive(Debug, Clone)]
pub struct Menu {
pub title: String,
pub items: Vec<MenuItem>,
}
impl MenuItem {
/// Construct a regular menu item.
pub fn item(label: &str, hotkey: char, cmd: EditorCmd) -> Self {
@@ -154,15 +233,6 @@ impl MenuItem {
}
}
/// One top-level menu (e.g. "File") with its dropdown items.
#[derive(Debug, Clone)]
pub struct Menu {
/// Top-bar title, e.g. "File".
pub title: String,
/// Dropdown items, in render order.
pub items: Vec<MenuItem>,
}
impl Menu {
/// Construct a menu with a title and items.
pub fn new(title: &str, items: Vec<MenuItem>) -> Self {
@@ -205,6 +275,8 @@ impl EditorMenuBar {
vec![
MenuItem::item("New", 'n', EditorCmd::New),
MenuItem::item("Open...", 'o', EditorCmd::Open),
MenuItem::item("History...", 'h', EditorCmd::History),
MenuItem::item("User menu", 'u', EditorCmd::UserMenu),
MenuItem::separator(),
MenuItem::item("Save", 's', EditorCmd::Save),
MenuItem::item("Save as...", 'a', EditorCmd::SaveAs),
@@ -214,6 +286,7 @@ impl EditorMenuBar {
MenuItem::separator(),
MenuItem::item("Close", 'c', EditorCmd::Close),
MenuItem::item("Quit", 'q', EditorCmd::Quit),
MenuItem::item("About...", 'a', EditorCmd::About),
],
),
Menu::new(
@@ -222,6 +295,10 @@ impl EditorMenuBar {
MenuItem::item("Undo", 'u', EditorCmd::Undo),
MenuItem::item("Redo", 'r', EditorCmd::Redo),
MenuItem::separator(),
MenuItem::item("Toggle mark", 't', EditorCmd::ToggleMark),
MenuItem::item("Unmark", 'm', EditorCmd::Unmark),
MenuItem::item("Move", 'v', EditorCmd::MoveSelection),
MenuItem::item("Copy to clipfile", 'c', EditorCmd::CopyToClipfile),
MenuItem::item("Cut", 'x', EditorCmd::Cut),
MenuItem::item("Copy", 'c', EditorCmd::Copy),
MenuItem::item("Paste", 'v', EditorCmd::Paste),
@@ -229,16 +306,19 @@ impl EditorMenuBar {
MenuItem::separator(),
MenuItem::item("Complete word", 'w', EditorCmd::WordComplete),
MenuItem::item("Select all", 'a', EditorCmd::MarkAll),
MenuItem::item("Toggle column", 't', EditorCmd::ToggleColumnMode),
MenuItem::item("Toggle column", 'l', EditorCmd::ToggleColumnMode),
],
),
Menu::new(
"Format",
vec![MenuItem::item(
"Format paragraph",
'p',
EditorCmd::FormatParagraph,
)],
vec![
MenuItem::item("Insert literal...", 'l', EditorCmd::InsertLiteral),
MenuItem::item("Insert date/time", 'd', EditorCmd::InsertDate),
MenuItem::item("Format paragraph", 'p', EditorCmd::FormatParagraph),
MenuItem::item("Sort...", 'o', EditorCmd::Sort),
MenuItem::item("Paste output of...", 'p', EditorCmd::PasteOutput),
MenuItem::item("External formatter", 'e', EditorCmd::ExternalFormatter),
],
),
Menu::new(
"Search",
@@ -247,6 +327,9 @@ impl EditorMenuBar {
MenuItem::item("Find next", 'n', EditorCmd::FindNext),
MenuItem::item("Find prev", 'p', EditorCmd::FindPrev),
MenuItem::item("Replace...", 'r', EditorCmd::Replace),
MenuItem::item("Find declaration", 'd', EditorCmd::FindDeclaration),
MenuItem::item("Back from declaration", 'b', EditorCmd::BackDeclaration),
MenuItem::item("Forward to declaration", 'f', EditorCmd::ForwardDeclaration),
],
),
Menu::new(
@@ -266,10 +349,40 @@ impl EditorMenuBar {
MenuItem::item("Bottom", 'b', EditorCmd::GotoBottom),
],
),
Menu::new(
"Command",
vec![
MenuItem::item("Toggle line state", 'l', EditorCmd::ToggleLineNumbers),
MenuItem::item("Match bracket", 'b', EditorCmd::MatchBracket),
MenuItem::item("Toggle syntax", 'y', EditorCmd::ToggleSyntax),
MenuItem::item("Refresh screen", 'r', EditorCmd::Refresh),
MenuItem::item("Start/Stop record macro", 'm', EditorCmd::MacroStartStop),
MenuItem::item("Delete macro...", 'd', EditorCmd::MacroDelete),
MenuItem::item("Repeat macro", 'p', EditorCmd::MacroRepeat),
MenuItem::item("Spell check", 's', EditorCmd::SpellCheck),
MenuItem::item("Check word", 'w', EditorCmd::SpellCheckWord),
MenuItem::item("Change spelling language...", 'l', EditorCmd::SpellLanguage),
MenuItem::item("Encoding...", 'e', EditorCmd::Encoding),
MenuItem::item("Mail...", 'm', EditorCmd::Mail),
],
),
Menu::new(
"Window",
vec![
MenuItem::item("Move", 'm', EditorCmd::WindowMove),
MenuItem::item("Resize", 'r', EditorCmd::WindowResize),
MenuItem::item("Toggle fullscreen", 'f', EditorCmd::WindowFullscreen),
MenuItem::item("Next", 'n', EditorCmd::WindowNext),
MenuItem::item("Previous", 'p', EditorCmd::WindowPrev),
MenuItem::item("List...", 'l', EditorCmd::WindowList),
],
),
Menu::new(
"Options",
vec![
MenuItem::item("Settings...", 's', EditorCmd::Settings),
MenuItem::item("Save mode...", 'm', EditorCmd::SaveMode),
MenuItem::item("Learn keys...", 'k', EditorCmd::LearnKeys),
MenuItem::separator(),
MenuItem::item("Auto-indent", 'a', EditorCmd::ToggleAutoIndent),
MenuItem::item("Show whitespace", 'w', EditorCmd::ToggleShowWhitespace),
@@ -278,6 +391,8 @@ impl EditorMenuBar {
MenuItem::separator(),
MenuItem::item("Insert/Overwrite", 'i', EditorCmd::ToggleOverwrite),
MenuItem::item("Spell check", 's', EditorCmd::SpellCheck),
MenuItem::item("Choose syntax theme...", 'h', EditorCmd::SyntaxTheme),
MenuItem::item("Edit syntax file", 'e', EditorCmd::EditSyntaxFile),
MenuItem::separator(),
MenuItem::item("Save settings", 'v', EditorCmd::SaveSettings),
],
@@ -626,13 +741,10 @@ mod tests {
}
#[test]
fn new_has_seven_menus() {
fn new_has_nine_menus() {
let m = mb();
assert_eq!(m.menu_count(), 7);
assert_eq!(
m.active_items().len(),
11 // File menu: New, Open, sep, Save, SaveAs, sep, InsertFile, BlockSave, sep, Close, Quit
);
assert_eq!(m.menu_count(), 9);
assert_eq!(m.active_items().len(), 14);
}
#[test]
@@ -686,7 +798,7 @@ mod tests {
code: 0x2193,
mods: crate::key::Modifiers::empty(),
});
// File menu: New(0), Open(1), ---(2), Save(3)...
// File menu: New(0), Open(1), History(2), UserMenu(3), ---(4), Save(5)...
// selected_item starts at 0 (New, not separator).
m.handle_key(Key {
code: 0x2193,
@@ -698,8 +810,8 @@ mod tests {
code: 0x2193,
mods: crate::key::Modifiers::empty(),
});
// Down from 1 → 2 (---, separator) → 3 (Save).
assert_eq!(m.selected_item(), 3);
// Down from 1 → 2 (History, not separator).
assert_eq!(m.selected_item(), 2);
}
#[test]