mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-04 02:14:06 +03:00
Delete till previous tabstop when backspacing within indent column
This commit is contained in:
parent
9076345a8f
commit
ee6d7fc6d5
@ -2638,11 +2638,25 @@ impl Editor {
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
for selection in &mut selections {
|
||||
if selection.is_empty() {
|
||||
let head = selection.head().to_display_point(&display_map);
|
||||
let cursor = movement::left(&display_map, head)
|
||||
.unwrap()
|
||||
.to_point(&display_map);
|
||||
selection.set_head(cursor);
|
||||
let old_head = selection.head();
|
||||
let (buffer, line_buffer_range) = display_map
|
||||
.buffer_snapshot
|
||||
.buffer_line_for_row(old_head.row)
|
||||
.unwrap();
|
||||
let indent_column = buffer.indent_column_for_line(line_buffer_range.start.row);
|
||||
let mut new_head =
|
||||
movement::left(&display_map, old_head.to_display_point(&display_map))
|
||||
.unwrap()
|
||||
.to_point(&display_map);
|
||||
if old_head.column <= indent_column && old_head.column > 0 {
|
||||
let indent = buffer.indent_size();
|
||||
new_head = cmp::min(
|
||||
new_head,
|
||||
Point::new(old_head.row, ((old_head.column - 1) / indent) * indent),
|
||||
);
|
||||
}
|
||||
|
||||
selection.set_head(new_head);
|
||||
selection.goal = SelectionGoal::None;
|
||||
}
|
||||
}
|
||||
@ -7153,14 +7167,13 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
fn test_backspace(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer =
|
||||
MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
|
||||
let settings = Settings::test(&cx);
|
||||
let (_, view) = cx.add_window(Default::default(), |cx| {
|
||||
build_editor(buffer.clone(), settings, cx)
|
||||
build_editor(MultiBuffer::build_simple("", cx), settings, cx)
|
||||
});
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
|
||||
view.select_display_ranges(
|
||||
&[
|
||||
// an empty selection - the preceding character is deleted
|
||||
@ -7173,12 +7186,28 @@ mod tests {
|
||||
cx,
|
||||
);
|
||||
view.backspace(&Backspace, cx);
|
||||
});
|
||||
assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
|
||||
|
||||
assert_eq!(
|
||||
buffer.read(cx).read(cx).text(),
|
||||
"oe two three\nfou five six\nseven ten\n"
|
||||
);
|
||||
view.set_text(" one\n two\n three\n four", cx);
|
||||
view.select_display_ranges(
|
||||
&[
|
||||
// cursors at the the end of leading indent - last indent is deleted
|
||||
DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
|
||||
DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
|
||||
// cursors inside leading indent - overlapping indent deletions are coalesced
|
||||
DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
|
||||
DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
|
||||
DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
|
||||
// cursor at the beginning of a line - preceding newline is deleted
|
||||
DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
|
||||
// selection inside leading indent - only the selected character is deleted
|
||||
DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
|
||||
],
|
||||
cx,
|
||||
);
|
||||
view.backspace(&Backspace, cx);
|
||||
assert_eq!(view.text(cx), "one\n two\n three four");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -1657,7 +1657,7 @@ impl MultiBufferSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
|
||||
pub fn buffer_line_for_row(&self, row: u32) -> Option<(&BufferSnapshot, Range<Point>)> {
|
||||
let mut cursor = self.excerpts.cursor::<Point>();
|
||||
cursor.seek(&Point::new(row, 0), Bias::Right, &());
|
||||
if let Some(excerpt) = cursor.item() {
|
||||
|
@ -47,9 +47,6 @@ lazy_static! {
|
||||
static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
|
||||
}
|
||||
|
||||
// TODO - Make this configurable
|
||||
const INDENT_SIZE: u32 = 4;
|
||||
|
||||
pub struct Buffer {
|
||||
text: TextBuffer,
|
||||
file: Option<Box<dyn File>>,
|
||||
@ -70,6 +67,7 @@ pub struct Buffer {
|
||||
file_update_count: usize,
|
||||
completion_triggers: Vec<String>,
|
||||
deferred_ops: OperationQueue<Operation>,
|
||||
indent_size: u32,
|
||||
}
|
||||
|
||||
pub struct BufferSnapshot {
|
||||
@ -81,9 +79,9 @@ pub struct BufferSnapshot {
|
||||
file_update_count: usize,
|
||||
remote_selections: TreeMap<ReplicaId, SelectionSet>,
|
||||
selections_update_count: usize,
|
||||
is_parsing: bool,
|
||||
language: Option<Arc<Language>>,
|
||||
parse_count: usize,
|
||||
indent_size: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -416,6 +414,8 @@ impl Buffer {
|
||||
file_update_count: 0,
|
||||
completion_triggers: Default::default(),
|
||||
deferred_ops: OperationQueue::new(),
|
||||
// TODO: make this configurable
|
||||
indent_size: 4,
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,10 +428,10 @@ impl Buffer {
|
||||
diagnostics: self.diagnostics.clone(),
|
||||
diagnostics_update_count: self.diagnostics_update_count,
|
||||
file_update_count: self.file_update_count,
|
||||
is_parsing: self.parsing_in_background,
|
||||
language: self.language.clone(),
|
||||
parse_count: self.parse_count,
|
||||
selections_update_count: self.selections_update_count,
|
||||
indent_size: self.indent_size,
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,7 +768,11 @@ impl Buffer {
|
||||
.before_edit
|
||||
.indent_column_for_line(suggestion.basis_row)
|
||||
});
|
||||
let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
|
||||
let delta = if suggestion.indent {
|
||||
snapshot.indent_size
|
||||
} else {
|
||||
0
|
||||
};
|
||||
old_suggestions.insert(
|
||||
*old_to_new_rows.get(&old_row).unwrap(),
|
||||
indentation_basis + delta,
|
||||
@ -787,7 +791,11 @@ impl Buffer {
|
||||
.into_iter()
|
||||
.flatten();
|
||||
for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
|
||||
let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
|
||||
let delta = if suggestion.indent {
|
||||
snapshot.indent_size
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let new_indentation = indent_columns
|
||||
.get(&suggestion.basis_row)
|
||||
.copied()
|
||||
@ -819,7 +827,11 @@ impl Buffer {
|
||||
.into_iter()
|
||||
.flatten();
|
||||
for (row, suggestion) in inserted_row_range.zip(suggestions) {
|
||||
let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
|
||||
let delta = if suggestion.indent {
|
||||
snapshot.indent_size
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let new_indentation = indent_columns
|
||||
.get(&suggestion.basis_row)
|
||||
.copied()
|
||||
@ -1868,6 +1880,10 @@ impl BufferSnapshot {
|
||||
pub fn file_update_count(&self) -> usize {
|
||||
self.file_update_count
|
||||
}
|
||||
|
||||
pub fn indent_size(&self) -> u32 {
|
||||
self.indent_size
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for BufferSnapshot {
|
||||
@ -1881,9 +1897,9 @@ impl Clone for BufferSnapshot {
|
||||
selections_update_count: self.selections_update_count,
|
||||
diagnostics_update_count: self.diagnostics_update_count,
|
||||
file_update_count: self.file_update_count,
|
||||
is_parsing: self.is_parsing,
|
||||
language: self.language.clone(),
|
||||
parse_count: self.parse_count,
|
||||
indent_size: self.indent_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user