Slightly more sensible newline logic
This commit is contained in:
parent
0912450513
commit
1f7a0c48e8
2 changed files with 66 additions and 26 deletions
90
src/state.rs
90
src/state.rs
|
|
@ -124,6 +124,19 @@ impl Text {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn indent_of_line(&self, line: isize) -> &[char] {
|
||||||
|
let line_start = self.to_pos([0, line]);
|
||||||
|
let mut i = 0;
|
||||||
|
while self
|
||||||
|
.chars()
|
||||||
|
.get(line_start + i)
|
||||||
|
.map_or(false, |c| [' ', '\t'].contains(c))
|
||||||
|
{
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
self.chars().get(line_start..line_start + i).unwrap_or(&[])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -445,9 +458,17 @@ impl Buffer {
|
||||||
let Some(cursor) = self.cursors.get(cursor_id) else {
|
let Some(cursor) = self.cursors.get(cursor_id) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let line_start = self.text.to_pos([0, self.text.to_coord(cursor.pos)[1]]);
|
||||||
if let Some(selection) = cursor.selection() {
|
if let Some(selection) = cursor.selection() {
|
||||||
self.remove(selection);
|
self.remove(selection);
|
||||||
} else if let Some(pos) = cursor.pos.checked_sub(1) {
|
} else
|
||||||
|
/*if line_start != cursor.pos && (line_start..cursor.pos)
|
||||||
|
.all(|p| self.text.chars().get(p).map_or(false, |c| [' ', '\t'].contains(c)))
|
||||||
|
{
|
||||||
|
self.remove(line_start..cursor.pos);
|
||||||
|
self.backspace(cursor_id); // Remove the newline too
|
||||||
|
} else*/
|
||||||
|
if let Some(pos) = cursor.pos.checked_sub(1) {
|
||||||
// If a backspace is performed on a space, a deindent takes place instead
|
// If a backspace is performed on a space, a deindent takes place instead
|
||||||
if self.text.chars().get(pos) == Some(&' ') {
|
if self.text.chars().get(pos) == Some(&' ') {
|
||||||
self.indent_at(pos, false);
|
self.indent_at(pos, false);
|
||||||
|
|
@ -472,40 +493,59 @@ impl Buffer {
|
||||||
let Some(cursor) = self.cursors.get(cursor_id) else {
|
let Some(cursor) = self.cursors.get(cursor_id) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let line_start = self.text.to_pos([0, self.text.to_coord(cursor.pos)[1]]);
|
let line = self.text.to_coord(cursor.pos)[1];
|
||||||
let is_block = if let Some(last_pos) = cursor
|
let line_start = self.text.to_pos([0, line]);
|
||||||
.selection()
|
|
||||||
.map_or(cursor.pos, |s| s.start)
|
let prev_indent = self.text.indent_of_line(line).to_vec();
|
||||||
.checked_sub(1)
|
let next_indent = self.text.indent_of_line(line + 1).to_vec();
|
||||||
|
|
||||||
|
let (close_block, extra_indent, trailing_indent, base_indent) = if let Some(last_pos) =
|
||||||
|
cursor
|
||||||
|
.selection()
|
||||||
|
.map_or(cursor.pos, |s| s.start)
|
||||||
|
.checked_sub(1)
|
||||||
&& let Some(last_char) = self.text.chars().get(last_pos)
|
&& let Some(last_char) = self.text.chars().get(last_pos)
|
||||||
&& let Some((l, r)) = [('(', ')'), ('[', ']'), ('{', '}')]
|
&& let Some((l, r)) = [('(', ')'), ('[', ']'), ('{', '}')]
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(l, _)| l == last_char)
|
.find(|(l, _)| l == last_char)
|
||||||
&& let next_pos = cursor.selection().map_or(cursor.pos, |s| s.end)
|
&& let next_pos = cursor.selection().map_or(cursor.pos, |s| s.end)
|
||||||
&& let next_char = self.text.chars().get(next_pos)
|
&& let next_char = self
|
||||||
|
.text
|
||||||
|
.chars()
|
||||||
|
.get(next_pos..)
|
||||||
|
.unwrap_or(&[])
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !c.is_ascii_whitespace())
|
||||||
|
.next()
|
||||||
{
|
{
|
||||||
Some((*r, next_char == Some(r)))
|
let close_block = next_char != Some(r)
|
||||||
|
&& next_indent
|
||||||
|
.strip_prefix(&*prev_indent)
|
||||||
|
.map_or(true, |i| i.is_empty());
|
||||||
|
(
|
||||||
|
if close_block { Some(*r) } else { None },
|
||||||
|
true,
|
||||||
|
close_block || self.text.chars().get(next_pos) == Some(r),
|
||||||
|
prev_indent,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
(None, false, false, prev_indent)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.enter(cursor_id, ['\n']);
|
|
||||||
|
|
||||||
// Indent to same level as last line
|
// Indent to same level as last line
|
||||||
if let Some(chars) = self.text.chars().get(line_start..) {
|
self.enter(
|
||||||
let indent = chars
|
cursor_id,
|
||||||
.iter()
|
['\n'].into_iter().chain(base_indent.iter().copied()),
|
||||||
.take_while(|c| [' ', '\t'].contains(c))
|
);
|
||||||
.copied()
|
|
||||||
.collect::<Vec<_>>();
|
if let Some(r) = close_block {
|
||||||
self.enter(cursor_id, indent.iter().copied());
|
self.insert_after(cursor_id, [r]);
|
||||||
// If the last character was the start of a block, perform an additional indent
|
}
|
||||||
if let Some((r, is_complete)) = is_block {
|
if trailing_indent {
|
||||||
self.indent(cursor_id, true);
|
self.insert_after(cursor_id, core::iter::once('\n').chain(base_indent));
|
||||||
// If the block was not already completed, complete it (TODO: make configurable!)
|
}
|
||||||
let tail = if !is_complete { Some(r) } else { None };
|
if extra_indent {
|
||||||
self.insert_after(cursor_id, core::iter::once('\n').chain(indent).chain(tail));
|
self.indent(cursor_id, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ impl Default for Theme {
|
||||||
Self {
|
Self {
|
||||||
ui_bg: Color::AnsiValue(235),
|
ui_bg: Color::AnsiValue(235),
|
||||||
select_bg: Color::AnsiValue(23),
|
select_bg: Color::AnsiValue(23),
|
||||||
line_select_bg: Color::AnsiValue(8),
|
line_select_bg: Color::AnsiValue(238),
|
||||||
unfocus_select_bg: Color::AnsiValue(240),
|
unfocus_select_bg: Color::AnsiValue(240),
|
||||||
search_result_bg: Color::AnsiValue(60),
|
search_result_bg: Color::AnsiValue(60),
|
||||||
margin_bg: Color::Reset,
|
margin_bg: Color::Reset,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue