summaryrefslogtreecommitdiff
path: root/helix-term/src/commands.rs
diff options
context:
space:
mode:
authorMichael Davis2023-07-10 23:48:29 +0000
committerBlaž Hrastnik2023-07-31 06:05:38 +0000
commitbaceb02a090fe711ad772d855635bc590826fa53 (patch)
tree9bb4eecbce2e7c84caf707f33ff39d7a2dcf7102 /helix-term/src/commands.rs
parent0f19f282cfa49d441f58a8e2540a6b24efe1b769 (diff)
Use refactored Registers type
This is an unfortunately noisy change: we need to update virtually all callsites that access the registers. For reads this means passing in the Editor and for writes this means handling potential failure when we can't write to a clipboard register.
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r--helix-term/src/commands.rs148
1 files changed, 80 insertions, 68 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 58c17296..d9ea580d 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1847,11 +1847,11 @@ fn search_impl(
fn search_completions(cx: &mut Context, reg: Option<char>) -> Vec<String> {
let mut items = reg
- .and_then(|reg| cx.editor.registers.get(reg))
- .map_or(Vec::new(), |reg| reg.read().iter().take(200).collect());
+ .and_then(|reg| cx.editor.registers.read(reg, cx.editor))
+ .map_or(Vec::new(), |reg| reg.take(200).collect());
items.sort_unstable();
items.dedup();
- items.into_iter().cloned().collect()
+ items.into_iter().map(|value| value.to_string()).collect()
}
fn search(cx: &mut Context) {
@@ -1910,9 +1910,8 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
let count = cx.count();
let config = cx.editor.config();
let scrolloff = config.scrolloff;
- let (_, doc) = current!(cx.editor);
- let registers = &cx.editor.registers;
- if let Some(query) = registers.read('/').and_then(|query| query.last()) {
+ if let Some(query) = cx.editor.registers.last('/', cx.editor) {
+ let doc = doc!(cx.editor);
let contents = doc.text().slice(..).to_string();
let search_config = &config.search;
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
false
};
let wrap_around = search_config.wrap_around;
- if let Ok(regex) = RegexBuilder::new(query)
+ if let Ok(regex) = RegexBuilder::new(&query)
.case_insensitive(case_insensitive)
.multi_line(true)
.build()
@@ -1974,12 +1973,14 @@ fn search_selection(cx: &mut Context) {
.join("|");
let msg = format!("register '{}' set to '{}'", '/', &regex);
- cx.editor.registers.push('/', regex);
- cx.editor.set_status(msg);
+ match cx.editor.registers.push('/', regex) {
+ Ok(_) => cx.editor.set_status(msg),
+ Err(err) => cx.editor.set_error(err.to_string()),
+ }
}
fn make_search_word_bounded(cx: &mut Context) {
- let regex = match cx.editor.registers.last('/') {
+ let regex = match cx.editor.registers.last('/', cx.editor) {
Some(regex) => regex,
None => return,
};
@@ -1997,14 +1998,16 @@ fn make_search_word_bounded(cx: &mut Context) {
if !start_anchored {
new_regex.push_str("\\b");
}
- new_regex.push_str(regex);
+ new_regex.push_str(&regex);
if !end_anchored {
new_regex.push_str("\\b");
}
let msg = format!("register '{}' set to '{}'", '/', &new_regex);
- cx.editor.registers.push('/', new_regex);
- cx.editor.set_status(msg);
+ match cx.editor.registers.push('/', new_regex) {
+ Ok(_) => cx.editor.set_status(msg),
+ Err(err) => cx.editor.set_error(err.to_string()),
+ }
}
fn global_search(cx: &mut Context) {
@@ -2367,7 +2370,10 @@ fn delete_selection_impl(cx: &mut Context, op: Operation) {
let text = doc.text().slice(..);
let values: Vec<String> = selection.fragments(text).map(Cow::into_owned).collect();
let reg_name = cx.register.unwrap_or('"');
- cx.editor.registers.write(reg_name, values);
+ if let Err(err) = cx.editor.registers.write(reg_name, values) {
+ cx.editor.set_error(err.to_string());
+ return;
+ }
};
// then delete
@@ -3758,18 +3764,16 @@ fn yank(cx: &mut Context) {
.fragments(text)
.map(Cow::into_owned)
.collect();
+ let selections = values.len();
+ let register = cx.register.unwrap_or('"');
- let msg = format!(
- "yanked {} selection(s) to register {}",
- values.len(),
- cx.register.unwrap_or('"')
- );
-
- cx.editor
- .registers
- .write(cx.register.unwrap_or('"'), values);
+ match cx.editor.registers.write(register, values) {
+ Ok(_) => cx.editor.set_status(format!(
+ "yanked {selections} selection(s) to register {register}",
+ )),
+ Err(err) => cx.editor.set_error(err.to_string()),
+ }
- cx.editor.set_status(msg);
exit_select_mode(cx);
}
@@ -3778,6 +3782,7 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
let text = doc.text().slice(..);
let selection = doc.selection(view.id);
+ let selections = selection.len();
let joined = selection
.fragments(text)
.fold(String::new(), |mut acc, fragment| {
@@ -3788,14 +3793,12 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) {
acc
});
- let msg = format!(
- "joined and yanked {} selection(s) to register {}",
- selection.len(),
- register,
- );
-
- editor.registers.write(register, vec![joined]);
- editor.set_status(msg);
+ match editor.registers.write(register, vec![joined]) {
+ Ok(_) => editor.set_status(format!(
+ "joined and yanked {selections} selection(s) to register {register}",
+ )),
+ Err(err) => editor.set_error(err.to_string()),
+ }
}
fn yank_joined(cx: &mut Context) {
@@ -4040,34 +4043,34 @@ fn paste_primary_clipboard_before(cx: &mut Context) {
fn replace_with_yanked(cx: &mut Context) {
let count = cx.count();
let reg_name = cx.register.unwrap_or('"');
- let (view, doc) = current!(cx.editor);
- let registers = &mut cx.editor.registers;
-
- if let Some(values) = registers.read(reg_name) {
- if !values.is_empty() {
- let repeat = std::iter::repeat(
- values
- .last()
- .map(|value| Tendril::from(&value.repeat(count)))
- .unwrap(),
- );
- let mut values = values
- .iter()
- .map(|value| Tendril::from(&value.repeat(count)))
- .chain(repeat);
- let selection = doc.selection(view.id);
- let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
- if !range.is_empty() {
- (range.from(), range.to(), Some(values.next().unwrap()))
- } else {
- (range.from(), range.to(), None)
- }
- });
- doc.apply(&transaction, view.id);
- exit_select_mode(cx);
+ let Some(values) = cx.editor.registers
+ .read(reg_name, cx.editor)
+ .filter(|values| values.len() > 0) else { return };
+ let values: Vec<_> = values.map(|value| value.to_string()).collect();
+
+ let (view, doc) = current!(cx.editor);
+ let repeat = std::iter::repeat(
+ values
+ .last()
+ .map(|value| Tendril::from(&value.repeat(count)))
+ .unwrap(),
+ );
+ let mut values = values
+ .iter()
+ .map(|value| Tendril::from(&value.repeat(count)))
+ .chain(repeat);
+ let selection = doc.selection(view.id);
+ let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
+ if !range.is_empty() {
+ (range.from(), range.to(), Some(values.next().unwrap()))
+ } else {
+ (range.from(), range.to(), None)
}
- }
+ });
+
+ doc.apply(&transaction, view.id);
+ exit_select_mode(cx);
}
fn replace_selections_with_clipboard_impl(
@@ -4109,12 +4112,12 @@ fn replace_selections_with_primary_clipboard(cx: &mut Context) {
fn paste(cx: &mut Context, pos: Paste) {
let count = cx.count();
let reg_name = cx.register.unwrap_or('"');
- let (view, doc) = current!(cx.editor);
- let registers = &mut cx.editor.registers;
- if let Some(values) = registers.read(reg_name) {
- paste_impl(values, doc, view, pos, count, cx.editor.mode);
- }
+ let Some(values) = cx.editor.registers.read(reg_name, cx.editor) else { return };
+ let values: Vec<_> = values.map(|value| value.to_string()).collect();
+
+ let (view, doc) = current!(cx.editor);
+ paste_impl(&values, doc, view, pos, count, cx.editor.mode);
}
fn paste_after(cx: &mut Context) {
@@ -5593,9 +5596,12 @@ fn record_macro(cx: &mut Context) {
}
})
.collect::<String>();
- cx.editor.registers.write(reg, vec![s]);
- cx.editor
- .set_status(format!("Recorded to register [{}]", reg));
+ match cx.editor.registers.write(reg, vec![s]) {
+ Ok(_) => cx
+ .editor
+ .set_status(format!("Recorded to register [{}]", reg)),
+ Err(err) => cx.editor.set_error(err.to_string()),
+ }
} else {
let reg = cx.register.take().unwrap_or('@');
cx.editor.macro_recording = Some((reg, Vec::new()));
@@ -5615,8 +5621,14 @@ fn replay_macro(cx: &mut Context) {
return;
}
- let keys: Vec<KeyEvent> = if let Some([keys_str]) = cx.editor.registers.read(reg) {
- match helix_view::input::parse_macro(keys_str) {
+ let keys: Vec<KeyEvent> = if let Some(keys) = cx
+ .editor
+ .registers
+ .read(reg, cx.editor)
+ .filter(|values| values.len() == 1)
+ .map(|mut values| values.next().unwrap())
+ {
+ match helix_view::input::parse_macro(&keys) {
Ok(keys) => keys,
Err(err) => {
cx.editor.set_error(format!("Invalid macro: {}", err));