editable_line: guard against empty text

there's got to be a nicer way to do this

Fixes #11324
This commit is contained in:
Fabian Boehm
2025-03-26 19:20:00 +01:00
parent 360cfdb7ae
commit 89b62a56e1
2 changed files with 26 additions and 7 deletions

View File

@@ -41,7 +41,11 @@ pub fn new(range: std::ops::Range<usize>, replacement: WString) -> Self {
/// Currently exposed for testing only.
pub fn apply_edit(target: &mut WString, colors: &mut Vec<HighlightSpec>, edit: &Edit) {
let range = &edit.range;
target.replace_range(range.clone(), &edit.replacement);
if target.is_empty() {
*target = edit.replacement.clone();
} else {
target.replace_range(range.clone(), &edit.replacement);
}
// Now do the same to highlighting.
let last_color = edit
@@ -50,10 +54,16 @@ pub fn apply_edit(target: &mut WString, colors: &mut Vec<HighlightSpec>, edit: &
.checked_sub(1)
.map(|i| colors[i])
.unwrap_or_default();
colors.splice(
range.clone(),
std::iter::repeat(last_color).take(edit.replacement.len()),
);
if colors.is_empty() {
*colors = std::iter::repeat(last_color)
.take(edit.replacement.len())
.collect();
} else {
colors.splice(
range.clone(),
std::iter::repeat(last_color).take(edit.replacement.len()),
);
}
}
/// The history of all edits to some command line.
@@ -185,7 +195,11 @@ pub fn push_edit(&mut self, mut edit: Edit, allow_coalesce: bool) {
.truncate(self.undo_history.edits_applied);
}
edit.cursor_position_before_edit = self.pending_position.take().unwrap_or(self.position());
edit.old = self.text[range.clone()].to_owned();
edit.old = if self.text.is_empty() {
L!("").to_owned()
} else {
self.text[range.clone()].to_owned()
};
apply_edit(&mut self.text, &mut self.colors, &edit);
self.set_position(cursor_position_after_edit(&edit));
assert_eq!(
@@ -204,7 +218,7 @@ pub fn undo(&mut self) -> bool {
let mut last_group_id = None;
let position_before_undo = self.position();
let end = self.undo_history.edits_applied;
while self.undo_history.edits_applied != 0 {
while !self.undo_history.edits.is_empty() && self.undo_history.edits_applied != 0 {
let edit = &self.undo_history.edits[self.undo_history.edits_applied - 1];
if did_undo
&& edit

View File

@@ -184,3 +184,8 @@ sendline(r"""abbr fruit --command={git,hg,svn,} banana""")
expect_prompt()
sendline(r"""fruit foo""")
expect_prompt("I am a banana")
# (don't add the literal string "bar" here or the expect_prompt will match it - so we add some no-op quotes)
sendline(r"""function replace; commandline -r ""; echo echo b''ar; end; abbr foo --function replace""")
sendline("foo")
expect_prompt("bar")