use crate::{
DEBUG, buffer::Buffer, io::try_get_git_hash, log, mode::Mode, register::RegisterHandler,
status_bar::StatusBar, undo::UndoTree, view::View, view_box::ViewBox,
view_command::split_curr_view_box_vertical,
};
use anyhow::Result;
use ropey::Rope;
use std::path::PathBuf;
#[allow(clippy::too_many_arguments)]
pub fn match_meta_command(
status_bar: &mut StatusBar,
view: &mut View,
register_handler: &RegisterHandler,
undo_tree: &mut UndoTree,
mode: &mut Mode,
) -> Result<bool> {
for (i, command) in status_bar.iter().enumerate().skip(1) {
match command {
'w' => view.write()?,
'u' => {
view.set_path(None);
}
'l' => {
view.load_file()?;
let view_box = view.get_view_box();
view_box.flush(false)?;
}
'o' => {
attach_buffer(status_bar, i, view.get_view_box());
view.load_file()?;
let view_box = view.get_view_box();
view_box.flush(false)?;
break;
}
'd' => {
split_curr_view_box_vertical(view);
print_directories(view, undo_tree)?;
}
'r' => {
let registers = register_handler.to_string();
view.split_view_box_vertical(view.cursor);
let last_idx = view.boxes_len() - 1;
view.replace_buffer_contents(®isters, last_idx, undo_tree);
}
's' => {
let buffer = view.get_buffer_mut();
substitute_cmd(buffer, status_bar, undo_tree, i);
break;
}
n if n.is_numeric() => {
let num_str = status_bar[i..].iter().collect::<String>();
let num: usize = match num_str.parse() {
Ok(n) => n,
Err(err) => {
log!("Failed to parse number: {} ({})", num_str, err);
break;
}
};
let buffer = view.get_buffer_mut();
buffer.set_row(num + 1);
}
'q' => return Ok(true),
c => log!("Unknown Meta-Command: {}", c),
}
}
*mode = Mode::Normal;
status_bar.clear();
Ok(false)
}
pub fn substitute_cmd(
buffer: &mut Buffer,
status_bar: &StatusBar,
undo_tree: &mut UndoTree,
i: usize,
) {
if status_bar[i..].len() == 1 {
return;
}
let substitution: Vec<&[char]> = status_bar[i + 1..].split(|c| *c == '/').collect();
if substitution.len() != 3 || !substitution[0].is_empty() {
log!(
"Malformed substitution meta-command: {:?}. Should be in the form: s/[orig]/[new]",
substitution
);
return;
}
let original = substitution[1];
let new: String = substitution[2].iter().collect();
log!("Substition\n\tOriginal: {:?}\n\tNew: {}", original, new);
let idxs_of_substitution = buffer.find_occurences(original);
log!("\tIndexes of Substitution: {:?}", idxs_of_substitution);
buffer.replace_text(
&new,
&original.iter().collect::<String>(),
&idxs_of_substitution,
undo_tree,
false,
);
buffer.update_list_set(.., true);
buffer.has_changed = true;
}
pub fn print_directories(view: &mut View, undo_tree: &mut UndoTree) -> Result<()> {
let path = view.get_path().map_or_else(
|| PathBuf::from("./"),
|p| {
let mut p = p.clone();
p.pop();
p
},
);
let dir = std::fs::read_dir(path)?;
let contents = dir
.filter_map(std::result::Result::ok)
.map(|item| {
let mut path = item.file_name().to_string_lossy().to_string();
path.push('\n');
path
})
.collect::<String>();
view.get_buffer_mut().replace_contents(contents, undo_tree);
Ok(())
}
pub fn attach_buffer(status_bar: &StatusBar, i: usize, view_box: &mut ViewBox) {
if status_bar.len() == i + 1 {
return;
}
let path_buf = PathBuf::from(status_bar[i + 1..].iter().collect::<String>().trim());
log!("Set path to equal: {}", path_buf.to_string_lossy());
if let Some(_path) = &view_box.path {
view_box.buffer.rope = Rope::new();
view_box.buffer.cursor = 0;
view_box.buffer.lines_for_updating = Vec::new();
view_box.buffer.has_changed = true;
}
view_box.path = Some(path_buf);
view_box.git_hash = try_get_git_hash(view_box.path.as_ref());
}