@@ -1847,11 +1847,11 @@ fn search_impl(
18471847
18481848fn search_completions(cx: &mut Context, reg: Option<char>) -> Vec<String> {
18491849 let mut items = reg
1850− .and_then(|reg| cx.editor.registers.get(reg))
1851− .map_or(Vec::new(), |reg| reg.read().iter().take(200).collect());
1850+ .and_then(|reg| cx.editor.registers.read(reg, cx.editor))
1851+ .map_or(Vec::new(), |reg| reg.take(200).collect());
18521852 items.sort_unstable();
18531853 items.dedup();
1854− items.into_iter().cloned().collect()
1854+ items.into_iter().map(|value| value.to_string()).collect()
18551855}
18561856
18571857fn search(cx: &mut Context) {
@@ -1910,9 +1910,8 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
19101910 let count = cx.count();
19111911 let config = cx.editor.config();
19121912 let scrolloff = config.scrolloff;
1913− let (_, doc) = current!(cx.editor);
1914− let registers = &cx.editor.registers;
1915− if let Some(query) = registers.read('/').and_then(|query| query.last()) {
1913+ if let Some(query) = cx.editor.registers.last('/', cx.editor) {
1914+ let doc = doc!(cx.editor);
19161915 let contents = doc.text().slice(..).to_string();
19171916 let search_config = &config.search;
19181917 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
19211920 false
19221921 };
19231922 let wrap_around = search_config.wrap_around;
1924− if let Ok(regex) = RegexBuilder::new(query)
1923+ if let Ok(regex) = RegexBuilder::new(&query)
19251924 .case_insensitive(case_insensitive)
19261925 .multi_line(true)
19271926 .build()
@@ -1974,12 +1973,14 @@ fn search_selection(cx: &mut Context) {
19741973 .join("|");
19751974
19761975 let msg = format!("register '{}' set to '{}'", '/', ®ex);
1977− cx.editor.registers.push('/', regex);
1978− cx.editor.set_status(msg);
1976+ match cx.editor.registers.push('/', regex) {
1977+ Ok(_) => cx.editor.set_status(msg),
1978+ Err(err) => cx.editor.set_error(err.to_string()),
1979+ }
19791980}
19801981
19811982fn 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) {
19831984 Some(regex) => regex,
19841985 None => return,
19851986 };
@@ -1997,14 +1998,16 @@ fn make_search_word_bounded(cx: &mut Context) {
19971998 if !start_anchored {
19981999 new_regex.push_str("\\b");
19992000 }
2000− new_regex.push_str(regex);
2001+ new_regex.push_str(®ex);
20012002 if !end_anchored {
20022003 new_regex.push_str("\\b");
20032004 }
20042005
20052006 let msg = format!("register '{}' set to '{}'", '/', &new_regex);
2006− cx.editor.registers.push('/', new_regex);
2007− cx.editor.set_status(msg);
2007+ match cx.editor.registers.push('/', new_regex) {
2008+ Ok(_) => cx.editor.set_status(msg),
2009+ Err(err) => cx.editor.set_error(err.to_string()),
2010+ }
20082011}
20092012
20102013fn global_search(cx: &mut Context) {
@@ -2367,7 +2370,10 @@ fn delete_selection_impl(cx: &mut Context, op: Operation) {
23672370 let text = doc.text().slice(..);
23682371 let values: Vec<String> = selection.fragments(text).map(Cow::into_owned).collect();
23692372 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());
2375+ return;
2376+ }
23712377 };
23722378
23732379 // then delete
@@ -3758,18 +3764,16 @@ fn yank(cx: &mut Context) {
37583764 .fragments(text)
37593765 .map(Cow::into_owned)
37603766 .collect();
3767+ let selections = values.len();
3768+ let register = cx.register.unwrap_or('"');
37613769
3762− let msg = format!(
3763− "yanked {} selection(s) to register {}",
3764− values.len(),
3765− cx.register.unwrap_or('"')
3766− );
3767−
3768− cx.editor
3769− .registers
3770− .write(cx.register.unwrap_or('"'), values);
3770+ match cx.editor.registers.write(register, values) {
3771+ Ok(_) => cx.editor.set_status(format!(
3772+ "yanked {selections} selection(s) to register {register}",
3773+ )),
3774+ Err(err) => cx.editor.set_error(err.to_string()),
3775+ }
37713776
3772− cx.editor.set_status(msg);
37733777 exit_select_mode(cx);
37743778}
37753779
@@ -3778,6 +3782,7 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
37783782 let text = doc.text().slice(..);
37793783
37803784 let selection = doc.selection(view.id);
3785+ let selections = selection.len();
37813786 let joined = selection
37823787 .fragments(text)
37833788 .fold(String::new(), |mut acc, fragment| {
@@ -3788,14 +3793,12 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
37883793 acc
37893794 });
37903795
3791− let msg = format!(
3792− "joined and yanked {} selection(s) to register {}",
3793− selection.len(),
3794− register,
3795− );
3796−
3797− editor.registers.write(register, vec![joined]);
3798− editor.set_status(msg);
3796+ match editor.registers.write(register, vec![joined]) {
3797+ Ok(_) => editor.set_status(format!(
3798+ "joined and yanked {selections} selection(s) to register {register}",
3799+ )),
3800+ Err(err) => editor.set_error(err.to_string()),
3801+ }
37993802}
38003803
38013804fn yank_joined(cx: &mut Context) {
@@ -4040,34 +4043,34 @@ fn paste_primary_clipboard_before(cx: &mut Context) {
40404043fn replace_with_yanked(cx: &mut Context) {
40414044 let count = cx.count();
40424045 let reg_name = cx.register.unwrap_or('"');
4043− let (view, doc) = current!(cx.editor);
4044− let registers = &mut cx.editor.registers;
4045−
4046− if let Some(values) = registers.read(reg_name) {
4047− if !values.is_empty() {
4048− let repeat = std::iter::repeat(
4049− values
4050− .last()
4051− .map(|value| Tendril::from(&value.repeat(count)))
4052− .unwrap(),
4053− );
4054− let mut values = values
4055− .iter()
4056− .map(|value| Tendril::from(&value.repeat(count)))
4057− .chain(repeat);
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()))
4062− } else {
4063− (range.from(), range.to(), None)
4064− }
4065− });
40664046
4067− doc.apply(&transaction, view.id);
4068− exit_select_mode(cx);
4047+ let Some(values) = cx.editor.registers
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();
4051+
4052+ let (view, doc) = current!(cx.editor);
4053+ let repeat = std::iter::repeat(
4054+ values
4055+ .last()
4056+ .map(|value| Tendril::from(&value.repeat(count)))
4057+ .unwrap(),
4058+ );
4059+ let mut values = values
4060+ .iter()
4061+ .map(|value| Tendril::from(&value.repeat(count)))
4062+ .chain(repeat);
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()))
4067+ } else {
4068+ (range.from(), range.to(), None)
40694069 }
4070− }
4070+ });
4071+
4072+ doc.apply(&transaction, view.id);
4073+ exit_select_mode(cx);
40714074}
40724075
40734076fn replace_selections_with_clipboard_impl(
@@ -4109,12 +4112,12 @@ fn replace_selections_with_primary_clipboard(cx: &mut Context) {
41094112fn paste(cx: &mut Context, pos: Paste) {
41104113 let count = cx.count();
41114114 let reg_name = cx.register.unwrap_or('"');
4112− let (view, doc) = current!(cx.editor);
4113− let registers = &mut cx.editor.registers;
41144115
4115− if let Some(values) = registers.read(reg_name) {
4116− paste_impl(values, doc, view, pos, count, cx.editor.mode);
4117− }
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();
4118+
4119+ let (view, doc) = current!(cx.editor);
4120+ paste_impl(&values, doc, view, pos, count, cx.editor.mode);
41184121}
41194122
41204123fn paste_after(cx: &mut Context) {
@@ -5593,9 +5596,12 @@ fn record_macro(cx: &mut Context) {
55935596 }
55945597 })
55955598 .collect::<String>();
5596− cx.editor.registers.write(reg, vec![s]);
5597− cx.editor
5598− .set_status(format!("Recorded to register [{}]", reg));
5599+ match cx.editor.registers.write(reg, vec![s]) {
5600+ Ok(_) => cx
5601+ .editor
5602+ .set_status(format!("Recorded to register [{}]", reg)),
5603+ Err(err) => cx.editor.set_error(err.to_string()),
5604+ }
55995605 } else {
56005606 let reg = cx.register.take().unwrap_or('@');
56015607 cx.editor.macro_recording = Some((reg, Vec::new()));
@@ -5615,8 +5621,14 @@ fn replay_macro(cx: &mut Context) {
56155621 return;
56165622 }
56175623
5618− let keys: Vec<KeyEvent> = if let Some([keys_str]) = cx.editor.registers.read(reg) {
5619− match helix_view::input::parse_macro(keys_str) {
5624+ let keys: Vec<KeyEvent> = if let Some(keys) = cx
5625+ .editor
5626+ .registers
5627+ .read(reg, cx.editor)
5628+ .filter(|values| values.len() == 1)
5629+ .map(|mut values| values.next().unwrap())
5630+ {
5631+ match helix_view::input::parse_macro(&keys) {
56205632 Ok(keys) => keys,
56215633 Err(err) => {
56225634 cx.editor.set_error(format!("Invalid macro: {}", err));