use super::*;
use crate::options::MenuEntry;
pub struct UserMenu {
pub entries: Vec<MenuEntry>,
pub index: usize,
pub file: Option<PathBuf>,
}
pub struct MenuValues {
pub file: Option<PathBuf>,
pub files: Vec<PathBuf>,
pub dir: PathBuf,
pub other: PathBuf,
}
pub struct UserCommand {
pub label: String,
pub process: std::process::Command,
pub pause: bool,
}
impl AppState {
pub fn open_user_menu(&mut self) {
let file = crate::options::menu_file();
let entries = crate::options::load_menu();
self.dialog = Some(Dialog::UserMenu(Box::new(UserMenu { entries, index: 0, file })));
}
pub fn move_user_menu_cursor(&mut self, step: isize) {
if let Some(Dialog::UserMenu(menu)) = &mut self.dialog {
menu.index = menu.index.saturating_add_signed(step).min(menu.entries.len().saturating_sub(1));
}
}
pub fn edit_user_menu(&mut self) {
let Some(Dialog::UserMenu(menu)) = self.dialog.take() else {
return;
};
let Some(file) = menu.file else {
self.display_error(t!("No config directory to keep a menu in").to_string());
return;
};
if self.options.editor.trim().is_empty() {
self.request_open(file, true);
} else {
self.external_edit = Some(file);
}
}
}
pub fn uses_entries(command: &str) -> (bool, bool) {
let file = ["{file}", "{name}"].iter().any(|placeholder| command.contains(placeholder));
(file, command.contains("{files}"))
}
pub fn shell_command(command: &str, values: &MenuValues) -> std::process::Command {
let name = values.file.as_ref().and_then(|file| file.file_name()).map(OsString::from).unwrap_or_default();
let file = values.file.clone().unwrap_or_default();
#[cfg(windows)]
let script = {
let files: Vec<String> = (1..=values.files.len()).map(|n| format!("\"%FM84_FILE_{n}%\"")).collect();
command
.replace("{files}", &files.join(" "))
.replace("{file}", "\"%FM84_FILE%\"")
.replace("{name}", "\"%FM84_NAME%\"")
.replace("{dir}", "\"%FM84_DIR%\"")
.replace("{other}", "\"%FM84_OTHER%\"")
};
#[cfg(not(windows))]
let script = command
.replace("{files}", "\"$@\"")
.replace("{file}", "\"$FM84_FILE\"")
.replace("{name}", "\"$FM84_NAME\"")
.replace("{dir}", "\"$FM84_DIR\"")
.replace("{other}", "\"$FM84_OTHER\"");
#[cfg(windows)]
let mut process = {
use std::os::windows::process::CommandExt;
let mut process = std::process::Command::new("cmd");
process.raw_arg(format!("/S /C \"{script}\""));
for (n, path) in values.files.iter().enumerate() {
process.env(format!("FM84_FILE_{}", n + 1), path);
}
process
};
#[cfg(not(windows))]
let mut process = {
let mut process = std::process::Command::new("sh");
process.arg("-c").arg(script).arg("fm84").args(&values.files);
process
};
process.env("FM84_FILE", file).env("FM84_NAME", name).env("FM84_DIR", &values.dir).env("FM84_OTHER", &values.other).current_dir(&values.dir);
process
}