Skip to content

Commit

Permalink
Fix vertical movements in multi-lines input
Browse files Browse the repository at this point in the history
Take into account prompt offset
  • Loading branch information
gwenn committed Oct 27, 2024
1 parent bdc2f60 commit 13b4594
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ impl<H: Helper> State<'_, '_, H> {

/// Moves the cursor to the same column in the line above
pub fn edit_move_line_up(&mut self, n: RepeatCount) -> Result<bool> {
if self.line.move_to_line_up(n) {
if self.line.move_to_line_up(n, &self.layout) {
self.move_cursor(CmdKind::MoveCursor)?;
Ok(true)
} else {
Expand All @@ -588,7 +588,7 @@ impl<H: Helper> State<'_, '_, H> {

/// Moves the cursor to the same column in the line above
pub fn edit_move_line_down(&mut self, n: RepeatCount) -> Result<bool> {
if self.line.move_to_line_down(n) {
if self.line.move_to_line_down(n, &self.layout) {
self.move_cursor(CmdKind::MoveCursor)?;
Ok(true)
} else {
Expand Down
50 changes: 37 additions & 13 deletions src/line_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Line buffer with current cursor position
use crate::keymap::{At, CharSearch, Movement, RepeatCount, Word};
use crate::layout::Layout;
use std::cmp::min;
use std::fmt;
use std::iter;
Expand Down Expand Up @@ -582,7 +583,7 @@ impl LineBuffer {
}

/// Moves the cursor to the same column in the line above
pub fn move_to_line_up(&mut self, n: RepeatCount) -> bool {
pub fn move_to_line_up(&mut self, n: RepeatCount, layout: &Layout) -> bool {
match self.buf[..self.pos].rfind('\n') {
Some(off) => {
let column = self.buf[off + 1..self.pos].graphemes(true).count();
Expand All @@ -596,9 +597,14 @@ impl LineBuffer {
dest_end = dest_start - 1;
dest_start = self.buf[..dest_end].rfind('\n').map_or(0, |n| n + 1);
}
let offset = if dest_start == 0 {
layout.prompt_size.col
} else {
0
};
let gidx = self.buf[dest_start..dest_end]
.grapheme_indices(true)
.nth(column);
.nth(column.saturating_sub(offset));

self.pos = gidx.map_or(off, |(idx, _)| dest_start + idx); // if there's no enough columns
true
Expand Down Expand Up @@ -652,11 +658,16 @@ impl LineBuffer {
}

/// Moves the cursor to the same column in the line above
pub fn move_to_line_down(&mut self, n: RepeatCount) -> bool {
pub fn move_to_line_down(&mut self, n: RepeatCount, layout: &Layout) -> bool {
match self.buf[self.pos..].find('\n') {
Some(off) => {
let line_start = self.buf[..self.pos].rfind('\n').map_or(0, |n| n + 1);
let column = self.buf[line_start..self.pos].graphemes(true).count();
let offset = if line_start == 0 {
layout.prompt_size.col
} else {
0
};
let column = self.buf[line_start..self.pos].graphemes(true).count() + offset;
let mut dest_start = self.pos + off + 1;
let mut dest_end = self.buf[dest_start..]
.find('\n')
Expand Down Expand Up @@ -1182,7 +1193,10 @@ mod test {
use super::{
ChangeListener, DeleteListener, Direction, LineBuffer, NoListener, WordAction, MAX_LINE,
};
use crate::keymap::{At, CharSearch, Word};
use crate::{
keymap::{At, CharSearch, Word},
layout::Layout,
};

struct Listener {
deleted_str: Option<String>,
Expand Down Expand Up @@ -1819,40 +1833,50 @@ mod test {
fn move_by_line() {
let text = "aa123\nsdf bc\nasdf";
let mut s = LineBuffer::init(text, 14);
let mut layout = Layout::default();
// move up
let ok = s.move_to_line_up(1);
let ok = s.move_to_line_up(1, &layout);
assert_eq!(7, s.pos);
assert!(ok);

let ok = s.move_to_line_up(1);
let ok = s.move_to_line_up(1, &layout);
assert_eq!(1, s.pos);
assert!(ok);

let ok = s.move_to_line_up(1);
let ok = s.move_to_line_up(1, &layout);
assert_eq!(1, s.pos);
assert!(!ok);

// move down
let ok = s.move_to_line_down(1);
let ok = s.move_to_line_down(1, &layout);
assert_eq!(7, s.pos);
assert!(ok);

let ok = s.move_to_line_down(1);
let ok = s.move_to_line_down(1, &layout);
assert_eq!(14, s.pos);
assert!(ok);

let ok = s.move_to_line_down(1);
let ok = s.move_to_line_down(1, &layout);
assert_eq!(14, s.pos);
assert!(!ok);

// move by multiple steps
let ok = s.move_to_line_up(2);
let ok = s.move_to_line_up(2, &layout);
assert_eq!(1, s.pos);
assert!(ok);

let ok = s.move_to_line_down(2);
let ok = s.move_to_line_down(2, &layout);
assert_eq!(14, s.pos);
assert!(ok);

// non-empty prompt
layout.prompt_size.col = 2;
s.move_to_line_up(1, &layout);
assert_eq!(7, s.pos);
s.move_to_line_up(1, &layout);
assert_eq!(0, s.pos);
s.move_to_line_down(1, &layout);
assert_eq!(8, s.pos);
}

#[test]
Expand Down

0 comments on commit 13b4594

Please sign in to comment.