diff --git a/helix-core/src/register.rs b/helix-core/src/register.rs index b39e4034..7fa34644 100644 --- a/helix-core/src/register.rs +++ b/helix-core/src/register.rs @@ -69,6 +69,10 @@ impl Registers { self.get(name).map(|reg| reg.read()) } + pub fn first(&self, name: char) -> Option<&String> { + self.read(name).and_then(|entries| entries.first()) + } + pub fn inner(&self) -> &HashMap { &self.inner } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index e7efa6c3..e2ef8f2a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1488,7 +1488,7 @@ fn select_regex(cx: &mut Context) { Some(reg), ui::completers::none, move |view, doc, regex, event| { - if event != PromptEvent::Update { + if !matches!(event, PromptEvent::Update | PromptEvent::Validate) { return; } let text = doc.text().slice(..); @@ -1509,7 +1509,7 @@ fn split_selection(cx: &mut Context) { Some(reg), ui::completers::none, move |view, doc, regex, event| { - if event != PromptEvent::Update { + if !matches!(event, PromptEvent::Update | PromptEvent::Validate) { return; } let text = doc.text().slice(..); @@ -1657,7 +1657,7 @@ fn searcher(cx: &mut Context, direction: Direction) { .collect() }, move |view, doc, regex, event| { - if event != PromptEvent::Update { + if !matches!(event, PromptEvent::Update | PromptEvent::Validate) { return; } search_impl( @@ -3563,7 +3563,7 @@ fn keep_or_remove_selections_impl(cx: &mut Context, remove: bool) { Some(reg), ui::completers::none, move |view, doc, regex, event| { - if event != PromptEvent::Update { + if !matches!(event, PromptEvent::Update | PromptEvent::Validate) { return; } let text = doc.text().slice(..); diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 2dca870b..6dea2192 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -63,18 +63,8 @@ pub fn regex_prompt( doc.set_selection(view.id, snapshot.clone()); view.offset = offset_snapshot; } - PromptEvent::Validate => match Regex::new(input) { - Ok(regex) => { - let (view, doc) = current!(cx.editor); - // Equivalent to push_jump to store selection just before jump - view.jumps.push((doc_id, snapshot.clone())); - fun(view, doc, regex, event); - } - Err(_err) => (), // TODO: mark command line as error - }, - - PromptEvent::Update => { - // skip empty input, TODO: trigger default + PromptEvent::Update | PromptEvent::Validate => { + // skip empty input if input.is_empty() { return; } @@ -96,6 +86,11 @@ pub fn regex_prompt( // revert state to what it was before the last update doc.set_selection(view.id, snapshot.clone()); + if event == PromptEvent::Validate { + // Equivalent to push_jump to store selection just before jump + view.jumps.push((doc_id, snapshot.clone())); + } + fun(view, doc, regex, event); view.ensure_cursor_in_view(doc, config.scrolloff); diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index a5be33ff..64154bae 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -442,10 +442,21 @@ impl Prompt { let line = area.height - 1; // render buffer text surface.set_string(area.x, area.y + line, &self.prompt, prompt_color); + + let input: Cow = if self.line.is_empty() { + // latest value in the register list + self.history_register + .and_then(|reg| cx.editor.registers.first(reg).cloned()) // TODO: can we avoid cloning? + .map(|entry| entry.into()) + .unwrap_or_else(|| Cow::from("")) + } else { + self.line.as_str().into() + }; + surface.set_string( area.x + self.prompt.len() as u16, area.y + line, - &self.line, + &input, prompt_color, ); } @@ -510,7 +521,18 @@ impl Component for Prompt { self.recalculate_completion(cx.editor); self.exit_selection(); } else { - (self.callback_fn)(cx, &self.line, PromptEvent::Validate); + // handle executing with last command in history if nothing entered + let input: Cow = if self.line.is_empty() { + // latest value in the register list + self.history_register + .and_then(|reg| cx.editor.registers.first(reg).cloned()) + .map(|entry| entry.into()) + .unwrap_or_else(|| Cow::from("")) + } else { + self.line.as_str().into() + }; + + (self.callback_fn)(cx, &input, PromptEvent::Validate); if let Some(register) = self.history_register { // store in history