Files
TerminalBasic/crates/tb-ide/src/commands.rs

344 lines
9.2 KiB
Rust

//! Eine Befehlsliste für Menü, Tastatur und Statusleiste.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Command {
NewProject,
OpenProject,
SaveProject,
NewForm,
NewModule,
AddFile,
RemoveFile,
SaveFile,
SaveAs,
LoadText,
SaveText,
Print,
Shell,
Exit,
Undo,
Cut,
Copy,
Paste,
Clear,
Procedures,
PreviousCode,
Diagnostics,
NewSub,
NewFunction,
Events,
Code,
Form,
NextStatement,
OutputScreen,
IncludedFile,
IncludedLines,
MenuBar,
Grid,
Find,
SelectedText,
FindNext,
Replace,
Start,
Restart,
Continue,
Pause,
CommandLine,
MakeExe,
MakeLibrary,
Startup,
AddWatch,
InstantWatch,
Watchpoint,
DeleteWatch,
DeleteWatches,
Trace,
History,
Breakpoint,
ClearBreakpoints,
BreakErrors,
SetStatement,
RunToCursor,
Step,
ProcedureStep,
HistoryBack,
HistoryForward,
Display,
Paths,
RightMouse,
SaveOptions,
SyntaxChecking,
NewWindow,
Arrange,
Calls,
Debug,
HelpWindow,
Immediate,
Output,
Project,
Palette,
MenuDesign,
Toolbox,
Tool(&'static str),
HelpIndex,
HelpContents,
Keyboard,
Topic,
UsingHelp,
Tutorial,
About,
NextWindow,
PreviousWindow,
CloseWindow,
MoveWindow,
SizeWindow,
Minimize,
Maximize,
Restore,
ControlMenu,
FocusWindow(u64),
}
impl Command {
pub fn feature_phase(self) -> Option<u8> {
use Command::*;
match self {
NextStatement | AddWatch | InstantWatch | Watchpoint | DeleteWatch | DeleteWatches
| Trace | History | Breakpoint | ClearBreakpoints | BreakErrors | SetStatement
| RunToCursor | Step | ProcedureStep | HistoryBack | HistoryForward => Some(6),
HelpIndex | HelpContents | Keyboard | Topic | UsingHelp | Tutorial => Some(7),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct Item {
/// & markiert das sichtbare Mnemonic, … einen Dialog.
pub label: String,
pub command: Option<Command>,
}
impl Item {
pub fn text(&self) -> String {
self.label.replace('&', "")
}
pub fn mnemonic(&self) -> Option<char> {
self.label
.split_once('&')?
.1
.chars()
.next()
.map(|c| c.to_ascii_lowercase())
}
}
pub struct Menu {
pub title: &'static str,
pub mnemonic: char,
pub items: Vec<Item>,
}
pub fn menus(designer: bool) -> Vec<Menu> {
use Command::*;
let item = |label: &str, command| Item {
label: label.into(),
command: Some(command),
};
let sep = || Item {
label: "────────".into(),
command: None,
};
let menu = |title, mnemonic, items| Menu {
title,
mnemonic,
items,
};
let mut result = vec![
menu(
"File",
'f',
vec![
item("&New Project", NewProject),
item("&Open Project…", OpenProject),
item("Save &Project", SaveProject),
sep(),
item("New &Form", NewForm),
item("New &Module…", NewModule),
item("&Add File…", AddFile),
item("&Remove File…", RemoveFile),
item("&Save File", SaveFile),
item("Sa&ve File As…", SaveAs),
sep(),
item("&Load Text…", LoadText),
item("Save &Text…", SaveText),
sep(),
item("Pr&int…", Print),
item("S&hell", Shell),
sep(),
item("E&xit", Exit),
],
),
menu(
"Edit",
'e',
vec![
item("&Undo", Undo),
sep(),
item("Cu&t", Cut),
item("&Copy", Copy),
item("&Paste", Paste),
item("C&lear", Clear),
sep(),
item("New &Sub…", NewSub),
item("New &Function…", NewFunction),
item("&Event Procedures…", Events),
],
),
menu(
"View",
'v',
vec![
item("&Code…", Code),
item("&Procedures…", Procedures),
item("Diagno&stics…", Diagnostics),
item("&Form…", Form),
sep(),
item("&Next Statement", NextStatement),
item("&Output Screen", OutputScreen),
sep(),
item("&Included File", IncludedFile),
item("Included &Lines", IncludedLines),
],
),
];
if designer {
result[2]
.items
.extend([sep(), item("&Menu Bar", MenuBar), item("&Grid Lines", Grid)]);
result.push(menu("Tools", 't', {
let mut used = std::collections::BTreeSet::new();
crate::designer::tools()
.into_iter()
.map(|(name, _, _)| {
let mut label = name.to_owned();
if let Some((at, c)) = name
.char_indices()
.find(|(_, c)| !used.contains(&c.to_ascii_lowercase()))
{
used.insert(c.to_ascii_lowercase());
label.insert(at, '&');
} else {
let c = ('1'..='9').find(|c| !used.contains(c)).unwrap();
used.insert(c);
label = format!("&{c} {label}");
}
Item {
label,
command: Some(Tool(name)),
}
})
.collect()
}));
} else {
result.extend([
menu(
"Search",
's',
vec![
item("&Find…", Find),
item("&Selected Text", SelectedText),
item("&Repeat Last Find", FindNext),
item("&Change…", Replace),
],
),
menu(
"Run",
'r',
vec![
item("&Start", Start),
item("&Restart", Restart),
item("&Continue", Continue),
item("&Pause (Ctrl+Break)", Pause),
item("Modify COMMAND&$…", CommandLine),
sep(),
item("Make &EXE File…", MakeExe),
item("Make &Library…", MakeLibrary),
sep(),
item("Set Start-&up File…", Startup),
],
),
menu(
"Debug",
'd',
vec![
item("&Add Watch…", AddWatch),
item("&Instant Watch…", InstantWatch),
item("&Watchpoint…", Watchpoint),
item("&Delete Watch…", DeleteWatch),
item("Delete A&ll Watch", DeleteWatches),
sep(),
item("&Trace On", Trace),
item("&History On", History),
sep(),
item("Toggle &Breakpoint", Breakpoint),
item("&Clear All Breakpoints", ClearBreakpoints),
item("Break on &Errors", BreakErrors),
item("Set &Next Statement", SetStatement),
],
),
]);
}
result.push(menu(
"Options",
'o',
vec![
item("&Display…", Display),
item("Set &Paths…", Paths),
item("&Right Mouse…", RightMouse),
item("&Save…", SaveOptions),
item("S&yntax Checking", SyntaxChecking),
],
));
result.push(if designer {
menu(
"Window",
'w',
vec![
item("&Color Palette", Palette),
item("&Menu Design Window", MenuDesign),
item("&Toolbox", Toolbox),
item("&Help", HelpWindow),
],
)
} else {
menu(
"Window",
'w',
vec![
item("&New Window", NewWindow),
item("&Arrange All", Arrange),
sep(),
item("&Calls", Calls),
item("&Debug", Debug),
item("&Help", HelpWindow),
item("&Immediate", Immediate),
item("&Output", Output),
item("&Project", Project),
sep(),
],
)
});
result.push(menu(
"Help",
'h',
vec![
item("&Index", HelpIndex),
item("&Contents", HelpContents),
sep(),
item("&Keyboard", Keyboard),
sep(),
item("&Topic", Topic),
item("&Using Help", UsingHelp),
item("Tuto&rial", Tutorial),
sep(),
item("&About…", About),
],
));
result
}