mod desktop;
mod support;
use clap::{Parser, Subcommand};
use support::ExecEntry;
pub struct Context {
pub xdg_data_dirs: String,
}
pub enum SideEffect {
Exec(String),
Print(String),
}
pub trait Executable {
fn execute(&self, context: Context) -> Result<Vec<SideEffect>, &'static str>;
}
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
#[clap(propagate_version = true)]
pub struct Args {
#[clap(subcommand)]
pub command: Command,
}
#[derive(Subcommand)]
pub enum Command {
#[clap(subcommand)]
App(AppCommand),
#[clap(subcommand)]
Path(PathCommand),
}
impl Executable for Command {
fn execute(&self, context: Context) -> Result<Vec<SideEffect>, &'static str> {
match &self {
Self::App(command) => command.execute(context),
Self::Path(command) => command.execute(context),
}
}
}
#[derive(Subcommand)]
pub enum AppCommand {
Ls,
How { name: String },
Exec { name: String },
Which { name: String },
}
impl Executable for AppCommand {
fn execute(&self, context: Context) -> Result<Vec<SideEffect>, &'static str> {
match &self {
Self::Ls => {
let exec_entries = support::parse_sorted_data_dirs(&context.xdg_data_dirs);
let output = exec_entries
.into_iter()
.map(|ExecEntry { name, .. }| name)
.collect::<Vec<String>>()
.join("\n");
let print_se = SideEffect::Print(output);
Ok(vec![print_se])
}
Self::Exec { name } => {
let maybe_found = support::find_by_name(&context.xdg_data_dirs, name)
.map(|ExecEntry { exec, .. }| support::normalize_exec(&exec));
match maybe_found {
Some(exec) => Ok(vec![SideEffect::Exec(exec)]),
None => Err("no such application name"),
}
}
Self::How { name } => {
let maybe_found = support::find_by_name(&context.xdg_data_dirs, name)
.map(|ExecEntry { exec, .. }| support::normalize_exec(&exec));
match maybe_found {
Some(exec) => Ok(vec![SideEffect::Print(exec)]),
None => Err("no such application name"),
}
}
Self::Which { name } => {
let maybe_found = support::find_by_name(&context.xdg_data_dirs, name);
match maybe_found {
Some(ExecEntry { path, .. }) => {
Ok(vec![SideEffect::Print(support::path_to_string(path))])
}
None => Err("no such application name"),
}
}
}
}
}
#[derive(Subcommand)]
pub enum PathCommand {
Ls,
}
impl Executable for PathCommand {
fn execute(&self, context: Context) -> Result<Vec<SideEffect>, &'static str> {
match &self {
Self::Ls => {
let exec_entries = support::parse_sorted_data_dirs(&context.xdg_data_dirs);
let output = exec_entries
.into_iter()
.map(|ExecEntry { path, .. }| path)
.map(support::path_to_string)
.collect::<Vec<String>>()
.join("\n");
let print_se = SideEffect::Print(output);
Ok(vec![print_se])
}
}
}
}