use crate::{
DEBUG, buffer::Buffer, file_io::try_get_git_hash, mode::Mode, register::RegisterHandler,
status_bar::StatusBar, undo::UndoTree, utility::SplitOnce, view::View, view_box::ViewBox,
view_command::split_curr_view_box_horizontal,
};
use anyhow::Result;
use ropey::Rope;
use std::path::PathBuf;
use tree_sitter::Parser;
pub fn match_meta_command(
status_bar: &mut StatusBar,
view: &mut View,
register_handler: &RegisterHandler,
undo_tree: &mut UndoTree,
mode: &mut Mode,
) -> Result<bool> {
let (command, arg) = status_bar[1..]
.split_once_a(|c| *c == ' ' || *c == '/')
.unwrap_or_else(|| (&status_bar[1..], &[]));
let (command, arg): (String, String) = (command.iter().collect(), arg.iter().collect());
match command.as_str() {
"write" | "w" => view.write()?,
"quit" | "q" => return Ok(true),
"wq" => {
view.write()?;
return Ok(true);
}
"undo" | "u" => view.set_path(None),
"load" | "l" => {
view.load_file()?;
let view_box = view.get_view_box();
view_box.flush(false)?;
}
"open" | "o" => {
attach_buffer(&arg, view.get_view_box());
view.load_file()?;
let view_box = view.get_view_box();
view_box.flush(false)?;
}
"sub" | "s" => {
let buffer = view.get_buffer_mut();
log!("arg {}", arg);
substitute_cmd(buffer, &arg, undo_tree);
}
"dir" => {
if view.get_buffer().rope.len_chars() == 0 {
print_directories(view, undo_tree)?;
}
split_curr_view_box_horizontal(view);
let anchor = view.cursor;
view.cursor = view.boxes.len() - 1;
print_directories(view, undo_tree)?;
view.cursor = anchor;
}
"reg" => {
let registers = register_handler.to_string();
log!("registers: {}", registers);
if view.get_buffer().rope.len_chars() == 0 {
view.get_buffer_mut()
.replace_contents(®isters, undo_tree);
}
split_curr_view_box_horizontal(view);
let anchor = view.cursor;
view.cursor = view.boxes.len() - 1;
view.get_buffer_mut()
.replace_contents(®isters, undo_tree);
view.cursor = anchor;
}
n => {
if let Ok(num) = n.parse::<usize>() {
let buffer = view.get_buffer_mut();
buffer.set_row(num + 1);
} else {
log!("Unknown Meta-Command: {}", n);
}
}
}
*mode = Mode::Normal;
status_bar.clear();
Ok(false)
}
pub fn substitute_cmd(buffer: &mut Buffer, arg: &str, undo_tree: &mut UndoTree) {
if arg.len() < 3 {
return;
}
let substitution: Vec<&str> = arg.split('/').collect();
if substitution.len() != 2 {
log!(
"Malformed substitution meta-command: {:?}. Should be in the form: s/[orig]/[new]",
substitution
);
return;
}
let original: Vec<char> = substitution[0].chars().collect();
let new: String = substitution[1].chars().collect();
let idxs_of_substitution = buffer.find_occurences(&original);
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 = PathBuf::from("./");
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[0..contents.len() - 1], undo_tree);
Ok(())
}
pub fn attach_buffer(arg: &str, view_box: &mut ViewBox) {
let path_buf = PathBuf::from(arg.trim());
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.clone());
view_box.git_hash = try_get_git_hash(view_box.path.as_ref());
if let Some(ext) = path_buf.extension()
&& (ext == "c" || ext == "h")
{
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_c::LANGUAGE.into())
.expect("Failed to load C parser");
view_box.parser = Some(parser);
}
}