@@ -1847,11 +1847,11 @@ fn search_impl(
1848fn search_completions(cx: &mut Context, reg: Option<char>) -> Vec<String> {
1848fn search_completions(cx: &mut Context, reg: Option<char>) -> Vec<String> {
1849 let mut items = reg
1849 let mut items = reg
1850− .and_then(|reg| cx.editor.registers.get(reg))
1850+ .and_then(|reg| cx.editor.registers.read(reg, cx.editor))
1851− .map_or(Vec::new(), |reg| reg.read().iter().take(200).collect());
1851+ .map_or(Vec::new(), |reg| reg.take(200).collect());
1852 items.sort_unstable();
1852 items.sort_unstable();
1853 items.dedup();
1853 items.dedup();
1854− items.into_iter().cloned().collect()
1854+ items.into_iter().map(|value| value.to_string()).collect()
1857fn search(cx: &mut Context) {
1857fn search(cx: &mut Context) {
@@ -1910,9 +1910,8 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
1910 let count = cx.count();
1910 let count = cx.count();
1911 let config = cx.editor.config();
1911 let config = cx.editor.config();
1912 let scrolloff = config.scrolloff;
1912 let scrolloff = config.scrolloff;
1913− let (_, doc) = current!(cx.editor);
1913+ if let Some(query) = cx.editor.registers.last('/', cx.editor) {
1914− let registers = &cx.editor.registers;
1914+ let doc = doc!(cx.editor);
1915− if let Some(query) = registers.read('/').and_then(|query| query.last()) {
1916 let contents = doc.text().slice(..).to_string();
1915 let contents = doc.text().slice(..).to_string();
1917 let search_config = &config.search;
1916 let search_config = &config.search;
1918 let case_insensitive = if search_config.smart_case {
1917 let case_insensitive = if search_config.smart_case {
@@ -1921,7 +1920,7 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
1923 let wrap_around = search_config.wrap_around;
1922 let wrap_around = search_config.wrap_around;
1924− if let Ok(regex) = RegexBuilder::new(query)
1923+ if let Ok(regex) = RegexBuilder::new(&query)
1925 .case_insensitive(case_insensitive)
1924 .case_insensitive(case_insensitive)
1926 .multi_line(true)
1925 .multi_line(true)
1927 .build()
1926 .build()
@@ -1974,12 +1973,14 @@ fn search_selection(cx: &mut Context) {
1974 .join("|");
1973 .join("|");
1976 let msg = format!("register '{}' set to '{}'", '/', ®ex);
1975 let msg = format!("register '{}' set to '{}'", '/', ®ex);
1977− cx.editor.registers.push('/', regex);
1976+ match cx.editor.registers.push('/', regex) {
1978− cx.editor.set_status(msg);
1977+ Ok(_) => cx.editor.set_status(msg),
1978+ Err(err) => cx.editor.set_error(err.to_string()),
1981fn make_search_word_bounded(cx: &mut Context) {
1982fn make_search_word_bounded(cx: &mut Context) {
1982− let regex = match cx.editor.registers.last('/') {
1983+ let regex = match cx.editor.registers.last('/', cx.editor) {
1983 Some(regex) => regex,
1984 Some(regex) => regex,
1984 None => return,
1985 None => return,
@@ -1997,14 +1998,16 @@ fn make_search_word_bounded(cx: &mut Context) {
1997 if !start_anchored {
1998 if !start_anchored {
1998 new_regex.push_str("\\b");
1999 new_regex.push_str("\\b");
2000− new_regex.push_str(regex);
2001+ new_regex.push_str(®ex);
2001 if !end_anchored {
2002 if !end_anchored {
2002 new_regex.push_str("\\b");
2003 new_regex.push_str("\\b");
2005 let msg = format!("register '{}' set to '{}'", '/', &new_regex);
2006 let msg = format!("register '{}' set to '{}'", '/', &new_regex);
2006− cx.editor.registers.push('/', new_regex);
2007+ match cx.editor.registers.push('/', new_regex) {
2007− cx.editor.set_status(msg);
2008+ Ok(_) => cx.editor.set_status(msg),
2009+ Err(err) => cx.editor.set_error(err.to_string()),
2010fn global_search(cx: &mut Context) {
2013fn global_search(cx: &mut Context) {
@@ -2367,7 +2370,10 @@ fn delete_selection_impl(cx: &mut Context, op: Operation) {
2367 let text = doc.text().slice(..);
2370 let text = doc.text().slice(..);
2368 let values: Vec<String> = selection.fragments(text).map(Cow::into_owned).collect();
2371 let values: Vec<String> = selection.fragments(text).map(Cow::into_owned).collect();
2369 let reg_name = cx.register.unwrap_or('"');
2372 let reg_name = cx.register.unwrap_or('"');
2370− cx.editor.registers.write(reg_name, values);
2373+ if let Err(err) = cx.editor.registers.write(reg_name, values) {
2374+ cx.editor.set_error(err.to_string());
2373 // then delete
2379 // then delete
@@ -3758,18 +3764,16 @@ fn yank(cx: &mut Context) {
3758 .fragments(text)
3764 .fragments(text)
3759 .map(Cow::into_owned)
3765 .map(Cow::into_owned)
3760 .collect();
3766 .collect();
3767+ let selections = values.len();
3768+ let register = cx.register.unwrap_or('"');
3762− let msg = format!(
3770+ match cx.editor.registers.write(register, values) {
3771+ Ok(_) => cx.editor.set_status(format!(
3763− "yanked {} selection(s) to register {}",
3772+ "yanked {selections} selection(s) to register {register}",
3764− values.len(),
3773+ )),
3765− cx.register.unwrap_or('"')
3774+ Err(err) => cx.editor.set_error(err.to_string()),
3770− .write(cx.register.unwrap_or('"'), values);
3772− cx.editor.set_status(msg);
3773 exit_select_mode(cx);
3777 exit_select_mode(cx);
@@ -3778,6 +3782,7 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
3778 let text = doc.text().slice(..);
3782 let text = doc.text().slice(..);
3780 let selection = doc.selection(view.id);
3784 let selection = doc.selection(view.id);
3785+ let selections = selection.len();
3781 let joined = selection
3786 let joined = selection
3782 .fragments(text)
3787 .fragments(text)
3783 .fold(String::new(), |mut acc, fragment| {
3788 .fold(String::new(), |mut acc, fragment| {
@@ -3788,14 +3793,12 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
3792− "joined and yanked {} selection(s) to register {}",
3797− editor.registers.write(register, vec![joined]);
3796+ match editor.registers.write(register, vec![joined]) {
3798− editor.set_status(msg);
3797+ Ok(_) => editor.set_status(format!(
3798+ "joined and yanked {selections} selection(s) to register {register}",
3800+ Err(err) => editor.set_error(err.to_string()),
3801fn yank_joined(cx: &mut Context) {
3804fn yank_joined(cx: &mut Context) {
@@ -4040,34 +4043,34 @@ fn paste_primary_clipboard_before(cx: &mut Context) {
4040fn replace_with_yanked(cx: &mut Context) {
4043fn replace_with_yanked(cx: &mut Context) {
4041 let count = cx.count();
4044 let count = cx.count();
4042 let reg_name = cx.register.unwrap_or('"');
4045 let reg_name = cx.register.unwrap_or('"');
4043− let (view, doc) = current!(cx.editor);
4044− let registers = &mut cx.editor.registers;
4046− if let Some(values) = registers.read(reg_name) {
4047− if !values.is_empty() {
4048− let repeat = std::iter::repeat(
4051− .map(|value| Tendril::from(&value.repeat(count)))
4054− let mut values = values
4056− .map(|value| Tendril::from(&value.repeat(count)))
4058− let selection = doc.selection(view.id);
4059− let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
4060− if !range.is_empty() {
4061− (range.from(), range.to(), Some(values.next().unwrap()))
4063− (range.from(), range.to(), None)
4067− doc.apply(&transaction, view.id);
4047+ let Some(values) = cx.editor.registers
4068− exit_select_mode(cx);
4048+ .read(reg_name, cx.editor)
4049+ .filter(|values| values.len() > 0) else { return };
4050+ let values: Vec<_> = values.map(|value| value.to_string()).collect();
4052+ let (view, doc) = current!(cx.editor);
4053+ let repeat = std::iter::repeat(
4056+ .map(|value| Tendril::from(&value.repeat(count)))
4059+ let mut values = values
4061+ .map(|value| Tendril::from(&value.repeat(count)))
4063+ let selection = doc.selection(view.id);
4064+ let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
4065+ if !range.is_empty() {
4066+ (range.from(), range.to(), Some(values.next().unwrap()))
4068+ (range.from(), range.to(), None)
4072+ doc.apply(&transaction, view.id);
4073+ exit_select_mode(cx);
4073fn replace_selections_with_clipboard_impl(
4076fn replace_selections_with_clipboard_impl(
@@ -4109,12 +4112,12 @@ fn replace_selections_with_primary_clipboard(cx: &mut Context) {
4109fn paste(cx: &mut Context, pos: Paste) {
4112fn paste(cx: &mut Context, pos: Paste) {
4110 let count = cx.count();
4113 let count = cx.count();
4111 let reg_name = cx.register.unwrap_or('"');
4114 let reg_name = cx.register.unwrap_or('"');
4112− let (view, doc) = current!(cx.editor);
4113− let registers = &mut cx.editor.registers;
4115− if let Some(values) = registers.read(reg_name) {
4116+ let Some(values) = cx.editor.registers.read(reg_name, cx.editor) else { return };
4117+ let values: Vec<_> = values.map(|value| value.to_string()).collect();
4119+ let (view, doc) = current!(cx.editor);
4116− paste_impl(values, doc, view, pos, count, cx.editor.mode);
4120+ paste_impl(&values, doc, view, pos, count, cx.editor.mode);
4120fn paste_after(cx: &mut Context) {
4123fn paste_after(cx: &mut Context) {
@@ -5593,9 +5596,12 @@ fn record_macro(cx: &mut Context) {
5595 .collect::<String>();
5598 .collect::<String>();
5596− cx.editor.registers.write(reg, vec![s]);
5599+ match cx.editor.registers.write(reg, vec![s]) {
5597− cx.editor
5601+ .editor
5598− .set_status(format!("Recorded to register [{}]", reg));
5602+ .set_status(format!("Recorded to register [{}]", reg)),
5603+ Err(err) => cx.editor.set_error(err.to_string()),
5599 } else {
5605 } else {
5600 let reg = cx.register.take().unwrap_or('@');
5606 let reg = cx.register.take().unwrap_or('@');
5601 cx.editor.macro_recording = Some((reg, Vec::new()));
5607 cx.editor.macro_recording = Some((reg, Vec::new()));
@@ -5615,8 +5621,14 @@ fn replay_macro(cx: &mut Context) {
5618− let keys: Vec<KeyEvent> = if let Some([keys_str]) = cx.editor.registers.read(reg) {
5624+ let keys: Vec<KeyEvent> = if let Some(keys) = cx
5627+ .read(reg, cx.editor)
5628+ .filter(|values| values.len() == 1)
5629+ .map(|mut values| values.next().unwrap())
5619− match helix_view::input::parse_macro(keys_str) {
5631+ match helix_view::input::parse_macro(&keys) {
5620 Ok(keys) => keys,
5632 Ok(keys) => keys,
5621 Err(err) => {
5633 Err(err) => {
5622 cx.editor.set_error(format!("Invalid macro: {}", err));
5634 cx.editor.set_error(format!("Invalid macro: {}", err));