use crate::{
DEBUG, buffer::Buffer, global_state::GlobalState, mode::Mode, 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;
pub fn match_meta_command(global_state: &mut GlobalState, view: &mut View) -> Result<bool> {
let (command, arg): (&[char], &[char]) = global_state.status_bar[1..]
.split_once_a(|c| *c == ' ' || *c == '/')
.unwrap_or_else(|| (&global_state.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);
}
"unattach" | "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();
substitute_cmd(buffer, &arg, &mut global_state.undo_tree);
}
"dir" | "d" => {
if view.get_buffer().rope.len_chars() == 0 {
print_directories(view, &mut global_state.undo_tree)?;
return Ok(false);
}
split_curr_view_box_horizontal(view);
let anchor = view.cursor;
view.cursor = view.boxes.len() - 1;
print_directories(view, &mut global_state.undo_tree)?;
view.cursor = anchor;
}
"reg" => {
let registers = &mut global_state.register_handler.to_string();
if view.get_buffer().rope.len_chars() == 0 {
view.get_buffer_mut()
.replace_contents(registers, &mut global_state.undo_tree);
}
split_curr_view_box_horizontal(view);
let anchor = view.cursor;
view.cursor = view.boxes.len() - 1;
view.get_buffer_mut()
.replace_contents(registers, &mut global_state.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);
}
}
}
global_state.mode = Mode::Normal;
global_state.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.set_path(Some(path_buf));
}