on master help sign in
Add '#' and '.' special registers
da2afe7Michael Davis
helix-core/src/selection.rs+10−2
@@ -630,11 +630,19 @@ impl Selection {
630 self.transform(|range| Range::point(range.cursor(text)))
630 self.transform(|range| Range::point(range.cursor(text)))
631 }
631 }
632
632
633− pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
633+ pub fn fragments<'a>(
634+ &'a self,
635+ text: RopeSlice<'a>,
636+ ) -> impl DoubleEndedIterator<Item = Cow<'a, str>> + ExactSizeIterator<Item = Cow<str>> + 'a
637+ {
634 self.ranges.iter().map(move |range| range.fragment(text))
638 self.ranges.iter().map(move |range| range.fragment(text))
635 }
639 }
636
640
637− pub fn slices<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = RopeSlice> + 'a {
641+ pub fn slices<'a>(
642+ &'a self,
643+ text: RopeSlice<'a>,
644+ ) -> impl DoubleEndedIterator<Item = RopeSlice<'a>> + ExactSizeIterator<Item = RopeSlice<'a>> + 'a
645+ {
638 self.ranges.iter().map(move |range| range.slice(text))
646 self.ranges.iter().map(move |range| range.slice(text))
639 }
647 }
640
648
helix-view/src/register.rs+29−3
@@ -11,15 +11,31 @@ use crate::Editor;
11/// behaviors when read or written to:
11/// behaviors when read or written to:
12///
12///
13/// * Black hole (`_`): all values read and written are discarded
13/// * Black hole (`_`): all values read and written are discarded
14+/// * Selection indices (`#`): index number of each selection starting at 1
15+/// * Selection contents (`.`)
14#[derive(Debug, Default)]
16#[derive(Debug, Default)]
15pub struct Registers {
17pub struct Registers {
16 inner: HashMap<char, Vec<String>>,
18 inner: HashMap<char, Vec<String>>,
17}
19}
18
20
19impl Registers {
21impl Registers {
20− pub fn read<'a>(&'a self, name: char, _editor: &'a Editor) -> Option<RegisterValues<'a>> {
22+ pub fn read<'a>(&'a self, name: char, editor: &'a Editor) -> Option<RegisterValues<'a>> {
21 match name {
23 match name {
22 '_' => Some(RegisterValues::new(iter::empty())),
24 '_' => Some(RegisterValues::new(iter::empty())),
25+ '#' => {
26+ let (view, doc) = current_ref!(editor);
27+ let selections = doc.selection(view.id).len();
28+ // ExactSizeIterator is implemented for Range<usize> but
29+ // not RangeInclusive<usize>.
30+ Some(RegisterValues::new(
31+ (0..selections).map(|i| (i + 1).to_string().into()),
32+ ))
33+ }
34+ '.' => {
35+ let (view, doc) = current_ref!(editor);
36+ let text = doc.text().slice(..);
37+ Some(RegisterValues::new(doc.selection(view.id).fragments(text)))
38+ }
23 _ => self
39 _ => self
24 .inner
40 .inner
25 .get(&name)
41 .get(&name)
@@ -30,6 +46,7 @@ impl Registers {
30 pub fn write(&mut self, name: char, values: Vec<String>) -> Result<()> {
46 pub fn write(&mut self, name: char, values: Vec<String>) -> Result<()> {
31 match name {
47 match name {
32 '_' => Ok(()),
48 '_' => Ok(()),
49+ '#' | '.' => Err(anyhow::anyhow!("Register {name} does not support writing")),
33 _ => {
50 _ => {
34 self.inner.insert(name, values);
51 self.inner.insert(name, values);
35 Ok(())
52 Ok(())
@@ -40,6 +57,7 @@ impl Registers {
40 pub fn push(&mut self, name: char, value: String) -> Result<()> {
57 pub fn push(&mut self, name: char, value: String) -> Result<()> {
41 match name {
58 match name {
42 '_' => Ok(()),
59 '_' => Ok(()),
60+ '#' | '.' => Err(anyhow::anyhow!("Register {name} does not support pushing")),
43 _ => {
61 _ => {
44 self.inner.entry(name).or_insert_with(Vec::new).push(value);
62 self.inner.entry(name).or_insert_with(Vec::new).push(value);
45 Ok(())
63 Ok(())
@@ -66,7 +84,15 @@ impl Registers {
66
84
67 (*name, preview)
85 (*name, preview)
68 })
86 })
87+ .chain(
88+ [
69− .chain([('_', "<empty>")].iter().copied())
89+ ('_', "<empty>"),
90+ ('#', "<selection indices>"),
91+ ('.', "<selection contents>"),
92+ ]
93+ .iter()
94+ .copied(),
95+ )
70 }
96 }
71
97
72 pub fn clear(&mut self) {
98 pub fn clear(&mut self) {
@@ -75,7 +101,7 @@ impl Registers {
75
101
76 pub fn remove(&mut self, name: char) -> bool {
102 pub fn remove(&mut self, name: char) -> bool {
77 match name {
103 match name {
78− '_' => false,
104+ '_' | '#' | '.' => false,
79 _ => self.inner.remove(&name).is_some(),
105 _ => self.inner.remove(&name).is_some(),
80 }
106 }
81 }
107 }