use crate::commands::{self, Result};
use crate::errors::*;
use crate::input::Key;
use crate::models::application::{Application, Mode};
use std::path::PathBuf;
pub fn push_char(app: &mut Application) -> Result {
let last_key = app
.view
.last_key()
.as_ref()
.ok_or("View hasn't tracked a key press")?;
if let Key::Char(c) = *last_key {
if let Mode::Path(ref mut mode) = app.mode {
mode.push_char(c);
} else {
bail!("Cannot push char outside of path mode");
}
} else {
bail!("Last key press wasn't a character");
}
Ok(())
}
pub fn pop_char(app: &mut Application) -> Result {
if let Mode::Path(ref mut mode) = app.mode {
mode.pop_char();
} else {
bail!("Cannot pop char outside of path mode");
}
Ok(())
}
pub fn accept_path(app: &mut Application) -> Result {
let save_on_accept = if let Mode::Path(ref mut mode) = app.mode {
let current_buffer = app
.workspace
.current_buffer
.as_mut()
.ok_or(BUFFER_MISSING)?;
let path_name = mode.input.clone();
if path_name.is_empty() {
bail!("Please provide a non-empty path")
}
current_buffer.path = Some(PathBuf::from(path_name));
mode.save_on_accept
} else {
bail!("Cannot accept path outside of path mode");
};
app.workspace
.update_current_syntax()
.chain_err(|| BUFFER_SYNTAX_UPDATE_FAILED)?;
app.mode = Mode::Normal;
if save_on_accept {
commands::buffer::save(app)
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::commands;
use crate::models::application::Mode;
use crate::models::Application;
use scribe::Buffer;
use std::path::{Path, PathBuf};
#[test]
fn accept_path_sets_buffer_path_based_on_input_and_switches_to_normal_mode() {
let mut app = Application::new(&Vec::new()).unwrap();
let buffer = Buffer::new();
app.workspace.add_buffer(buffer);
commands::application::switch_to_path_mode(&mut app).unwrap();
if let Mode::Path(ref mut mode) = app.mode {
mode.input = String::from("new_path");
}
super::accept_path(&mut app).unwrap();
assert_eq!(
app.workspace.current_buffer.as_ref().unwrap().path,
Some(PathBuf::from("new_path"))
);
if let Mode::Normal = app.mode {
} else {
panic!("Not in normal mode");
}
}
#[test]
fn accept_path_respects_save_on_accept_flag() {
let mut app = Application::new(&Vec::new()).unwrap();
let buffer = Buffer::new();
app.workspace.add_buffer(buffer);
commands::application::switch_to_path_mode(&mut app).unwrap();
if let Mode::Path(ref mut mode) = app.mode {
mode.input = Path::new(concat!(env!("OUT_DIR"), "new_path"))
.to_string_lossy()
.into();
mode.save_on_accept = true;
}
super::accept_path(&mut app).unwrap();
assert!(!app.workspace.current_buffer.as_ref().unwrap().modified());
}
#[test]
fn accept_path_doesnt_set_buffer_path_for_empty_input_and_doesnt_change_modes() {
let mut app = Application::new(&Vec::new()).unwrap();
let buffer = Buffer::new();
app.workspace.add_buffer(buffer);
commands::application::switch_to_path_mode(&mut app).unwrap();
if let Mode::Path(ref mut mode) = app.mode {
mode.input = String::from("");
}
let result = super::accept_path(&mut app);
assert!(result.is_err());
assert!(app
.workspace
.current_buffer
.as_ref()
.unwrap()
.path
.is_none());
if let Mode::Path(_) = app.mode {
} else {
panic!("Not in path mode");
}
}
#[test]
fn accept_path_updates_syntax() {
let mut app = Application::new(&Vec::new()).unwrap();
let buffer = Buffer::new();
app.workspace.add_buffer(buffer);
commands::application::switch_to_path_mode(&mut app).unwrap();
if let Mode::Path(ref mut mode) = app.mode {
mode.input = String::from("path.rs");
}
super::accept_path(&mut app).unwrap();
assert_eq!(
app.workspace
.current_buffer
.as_ref()
.unwrap()
.syntax_definition
.as_ref()
.unwrap()
.name,
"Rust"
);
}
}