on master help sign in
prompt: If submitting empty prompt, use default (last used)
b14c258Blaž Hrastnik
helix-core/src/register.rs+4
@@ -69,6 +69,10 @@ impl Registers {
69 self.get(name).map(|reg| reg.read())
69 self.get(name).map(|reg| reg.read())
70 }
70 }
71
71
72+ pub fn first(&self, name: char) -> Option<&String> {
73+ self.read(name).and_then(|entries| entries.first())
74+ }
75+
72 pub fn inner(&self) -> &HashMap<char, Register> {
76 pub fn inner(&self) -> &HashMap<char, Register> {
73 &self.inner
77 &self.inner
74 }
78 }
helix-term/src/commands.rs+4−4
@@ -1488,7 +1488,7 @@ fn select_regex(cx: &mut Context) {
1488 Some(reg),
1488 Some(reg),
1489 ui::completers::none,
1489 ui::completers::none,
1490 move |view, doc, regex, event| {
1490 move |view, doc, regex, event| {
1491− if event != PromptEvent::Update {
1491+ if !matches!(event, PromptEvent::Update | PromptEvent::Validate) {
1492 return;
1492 return;
1493 }
1493 }
1494 let text = doc.text().slice(..);
1494 let text = doc.text().slice(..);
@@ -1509,7 +1509,7 @@ fn split_selection(cx: &mut Context) {
1509 Some(reg),
1509 Some(reg),
1510 ui::completers::none,
1510 ui::completers::none,
1511 move |view, doc, regex, event| {
1511 move |view, doc, regex, event| {
1512− if event != PromptEvent::Update {
1512+ if !matches!(event, PromptEvent::Update | PromptEvent::Validate) {
1513 return;
1513 return;
1514 }
1514 }
1515 let text = doc.text().slice(..);
1515 let text = doc.text().slice(..);
@@ -1657,7 +1657,7 @@ fn searcher(cx: &mut Context, direction: Direction) {
1657 .collect()
1657 .collect()
1658 },
1658 },
1659 move |view, doc, regex, event| {
1659 move |view, doc, regex, event| {
1660− if event != PromptEvent::Update {
1660+ if !matches!(event, PromptEvent::Update | PromptEvent::Validate) {
1661 return;
1661 return;
1662 }
1662 }
1663 search_impl(
1663 search_impl(
@@ -3563,7 +3563,7 @@ fn keep_or_remove_selections_impl(cx: &mut Context, remove: bool) {
3563 Some(reg),
3563 Some(reg),
3564 ui::completers::none,
3564 ui::completers::none,
3565 move |view, doc, regex, event| {
3565 move |view, doc, regex, event| {
3566− if event != PromptEvent::Update {
3566+ if !matches!(event, PromptEvent::Update | PromptEvent::Validate) {
3567 return;
3567 return;
3568 }
3568 }
3569 let text = doc.text().slice(..);
3569 let text = doc.text().slice(..);
helix-term/src/ui/mod.rs+7−12
@@ -63,18 +63,8 @@ pub fn regex_prompt(
63 doc.set_selection(view.id, snapshot.clone());
63 doc.set_selection(view.id, snapshot.clone());
64 view.offset = offset_snapshot;
64 view.offset = offset_snapshot;
65 }
65 }
66− PromptEvent::Validate => match Regex::new(input) {
66+ PromptEvent::Update | PromptEvent::Validate => {
67− Ok(regex) => {
68− let (view, doc) = current!(cx.editor);
69− // Equivalent to push_jump to store selection just before jump
70− view.jumps.push((doc_id, snapshot.clone()));
71− fun(view, doc, regex, event);
72− }
73− Err(_err) => (), // TODO: mark command line as error
74− },
75−
76− PromptEvent::Update => {
77− // skip empty input, TODO: trigger default
67+ // skip empty input
78 if input.is_empty() {
68 if input.is_empty() {
79 return;
69 return;
80 }
70 }
@@ -96,6 +86,11 @@ pub fn regex_prompt(
96 // revert state to what it was before the last update
86 // revert state to what it was before the last update
97 doc.set_selection(view.id, snapshot.clone());
87 doc.set_selection(view.id, snapshot.clone());
98
88
89+ if event == PromptEvent::Validate {
90+ // Equivalent to push_jump to store selection just before jump
91+ view.jumps.push((doc_id, snapshot.clone()));
92+ }
93+
99 fun(view, doc, regex, event);
94 fun(view, doc, regex, event);
100
95
101 view.ensure_cursor_in_view(doc, config.scrolloff);
96 view.ensure_cursor_in_view(doc, config.scrolloff);
helix-term/src/ui/prompt.rs+24−2
@@ -442,10 +442,21 @@ impl Prompt {
442 let line = area.height - 1;
442 let line = area.height - 1;
443 // render buffer text
443 // render buffer text
444 surface.set_string(area.x, area.y + line, &self.prompt, prompt_color);
444 surface.set_string(area.x, area.y + line, &self.prompt, prompt_color);
445+
446+ let input: Cow<str> = if self.line.is_empty() {
447+ // latest value in the register list
448+ self.history_register
449+ .and_then(|reg| cx.editor.registers.first(reg).cloned()) // TODO: can we avoid cloning?
450+ .map(|entry| entry.into())
451+ .unwrap_or_else(|| Cow::from(""))
452+ } else {
453+ self.line.as_str().into()
454+ };
455+
445 surface.set_string(
456 surface.set_string(
446 area.x + self.prompt.len() as u16,
457 area.x + self.prompt.len() as u16,
447 area.y + line,
458 area.y + line,
448− &self.line,
459+ &input,
449 prompt_color,
460 prompt_color,
450 );
461 );
451 }
462 }
@@ -510,7 +521,18 @@ impl Component for Prompt {
510 self.recalculate_completion(cx.editor);
521 self.recalculate_completion(cx.editor);
511 self.exit_selection();
522 self.exit_selection();
512 } else {
523 } else {
524+ // handle executing with last command in history if nothing entered
525+ let input: Cow<str> = if self.line.is_empty() {
526+ // latest value in the register list
527+ self.history_register
528+ .and_then(|reg| cx.editor.registers.first(reg).cloned())
529+ .map(|entry| entry.into())
530+ .unwrap_or_else(|| Cow::from(""))
531+ } else {
532+ self.line.as_str().into()
533+ };
534+
513− (self.callback_fn)(cx, &self.line, PromptEvent::Validate);
535+ (self.callback_fn)(cx, &input, PromptEvent::Validate);
514
536
515 if let Some(register) = self.history_register {
537 if let Some(register) = self.history_register {
516 // store in history
538 // store in history