nexedit 0.2.2

A vim-like text editor, with simple shortcuts.
Documentation
use crate::commands::Result;
use crate::errors::*;
use crate::input::Key;
use crate::models::application::modes::jump;
use crate::models::application::modes::JumpMode;
use crate::models::application::{Application, Mode};
use scribe::Workspace;
use std::mem;

pub fn match_tag(app: &mut Application) -> Result {
    let result = if let Mode::Jump(ref mut jump_mode) = app.mode {
        match jump_mode.input.len() {
            0 => return Ok(()), // Not enough data to match to a position.
            1 => {
                if jump_mode.first_phase {
                    jump_to_tag(jump_mode, &mut app.workspace)
                } else {
                    return Ok(()); // Not enough data to match to a position.
                }
            }
            _ => jump_to_tag(jump_mode, &mut app.workspace),
        }
    } else {
        bail!("Can't match jump tags outside of jump mode.");
    };
    switch_to_previous_mode(app);

    result
}

fn jump_to_tag(jump_mode: &mut JumpMode, workspace: &mut Workspace) -> Result {
    let position = jump_mode
        .map_tag(&jump_mode.input)
        .ok_or("Couldn't find a position for the specified tag")?;
    let buffer = workspace.current_buffer.as_mut().ok_or(BUFFER_MISSING)?;

    if !buffer.cursor.move_to(*position) {
        bail!(
            "Couldn't move to the specified tag's position ({:?})",
            position
        )
    }

    Ok(())
}

fn switch_to_previous_mode(app: &mut Application) {
    let old_mode = mem::replace(&mut app.mode, Mode::Normal);

    if let Mode::Jump(jump_mode) = old_mode {
        match jump_mode.select_mode {
            jump::SelectModeOptions::None => (),
            jump::SelectModeOptions::Select(select_mode) => {
                app.mode = Mode::Select(select_mode);
            }
            jump::SelectModeOptions::SelectLine(select_mode) => {
                app.mode = Mode::SelectLine(select_mode);
            }
        }
    }
}

pub fn push_search_char(app: &mut Application) -> Result {
    if let Some(ref key) = *app.view.last_key() {
        if let Mode::Jump(ref mut mode) = app.mode {
            match *key {
                Key::Char('f') => {
                    if mode.first_phase {
                        mode.first_phase = false;
                    } else {
                        mode.input.push('f');
                    }
                }
                Key::Char(c) => mode.input.push(c),
                _ => bail!("Last key press wasn't a character"),
            }
        } else {
            bail!("Can't push jump character outside of jump mode")
        }
    } else {
        bail!("View hasn't tracked a key press")
    }

    match_tag(app)
}