Skip to content

Commit

Permalink
Add multiline support (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiajt committed Jul 18, 2021
1 parent db9722e commit 4056abe
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 7 deletions.
95 changes: 95 additions & 0 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,95 @@ impl Reedline {
self.line_buffer.clear();
}

fn up_command(&mut self) {
// If we're at the top, then:
if !self.line_buffer.get_buffer()[0..self.line_buffer.insertion_point().offset]
.contains('\n')
{
// If we're at the top, move to previous history
self.previous_history();
} else {
// If we're not at the top, move up a line in the multiline buffer
let mut position = self.line_buffer.insertion_point().offset;
let mut num_of_move_lefts = 0;
let buffer = self.line_buffer.get_buffer().to_string();

// Move left until we're looking at the newline
// Observe what column we were on
while position > 0 && &buffer[(position - 1)..position] != "\n" {
self.line_buffer.move_left();
num_of_move_lefts += 1;
position = self.line_buffer.insertion_point().offset;
}

// Find start of previous line
let mut matches = buffer[0..(position - 1)].rmatch_indices('\n');

if let Some((pos, _)) = matches.next() {
position = pos + 1;
} else {
position = 0;
}
self.line_buffer.set_insertion_point(InsertionPoint {
line: 0,
offset: position,
});

// Move right from this position to the column we were at
while &buffer[position..(position + 1)] != "\n" && num_of_move_lefts > 0 {
self.line_buffer.move_right();
position = self.line_buffer.insertion_point().offset;
num_of_move_lefts -= 1;
}
}
}

fn down_command(&mut self) {
// If we're at the top, then:
if !self.line_buffer.get_buffer()[self.line_buffer.insertion_point().offset..]
.contains('\n')
{
// If we're at the top, move to previous history
self.next_history();
} else {
// If we're not at the top, move up a line in the multiline buffer
let mut position = self.line_buffer.insertion_point().offset;
let mut num_of_move_lefts = 0;
let buffer = self.line_buffer.get_buffer().to_string();

// Move left until we're looking at the newline
// Observe what column we were on
while position > 0 && &buffer[(position - 1)..position] != "\n" {
self.line_buffer.move_left();
num_of_move_lefts += 1;
position = self.line_buffer.insertion_point().offset;
}

// Find start of next line
let mut matches = buffer[position..].match_indices('\n');

// Assume this always succeeds

let (pos, _) = matches
.next()
.expect("internal error: should have found newline");

position += pos + 1;

self.line_buffer.set_insertion_point(InsertionPoint {
line: 0,
offset: position,
});

// Move right from this position to the column we were at
while &buffer[position..(position + 1)] != "\n" && num_of_move_lefts > 0 {
self.line_buffer.move_right();
position = self.line_buffer.insertion_point().offset;
num_of_move_lefts -= 1;
}
}
}

fn append_to_history(&mut self) {
self.history.append(self.insertion_line().to_string());
}
Expand Down Expand Up @@ -485,6 +574,12 @@ impl Reedline {
EditCommand::NextHistory => {
self.next_history();
}
EditCommand::Up => {
self.up_command();
}
EditCommand::Down => {
self.down_command();
}
EditCommand::SearchHistory => {
self.search_history();
}
Expand Down
2 changes: 2 additions & 0 deletions src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub enum EditCommand {
MoveRight,
MoveWordLeft,
MoveWordRight,
Up,
Down,
InsertChar(char),
Backspace,
Delete,
Expand Down
9 changes: 7 additions & 2 deletions src/keybindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ pub fn default_emacs_keybindings() -> Keybindings {
Char('t'),
vec![EditCommand::SwapGraphemes],
);
keybindings.add_binding(
KeyModifiers::ALT,
Enter,
vec![EditCommand::InsertChar('\n')],
);
keybindings.add_binding(
KeyModifiers::ALT,
Char('b'),
Expand Down Expand Up @@ -227,8 +232,8 @@ pub fn default_emacs_keybindings() -> Keybindings {
keybindings.add_binding(KeyModifiers::NONE, Delete, vec![EditCommand::Delete]);
keybindings.add_binding(KeyModifiers::NONE, Home, vec![EditCommand::MoveToStart]);
keybindings.add_binding(KeyModifiers::NONE, End, vec![EditCommand::MoveToEnd]);
keybindings.add_binding(KeyModifiers::NONE, Up, vec![EditCommand::PreviousHistory]);
keybindings.add_binding(KeyModifiers::NONE, Down, vec![EditCommand::NextHistory]);
keybindings.add_binding(KeyModifiers::NONE, Up, vec![EditCommand::Up]);
keybindings.add_binding(KeyModifiers::NONE, Down, vec![EditCommand::Down]);
keybindings.add_binding(KeyModifiers::NONE, Left, vec![EditCommand::MoveLeft]);
keybindings.add_binding(KeyModifiers::NONE, Right, vec![EditCommand::MoveRight]);

Expand Down
32 changes: 27 additions & 5 deletions src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,38 @@ impl Painter {
.highlight(&original_line)
.render_around_insertion_point(cursor_position_in_buffer);

self.stdout
.queue(MoveTo(prompt_offset.0, prompt_offset.1))?
.queue(Print(highlighted_line.0))?
let (before_cursor, after_cursor) = highlighted_line;

let before_cursor_lines = before_cursor.lines();
let after_cursor_lines = after_cursor.lines();

let mut commands = self
.stdout
.queue(MoveTo(prompt_offset.0, prompt_offset.1))?;

for (idx, before_cursor_line) in before_cursor_lines.enumerate() {
if idx != 0 {
commands = commands.queue(Print("\r\n"))?;
}
commands = commands.queue(Print(before_cursor_line))?;
}

commands = commands
.queue(SavePosition)?
.queue(Print(self.hinter.handle(
&original_line,
cursor_position_in_buffer,
history,
)))?
.queue(Print(highlighted_line.1))?
)))?;

for (idx, after_cursor_line) in after_cursor_lines.enumerate() {
if idx != 0 {
commands = commands.queue(Print("\r\n"))?;
}
commands = commands.queue(Print(after_cursor_line))?;
}

commands
.queue(Clear(ClearType::FromCursorDown))?
.queue(RestorePosition)?
.flush()?;
Expand Down

0 comments on commit 4056abe

Please sign in to comment.