implement selection update mechanism

pull/10905/head
Sam Vente 6 months ago
parent 2da81b254b
commit d1e2bff16b
No known key found for this signature in database

@ -6125,8 +6125,8 @@ fn extend_to_word(cx: &mut Context) {
jump_to_word(cx, Movement::Extend)
}
fn read_from_register(editor: &Editor, reg: char) -> Option<RegisterValues> {
editor.registers.read(reg, &editor)
fn read_from_register(editor: &mut Editor, reg: char) -> Option<RegisterValues> {
editor.registers.read(reg, &*editor)
}
fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {

@ -467,14 +467,21 @@ fn register_mark(
let ranges_str = ranges
.iter()
.map(|r| r.to_string())
.collect::<Vec<String>>()
.join(",");
.collect::<Vec<String>>();
// we have to take because of cell
let history = doc.history.take();
let current_history_point = history.current_revision();
doc.history.replace(history);
let mut register_val = vec![
format!("{}", doc.id()),
format!("{}", current_history_point),
];
register_val.extend(ranges_str);
cx.editor
.registers
.write(
register_name,
vec![format!("{}:{}", doc.id(), ranges_str.to_string())],
)
.write(register_name, register_val)
.unwrap();
cx.editor
@ -482,30 +489,19 @@ fn register_mark(
Ok(())
}
fn goto_mark(
cx: &mut compositor::Context,
args: &[Cow<str>],
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
};
let register_name: char = args
.first()
.map_or_else(
|| cx.editor.selected_register,
|s| s.as_ref().chars().next(),
)
.unwrap_or('^');
let registers_vals = read_from_register(cx.editor, register_name);
let blurb = registers_vals
.unwrap()
.into_iter()
.next()
.map(|c| c.into_owned());
match blurb {
Some(s) => {
let doc_id_parser = seq!(take_until(|c| c == ':'), ":");
fn parse_mark_register_contents(
registers_vals: Option<RegisterValues>,
) -> Result<(DocumentId, usize, Selection), String> {
match registers_vals {
Some(rv) => {
let mut rv_iter = rv.into_iter();
let doc_id_str = rv_iter.next().unwrap().into_owned();
let doc_id: DocumentId = doc_id_str.try_into().unwrap();
let history_rev_str = rv_iter.next().unwrap().into_owned();
let history_rev: usize = history_rev_str.parse().unwrap();
let mut ranges = rv_iter
.map(|tup| {
let s = tup.into_owned();
let range_parser = seq!(
"(",
take_until(|c| c == ','),
@ -513,14 +509,8 @@ fn goto_mark(
take_until(|c| c == ')'),
")"
);
let multiple_ranges_parser = sep(range_parser, ",");
let (tail, (doc_id_str, _)) = doc_id_parser.parse(&s).unwrap();
let (_tail, v) = multiple_ranges_parser.parse(tail).unwrap();
let mut ranges = v
.iter()
.map(|tup| {
let (_, anchor_str, _, head_str, _) = tup;
let anchor: usize = <usize as FromStr>::from_str(anchor_str).unwrap();
let (_, (_, anchor_str, _, head_str, _)) = range_parser.parse(&s).unwrap();
let anchor: usize = <usize as FromStr>::from_str(anchor_str).unwrap().clone();
let head: usize = <usize as FromStr>::from_str(head_str).unwrap();
Range {
anchor,
@ -528,21 +518,54 @@ fn goto_mark(
old_visual_position: None,
}
})
.rev();
// reverse the iterators so the first range will end up as the primary when we push them
let doc_id: DocumentId = doc_id_str.try_into().unwrap();
cx.editor.switch(doc_id, Action::Replace);
let (view, doc) = current!(cx.editor);
.rev();
let last_range = ranges.next().unwrap(); // there is always at least one range
let mut selection = Selection::from(last_range);
for r in ranges {
selection = selection.push(r);
}
doc.set_selection(view.id, selection);
Ok((doc_id, history_rev, selection))
}
None => Err("Could not parse registry content".to_string()), // I can't figure out how to set status line here because of borrow issues :(
}
None => (),
}
fn get_revisions_to_apply(doc: &mut Document, history_rev: usize) -> Option<Transaction> {
let history = doc.history.take();
let revisions_to_apply = history.changes_since(history_rev);
doc.history.replace(history);
revisions_to_apply
}
fn goto_mark(
cx: &mut compositor::Context,
args: &[Cow<str>],
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
};
let register_name: char = args
.first()
.map_or_else(
|| cx.editor.selected_register,
|s| s.as_ref().chars().next(),
)
.unwrap_or('^');
let registers_vals = read_from_register(cx.editor, register_name);
let (doc_id, history_rev, mut selection) =
parse_mark_register_contents(registers_vals).unwrap();
cx.editor.switch(doc_id, Action::Replace);
let (view, doc) = current!(cx.editor);
let revisions_to_apply = get_revisions_to_apply(doc, history_rev);
selection = match revisions_to_apply {
Some(t) => selection.map(t.changes()),
None => selection,
};
doc.set_selection(view.id, selection);
Ok(())
}

@ -38,6 +38,14 @@ impl TryFrom<&str> for DocumentId {
Ok(Self(value.parse::<NonZeroUsize>()?))
}
}
impl TryFrom<String> for DocumentId {
type Error = ParseIntError;
fn try_from(value: String) -> Result<Self, Self::Error> {
Ok(Self(value.parse::<NonZeroUsize>()?))
}
}
impl std::fmt::Display for DocumentId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0))

Loading…
Cancel
Save