feat: command history navigation with up/down arrow keys
CommandLine now records every submitted command in a recall list (up to 50 entries). Pressing ↑ in the command input walks back through the list, ↓ moves forward, and returning to the newest position restores the draft text the user had typed before navigating. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0868a1719c
commit
80ca095121
4 changed files with 76 additions and 1 deletions
|
|
@ -176,6 +176,10 @@ pub enum Message {
|
|||
CommandInput(String),
|
||||
CommandSubmit,
|
||||
Command(String),
|
||||
/// Recall previous command in history (↑ arrow key).
|
||||
CommandHistoryPrev,
|
||||
/// Recall next command in history (↓ arrow key).
|
||||
CommandHistoryNext,
|
||||
ToggleLayers,
|
||||
LayerToggleVisible(usize),
|
||||
LayerToggleLock(usize),
|
||||
|
|
|
|||
|
|
@ -248,7 +248,21 @@ impl H7CAD {
|
|||
Task::none()
|
||||
}
|
||||
|
||||
Message::CommandInput(s) => { self.command_line.input = s; Task::none() }
|
||||
Message::CommandInput(s) => {
|
||||
// Any manual typing resets the history recall cursor.
|
||||
self.command_line.input = s;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::CommandHistoryPrev => {
|
||||
self.command_line.history_prev();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::CommandHistoryNext => {
|
||||
self.command_line.history_next();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::CommandSubmit => {
|
||||
let i = self.active_tab;
|
||||
|
|
|
|||
|
|
@ -320,6 +320,12 @@ impl H7CAD {
|
|||
{
|
||||
Some(Message::DeleteSelected)
|
||||
}
|
||||
keyboard::Key::Named(keyboard::key::Named::ArrowUp) => {
|
||||
Some(Message::CommandHistoryPrev)
|
||||
}
|
||||
keyboard::Key::Named(keyboard::key::Named::ArrowDown) => {
|
||||
Some(Message::CommandHistoryNext)
|
||||
}
|
||||
keyboard::Key::Named(keyboard::key::Named::F3) => {
|
||||
Some(Message::ToggleSnapEnabled)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ const MAX_HISTORY: usize = 64;
|
|||
pub struct CommandLine {
|
||||
pub input: String,
|
||||
pub history: Vec<HistoryEntry>,
|
||||
/// Commands the user has typed (for ↑/↓ recall).
|
||||
cmd_recall: Vec<String>,
|
||||
/// Current position in `cmd_recall` while navigating (None = not navigating).
|
||||
recall_cursor: Option<usize>,
|
||||
/// Saved draft input before the user started navigating history.
|
||||
recall_draft: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -39,15 +45,60 @@ impl CommandLine {
|
|||
cl.push_info("Type a command or use the ribbon. Open OBJ: INSERT tab.");
|
||||
cl
|
||||
}
|
||||
|
||||
pub fn submit(&mut self) -> Option<String> {
|
||||
let cmd = self.input.trim().to_uppercase();
|
||||
if cmd.is_empty() {
|
||||
return None;
|
||||
}
|
||||
// Record in recall list (avoid duplicates at the top).
|
||||
let raw = self.input.trim().to_string();
|
||||
if self.cmd_recall.last().map(|s| s.as_str()) != Some(&raw) {
|
||||
self.cmd_recall.push(raw);
|
||||
if self.cmd_recall.len() > 50 {
|
||||
self.cmd_recall.remove(0);
|
||||
}
|
||||
}
|
||||
self.recall_cursor = None;
|
||||
self.recall_draft.clear();
|
||||
self.push_command(&self.input.clone());
|
||||
self.input.clear();
|
||||
Some(cmd)
|
||||
}
|
||||
|
||||
/// Navigate to the previous command in recall history (↑).
|
||||
pub fn history_prev(&mut self) {
|
||||
if self.cmd_recall.is_empty() {
|
||||
return;
|
||||
}
|
||||
let cursor = match self.recall_cursor {
|
||||
None => {
|
||||
self.recall_draft = self.input.clone();
|
||||
self.cmd_recall.len() - 1
|
||||
}
|
||||
Some(c) if c > 0 => c - 1,
|
||||
Some(c) => c,
|
||||
};
|
||||
self.recall_cursor = Some(cursor);
|
||||
self.input = self.cmd_recall[cursor].clone();
|
||||
}
|
||||
|
||||
/// Navigate to the next command in recall history (↓).
|
||||
pub fn history_next(&mut self) {
|
||||
match self.recall_cursor {
|
||||
None => {}
|
||||
Some(c) if c + 1 < self.cmd_recall.len() => {
|
||||
let next = c + 1;
|
||||
self.recall_cursor = Some(next);
|
||||
self.input = self.cmd_recall[next].clone();
|
||||
}
|
||||
Some(_) => {
|
||||
self.recall_cursor = None;
|
||||
self.input = self.recall_draft.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_command(&mut self, cmd: &str) {
|
||||
self.push(EntryKind::Command, format!("Command: {cmd}"));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue