From 72cf86e4626c01c6ce2371c7b134ab7a7041620c Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 8 Sep 2021 14:52:09 +0900 Subject: Regex prompts should have a history with a specifiable register --- helix-term/src/commands.rs | 38 ++++++++++++++-------------- helix-term/src/ui/editor.rs | 4 +-- helix-term/src/ui/mod.rs | 9 +++---- helix-view/src/editor.rs | 6 ++--- helix-view/src/lib.rs | 2 -- helix-view/src/register_selection.rs | 48 ------------------------------------ 6 files changed, 29 insertions(+), 78 deletions(-) delete mode 100644 helix-view/src/register_selection.rs diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 38e65537..841af22a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -44,7 +44,7 @@ use once_cell::sync::Lazy; use serde::de::{self, Deserialize, Deserializer}; pub struct Context<'a> { - pub selected_register: helix_view::RegisterSelection, + pub register: Option, pub count: Option, pub editor: &'a mut Editor, @@ -1030,7 +1030,8 @@ fn select_all(cx: &mut Context) { } fn select_regex(cx: &mut Context) { - let prompt = ui::regex_prompt(cx, "select:".into(), move |view, doc, _, regex| { + let reg = cx.register.unwrap_or('/'); + let prompt = ui::regex_prompt(cx, "select:".into(), Some(reg), move |view, doc, regex| { let text = doc.text().slice(..); if let Some(selection) = selection::select_on_matches(text, doc.selection(view.id), ®ex) { @@ -1042,7 +1043,8 @@ fn select_regex(cx: &mut Context) { } fn split_selection(cx: &mut Context) { - let prompt = ui::regex_prompt(cx, "split:".into(), move |view, doc, _, regex| { + let reg = cx.register.unwrap_or('/'); + let prompt = ui::regex_prompt(cx, "split:".into(), Some(reg), move |view, doc, regex| { let text = doc.text().slice(..); let selection = selection::split_on_matches(text, doc.selection(view.id), ®ex); doc.set_selection(view.id, selection); @@ -1100,6 +1102,7 @@ fn search_impl(doc: &mut Document, view: &mut View, contents: &str, regex: &Rege // TODO: use one function for search vs extend fn search(cx: &mut Context) { + let reg = cx.register.unwrap_or('/'); let (_, doc) = current!(cx.editor); // TODO: could probably share with select_on_matches? @@ -1108,10 +1111,8 @@ fn search(cx: &mut Context) { // feed chunks into the regex yet let contents = doc.text().slice(..).to_string(); - let prompt = ui::regex_prompt(cx, "search:".into(), move |view, doc, registers, regex| { + let prompt = ui::regex_prompt(cx, "search:".into(), Some(reg), move |view, doc, regex| { search_impl(doc, view, &contents, ®ex, false); - // TODO: only store on enter (accept), not update - registers.write('/', vec![regex.as_str().to_string()]); }); cx.push_layer(Box::new(prompt)); @@ -1119,9 +1120,9 @@ fn search(cx: &mut Context) { fn search_next_impl(cx: &mut Context, extend: bool) { let (view, doc) = current!(cx.editor); - let registers = &mut cx.editor.registers; + let registers = &cx.editor.registers; if let Some(query) = registers.read('/') { - let query = query.first().unwrap(); + let query = query.last().unwrap(); let contents = doc.text().slice(..).to_string(); let regex = Regex::new(query).unwrap(); search_impl(doc, view, &contents, ®ex, extend); @@ -1141,7 +1142,7 @@ fn search_selection(cx: &mut Context) { let contents = doc.text().slice(..); let query = doc.selection(view.id).primary().fragment(contents); let regex = regex::escape(&query); - cx.editor.registers.write('/', vec![regex]); + cx.editor.registers.get_mut('/').push(regex); search_next(cx); } @@ -1200,7 +1201,7 @@ fn delete_selection_impl(reg: &mut Register, doc: &mut Document, view_id: ViewId } fn delete_selection(cx: &mut Context) { - let reg_name = cx.selected_register.name(); + let reg_name = cx.register.unwrap_or('"'); let (view, doc) = current!(cx.editor); let registers = &mut cx.editor.registers; let reg = registers.get_mut(reg_name); @@ -1213,7 +1214,7 @@ fn delete_selection(cx: &mut Context) { } fn change_selection(cx: &mut Context) { - let reg_name = cx.selected_register.name(); + let reg_name = cx.register.unwrap_or('"'); let (view, doc) = current!(cx.editor); let registers = &mut cx.editor.registers; let reg = registers.get_mut(reg_name); @@ -3346,12 +3347,12 @@ fn yank(cx: &mut Context) { let msg = format!( "yanked {} selection(s) to register {}", values.len(), - cx.selected_register.name() + cx.register.unwrap_or('"') ); cx.editor .registers - .write(cx.selected_register.name(), values); + .write(cx.register.unwrap_or('"'), values); cx.editor.set_status(msg); exit_select_mode(cx); @@ -3524,7 +3525,7 @@ fn paste_primary_clipboard_before(cx: &mut Context) { } fn replace_with_yanked(cx: &mut Context) { - let reg_name = cx.selected_register.name(); + let reg_name = cx.register.unwrap_or('"'); let (view, doc) = current!(cx.editor); let registers = &mut cx.editor.registers; @@ -3575,7 +3576,7 @@ fn replace_selections_with_primary_clipboard(cx: &mut Context) { } fn paste_after(cx: &mut Context) { - let reg_name = cx.selected_register.name(); + let reg_name = cx.register.unwrap_or('"'); let (view, doc) = current!(cx.editor); let registers = &mut cx.editor.registers; @@ -3589,7 +3590,7 @@ fn paste_after(cx: &mut Context) { } fn paste_before(cx: &mut Context) { - let reg_name = cx.selected_register.name(); + let reg_name = cx.register.unwrap_or('"'); let (view, doc) = current!(cx.editor); let registers = &mut cx.editor.registers; @@ -3770,7 +3771,8 @@ fn join_selections(cx: &mut Context) { fn keep_selections(cx: &mut Context) { // keep selections matching regex - let prompt = ui::regex_prompt(cx, "keep:".into(), move |view, doc, _, regex| { + let reg = cx.register.unwrap_or('/'); + let prompt = ui::regex_prompt(cx, "keep:".into(), Some(reg), move |view, doc, regex| { let text = doc.text().slice(..); if let Some(selection) = selection::keep_matches(text, doc.selection(view.id), ®ex) { @@ -4103,7 +4105,7 @@ fn wclose(cx: &mut Context) { fn select_register(cx: &mut Context) { cx.on_next_key(move |cx, event| { if let Some(ch) = event.char() { - cx.editor.selected_register.select(ch); + cx.editor.selected_register = Some(ch); } }) } diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index e8cd40cf..52cf3d2b 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -710,7 +710,7 @@ impl EditorView { // debug_assert!(cxt.count != 0); // set the register - cxt.selected_register = cxt.editor.selected_register.take(); + cxt.register = cxt.editor.selected_register.take(); self.handle_keymap_event(mode, cxt, event); if self.keymaps.pending().is_empty() { @@ -887,9 +887,9 @@ impl EditorView { impl Component for EditorView { fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult { let mut cxt = commands::Context { - selected_register: helix_view::RegisterSelection::default(), editor: &mut cx.editor, count: None, + register: None, callback: None, on_next_key_callback: None, jobs: cx.jobs, diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 0a1e24b5..07eef352 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -20,7 +20,6 @@ pub use spinner::{ProgressSpinners, Spinner}; pub use text::Text; use helix_core::regex::Regex; -use helix_core::register::Registers; use helix_view::{Document, Editor, View}; use std::path::PathBuf; @@ -28,7 +27,8 @@ use std::path::PathBuf; pub fn regex_prompt( cx: &mut crate::commands::Context, prompt: std::borrow::Cow<'static, str>, - fun: impl Fn(&mut View, &mut Document, &mut Registers, Regex) + 'static, + history_register: Option, + fun: impl Fn(&mut View, &mut Document, Regex) + 'static, ) -> Prompt { let (view, doc) = current!(cx.editor); let view_id = view.id; @@ -36,7 +36,7 @@ pub fn regex_prompt( Prompt::new( prompt, - None, + history_register, |_input: &str| Vec::new(), // this is fine because Vec::new() doesn't allocate move |cx: &mut crate::compositor::Context, input: &str, event: PromptEvent| { match event { @@ -56,12 +56,11 @@ pub fn regex_prompt( match Regex::new(input) { Ok(regex) => { let (view, doc) = current!(cx.editor); - let registers = &mut cx.editor.registers; // revert state to what it was before the last update doc.set_selection(view.id, snapshot.clone()); - fun(view, doc, registers, regex); + fun(view, doc, regex); view.ensure_cursor_in_view(doc, cx.editor.config.scrolloff); } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 3d2d4a87..52a0060c 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -3,7 +3,7 @@ use crate::{ graphics::{CursorKind, Rect}, theme::{self, Theme}, tree::Tree, - Document, DocumentId, RegisterSelection, View, ViewId, + Document, DocumentId, View, ViewId, }; use futures_util::future; @@ -73,7 +73,7 @@ pub struct Editor { pub tree: Tree, pub documents: SlotMap, pub count: Option, - pub selected_register: RegisterSelection, + pub selected_register: Option, pub registers: Registers, pub theme: Theme, pub language_servers: helix_lsp::Registry, @@ -111,7 +111,7 @@ impl Editor { tree: Tree::new(area), documents: SlotMap::with_key(), count: None, - selected_register: RegisterSelection::default(), + selected_register: None, theme: themes.default(), language_servers, syn_loader: config_loader, diff --git a/helix-view/src/lib.rs b/helix-view/src/lib.rs index 9bcc0b7d..c37474d6 100644 --- a/helix-view/src/lib.rs +++ b/helix-view/src/lib.rs @@ -8,7 +8,6 @@ pub mod graphics; pub mod info; pub mod input; pub mod keyboard; -pub mod register_selection; pub mod theme; pub mod tree; pub mod view; @@ -20,6 +19,5 @@ slotmap::new_key_type! { pub use document::Document; pub use editor::Editor; -pub use register_selection::RegisterSelection; pub use theme::Theme; pub use view::View; diff --git a/helix-view/src/register_selection.rs b/helix-view/src/register_selection.rs deleted file mode 100644 index a2b78f72..00000000 --- a/helix-view/src/register_selection.rs +++ /dev/null @@ -1,48 +0,0 @@ -/// Register selection and configuration -/// -/// This is a kind a of specialized `Option` for register selection. -/// Point is to keep whether the register selection has been explicitely -/// set or not while being convenient by knowing the default register name. -#[derive(Debug)] -pub struct RegisterSelection { - selected: char, - default_name: char, -} - -impl RegisterSelection { - pub fn new(default_name: char) -> Self { - Self { - selected: default_name, - default_name, - } - } - - pub fn select(&mut self, name: char) { - self.selected = name; - } - - pub fn take(&mut self) -> Self { - Self { - selected: std::mem::replace(&mut self.selected, self.default_name), - default_name: self.default_name, - } - } - - pub fn is_default(&self) -> bool { - self.selected == self.default_name - } - - pub fn name(&self) -> char { - self.selected - } -} - -impl Default for RegisterSelection { - fn default() -> Self { - let default_name = '"'; - Self { - selected: default_name, - default_name, - } - } -} -- cgit v1.2.3-70-g09d2