use crate::commands::{self, Result};
use crate::errors::*;
use crate::input::Key;
use crate::models::application::{Application, Mode};
use scribe::buffer::Position;
pub fn accept_input(app: &mut Application) -> Result {
if let Mode::LineJump(ref mode) = app.mode {
let line_number = mode
.input
.parse::<usize>()
.chain_err(|| "Couldn't parse a line number from the provided input.")?;
if line_number > 0 {
let buffer = app
.workspace
.current_buffer
.as_mut()
.ok_or(BUFFER_MISSING)?;
let target_line = line_number - 1;
let mut target_position = Position {
line: target_line,
offset: buffer.cursor.offset,
};
if !buffer.cursor.move_to(target_position) {
let line_content = buffer
.data()
.lines()
.nth(target_line)
.map(|line| line.to_string())
.ok_or("Couldn't find the specified line")?;
target_position.offset = line_content.len();
buffer.cursor.move_to(target_position);
}
}
} else {
bail!("Can't accept line jump input outside of line jump mode.");
}
commands::application::switch_to_normal_mode(app)?;
commands::view::scroll_cursor_to_center(app)?;
Ok(())
}
pub fn push_search_char(app: &mut Application) -> Result {
let key = app
.view
.last_key()
.as_ref()
.ok_or("View hasn't tracked a key press")?;
if let Key::Char(c) = *key {
if let Mode::LineJump(ref mut mode) = app.mode {
mode.input.push(c)
} else {
bail!("Can't push search character outside of search insert mode")
}
} else {
bail!("Last key press wasn't a character")
}
Ok(())
}
pub fn pop_search_char(app: &mut Application) -> Result {
if let Mode::LineJump(ref mut mode) = app.mode {
mode.input.pop()
} else {
bail!("Can't pop search character outside of search insert mode")
};
Ok(())
}
#[cfg(test)]
mod tests {
use crate::commands;
use crate::models::application::{Application, Mode};
use scribe::buffer::Position;
use scribe::Buffer;
#[test]
fn accept_input_moves_cursor_to_requested_line_and_changes_modes() {
let mut app = Application::new(&Vec::new()).unwrap();
let mut buffer = Buffer::new();
buffer.insert("nexedit");
app.workspace.add_buffer(buffer);
commands::application::switch_to_line_jump_mode(&mut app).unwrap();
match app.mode {
Mode::LineJump(ref mut mode) => mode.input = "3".to_string(),
_ => (),
};
commands::line_jump::accept_input(&mut app).unwrap();
assert_eq!(
*app.workspace.current_buffer.as_ref().unwrap().cursor,
Position { line: 2, offset: 0 }
);
assert!(match app.mode {
crate::models::application::Mode::Normal => true,
_ => false,
});
}
#[test]
fn accept_input_handles_unavailable_offsets() {
let mut app = Application::new(&Vec::new()).unwrap();
let mut buffer = Buffer::new();
buffer.insert("nexedit");
buffer.cursor.move_to(Position { line: 1, offset: 3 });
app.workspace.add_buffer(buffer);
commands::application::switch_to_line_jump_mode(&mut app).unwrap();
match app.mode {
Mode::LineJump(ref mut mode) => mode.input = "3".to_string(),
_ => (),
};
commands::line_jump::accept_input(&mut app).unwrap();
assert_eq!(
*app.workspace.current_buffer.as_ref().unwrap().cursor,
Position { line: 2, offset: 3 }
);
assert!(match app.mode {
crate::models::application::Mode::Normal => true,
_ => false,
});
}
#[test]
fn accept_input_ignores_zero_input() {
let mut app = Application::new(&Vec::new()).unwrap();
let mut buffer = Buffer::new();
buffer.insert("nexedit");
app.workspace.add_buffer(buffer);
commands::application::switch_to_line_jump_mode(&mut app).unwrap();
match app.mode {
Mode::LineJump(ref mut mode) => mode.input = "0".to_string(),
_ => (),
};
commands::line_jump::accept_input(&mut app).unwrap();
assert_eq!(
*app.workspace.current_buffer.as_ref().unwrap().cursor,
Position { line: 0, offset: 0 }
);
assert!(match app.mode {
crate::models::application::Mode::Normal => true,
_ => false,
});
}
}