Compare commits

...

2 commits

4 changed files with 42 additions and 23 deletions

View file

@ -23,6 +23,3 @@
- [ ] Replace - [ ] Replace
## Issues to fix ## Issues to fix
- Can't use left/right to edit text in finder
- Pressing return on `foo {|bar` should wrap `bar` in a block

View file

@ -87,7 +87,11 @@ impl Text {
let mut pos = 0; let mut pos = 0;
for (i, line) in self.lines().enumerate() { for (i, line) in self.lines().enumerate() {
if i as isize == coord[1] { if i as isize == coord[1] {
return pos + coord[0].clamp(0, line.len().saturating_sub(1) as isize) as usize; return pos
+ coord[0].clamp(
0,
line.len().saturating_sub(line.ends_with(&['\n']) as usize) as isize,
) as usize;
} else { } else {
pos += line.len(); pos += line.len();
} }
@ -565,7 +569,9 @@ impl Buffer {
fn remove_inner(&mut self, range: Range<usize>) -> Change { fn remove_inner(&mut self, range: Range<usize>) -> Change {
self.unsaved = true; self.unsaved = true;
// TODO: Bell if false? // Force range to be valid
let range = range.start.min(self.text.chars.len())..range.end.min(self.text.chars.len());
let removed = self.text.chars.drain(range.clone()).collect(); let removed = self.text.chars.drain(range.clone()).collect();
self.highlights_stale = true; self.highlights_stale = true;
Change { Change {
@ -602,12 +608,17 @@ impl Buffer {
self.push_undo(change); self.push_undo(change);
} }
pub fn insert_after(&mut self, cursor_id: CursorId, chars: impl IntoIterator<Item = char>) { pub fn insert_after(
&mut self,
cursor_id: CursorId,
at: Option<usize>,
chars: impl IntoIterator<Item = char>,
) {
let Some(cursor) = self.cursors.get(cursor_id) else { let Some(cursor) = self.cursors.get(cursor_id) else {
return; return;
}; };
let old_cursor = *cursor; let old_cursor = *cursor;
self.insert(old_cursor.pos, chars); self.insert(at.unwrap_or(old_cursor.pos), chars);
let Some(cursor) = self.cursors.get_mut(cursor_id) else { let Some(cursor) = self.cursors.get_mut(cursor_id) else {
return; return;
}; };
@ -642,7 +653,10 @@ impl Buffer {
} else*/ } else*/
if let Some(pos) = cursor.pos.checked_sub(1) { 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(&' ')
// Ensure there's only whitespace to our left
&& self.text.chars().get(line_start..pos).unwrap_or(&[]).iter().all(|c| "\t ".contains(*c))
{
self.indent_at(pos, false); self.indent_at(pos, false);
} else { } else {
self.remove(pos..pos + 1); self.remove(pos..pos + 1);
@ -667,6 +681,7 @@ impl Buffer {
}; };
let coord = self.text.to_coord(cursor.pos); let coord = self.text.to_coord(cursor.pos);
let line_start = self.text.to_pos([0, coord[1]]); let line_start = self.text.to_pos([0, coord[1]]);
let line_end = self.text.to_pos([1000000, coord[1]]);
let prev_indent = self let prev_indent = self
.text .text
@ -677,7 +692,8 @@ impl Buffer {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let next_indent = self.text.indent_of_line(coord[1] + 1).to_vec(); let next_indent = self.text.indent_of_line(coord[1] + 1).to_vec();
let (close_block, extra_indent, trailing_indent, base_indent) = if let Some(last_pos) = // Determine whether we're creating/forming a new code block
let (close_block, extra_indent, closing_indent, base_indent) = if let Some(last_pos) =
cursor cursor
.selection() .selection()
.map_or(cursor.pos, |s| s.start) .map_or(cursor.pos, |s| s.start)
@ -697,7 +713,7 @@ impl Buffer {
.next() .next()
&& let next_char = self.text.chars().get(next_pos) && let next_char = self.text.chars().get(next_pos)
{ {
let close_block = (next_tok.map_or(true, |c| *c == '\n') // TODO: More robust is_line_end check let close_block = (true//next_tok.map_or(true, |c| *c == '\n') // TODO: More robust is_line_end check
&& next_indent && next_indent
.strip_prefix(&*prev_indent) .strip_prefix(&*prev_indent)
.map_or(false, |i| i.is_empty())) .map_or(false, |i| i.is_empty()))
@ -715,19 +731,24 @@ impl Buffer {
(None, false, false, prev_indent) (None, false, false, prev_indent)
}; };
// Indent to same level as last line // Where is the end of the new code block?
self.enter( let end_of_block = line_end.max(cursor.pos);
cursor_id,
['\n'].into_iter().chain(base_indent.iter().copied()),
);
if let Some(r) = close_block { if let Some(r) = close_block {
self.insert_after(cursor_id, [r]); self.insert_after(cursor_id, Some(end_of_block), [r]);
} }
if trailing_indent { if closing_indent {
self.insert_after(cursor_id, core::iter::once('\n').chain(base_indent)); // Indent the block closer to the base level
self.insert_after(
cursor_id,
Some(end_of_block),
core::iter::once('\n').chain(base_indent.iter().copied()),
);
} }
// Indent to same level as last line
self.enter(cursor_id, ['\n'].into_iter().chain(base_indent));
if extra_indent { if extra_indent {
// If we're starting a new block, increase the indent
self.indent(cursor_id, true); self.indent(cursor_id, true);
} }
} }
@ -771,7 +792,7 @@ impl Buffer {
&& let Some(text) = cursor.selection().and_then(|s| self.text.chars().get(s)) && let Some(text) = cursor.selection().and_then(|s| self.text.chars().get(s))
{ {
// cursor.place_at(s.end); // cursor.place_at(s.end);
self.insert_after(cursor_id, text.to_vec()) self.insert_after(cursor_id, None, text.to_vec())
} else { } else {
let coord = self.text.to_coord(cursor.pos); let coord = self.text.to_coord(cursor.pos);
let line = self let line = self

View file

@ -314,7 +314,7 @@ impl Finder {
return Ok(Resp::end(None)); return Ok(Resp::end(None));
} }
Some(Action::Go) => return Ok(Resp::end(None)), Some(Action::Go) => return Ok(Resp::end(None)),
Some(Action::Move(dir, Dist::Char, false, false)) => { Some(Action::Move(dir @ (Dir::Up | Dir::Down), Dist::Char, false, false)) => {
match dir { match dir {
Dir::Up => { Dir::Up => {
self.selected = (self.selected + self.results.len().saturating_sub(1)) self.selected = (self.selected + self.results.len().saturating_sub(1))

View file

@ -292,12 +292,13 @@ impl Input {
.text([1, 0], &format!("{:>line_num_w$}", line_num + 1)), .text([1, 0], &format!("{:>line_num_w$}", line_num + 1)),
}; };
let line_selected = buffer.text.to_coord(cursor.pos)[1] == line_num as isize;
// Line // Line
{ {
let mut frame = frame.rect([margin_w, i], [!0, 1]); let mut frame = frame.rect([margin_w, i], [!0, 1]);
for i in 0..frame.size()[0] { for i in 0..frame.size()[0] {
let coord = self.focus[0] + i as isize; let coord = self.focus[0] + i as isize;
let line_selected = (line_pos..line_pos + line.len()).contains(&cursor.pos);
let pos = if i < line.len() { let pos = if i < line.len() {
Some(line_pos + coord as usize) Some(line_pos + coord as usize)
} else { } else {