made usage info, fixed configuration parsing, and made a better error for unimplemented subcommands

This commit is contained in:
Emma Tebibyte 2023-03-25 05:03:27 -04:00
parent 261b40cc0b
commit 53bd5ce4b3
Signed by: emma
GPG Key ID: 6D661C738815E7DD
4 changed files with 84 additions and 41 deletions

View File

@ -18,14 +18,19 @@
* Hopper. If not, see <https://www.gnu.org/licenses/>.
*/
use core::str::FromStr;
use core::{
fmt,
str::FromStr,
};
pub use arg::Args;
#[derive(Args, Debug)]
pub struct Arguments {
pub argv0: String,
#[arg(short = "v")]
pub v: bool,
pub v: Option<bool>,
#[arg(sub)]
pub sub: Command,
@ -85,6 +90,19 @@ pub enum Command {
Update(HopArgs),
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
Command::Add(_) => write!(f, "add"),
Command::Get(_) => write!(f, "get"),
Command::Init(_) => write!(f, "init"),
Command::List(_) => write!(f, "list"),
Command::Remove(_) => write!(f, "remove"),
Command::Update(_) => write!(f, "update"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum PackageType {
Mod(Loader),

View File

@ -67,9 +67,8 @@ impl HopperClient {
let mut urls = Vec::new();
for entry in self.config.sources.drain() {
let (source, domain) = entry;
urls.push(format!("{}/v2/search", domain));
for entry in self.config.sources.modrinth.iter() {
urls.push(format!("{}/v2/search", entry));
}
let mut params = vec![("query", search_args.package_name.to_owned())];

View File

@ -19,14 +19,12 @@
*/
use std::{
collections::HashMap,
fs::File,
io::Read,
path::PathBuf,
};
use serde::Deserialize;
use toml::de::ValueDeserializer;
use xdg::BaseDirectories;
use yacexits::{
EX_DATAERR,
@ -36,11 +34,16 @@ use yacexits::{
#[derive(Deserialize)]
pub struct Config {
pub hopfiles: Vec<String>,
pub sources: HashMap<String, String>,
pub sources: Sources,
}
#[derive(Deserialize)]
pub struct Sources {
pub modrinth: Vec<String>,
}
pub fn get_config(dirs: BaseDirectories) -> Result<PathBuf, (String, u32)> {
match dirs.place_config_file("hopper.toml") {
match dirs.place_config_file("config.toml") {
Ok(file) => Ok(file),
Err(_) => {
Err((
@ -59,21 +62,18 @@ impl Config {
Ok(file) => file,
Err(_) => {
return Err((
format!(
"{}: Permission denied.",
config_path
.clone()
.into_os_string()
.into_string()
.unwrap()
),
format!("{}: Permission denied.", config_path.display()),
EX_UNAVAILABLE,
));
},
};
match config_file.read_to_end(&mut buf) {
Ok(_) => {},
if let Some(err) = config_file.read_to_end(&mut buf).err() {
return Err((format!("{:?}", err), EX_DATAERR));
};
let toml = match String::from_utf8(buf) {
Ok(contents) => contents,
Err(err) => {
return Err((
format!("{:?}", err),
@ -82,19 +82,16 @@ impl Config {
},
};
let toml = match String::from_utf8(buf) {
Ok(contents) => contents,
Err(_) => {
return Err((
format!("Invalid configuration file."),
EX_DATAERR,
));
},
};
match Config::deserialize(ValueDeserializer::new(&toml)) {
match toml::from_str(&toml) {
Ok(val) => Ok(val),
Err(err) => Err((format!("{:?}", err), EX_DATAERR)),
Err(_) => {
Err((
format!(
"{}: Invalid configuration file.", config_path.display()
),
EX_DATAERR,
))
},
}
}
}

View File

@ -35,7 +35,9 @@ use hopfile::*;
use yacexits::{
exit,
EX_SOFTWARE,
EX_UNAVAILABLE,
EX_USAGE,
};
struct AppContext {
@ -46,20 +48,40 @@ struct AppContext {
#[tokio::main]
#[no_mangle]
async fn rust_main(arguments: c_main::Args) {
let args = Arguments::from_args(arguments.into_iter()).unwrap();
let argv: Vec<&str> = arguments.into_iter().collect();
let args: Arguments;
let xdg_dirs = match xdg::BaseDirectories::with_prefix("hopper") {
Ok(dirs) => dirs,
Err(err) => {
eprintln!("{:?}", err);
let usage_info = format!(
"Usage: {}{}",
argv[0],
" [-v] add | get | init | list | remove | update \n\n".to_owned() +
"add -f hopfiles... [-m version]\n" +
"get [-d directory] -m versions... [-n] [-t types...]\n" +
"init -d directory [-f hopfiles...] -m version -t type\n" +
"list [-f hopfiles...] [-m versions...] [-t types...]\n" +
"remove [-f hopfiles...] -m version -t type\n" +
"update [-f hopfiles...] [-m versions...] [-t types...]",
);
args = Arguments::from_args(argv.clone().into_iter()).unwrap_or_else(|_| {
eprintln!("{}", usage_info);
exit(EX_USAGE);
});
let xdg_dirs = xdg::BaseDirectories::with_prefix("hopper")
.unwrap_or_else(|_| {
eprintln!(
"{}: Unable to open configuration file: Permission denied.",
argv[0],
);
exit(EX_UNAVAILABLE);
},
};
});
let config_path = match get_config(xdg_dirs) {
Ok(path) => path,
Err((err, code)) => {
eprintln!("{:?}", err);
eprintln!("{}: {}", argv[0], err);
exit(code);
},
};
@ -67,7 +89,7 @@ async fn rust_main(arguments: c_main::Args) {
let config = match Config::read_config(config_path) {
Ok(file) => file,
Err((err, code)) => {
eprintln!("{:?}", err);
eprintln!("{}: {}", argv[0], err);
exit(code);
},
};
@ -77,6 +99,13 @@ async fn rust_main(arguments: c_main::Args) {
match ctx.args.sub {
// Command::Get(search_args) => cmd_get(&ctx, search_args).await,
// Command::Init(hopfile_args) => cmd_init(hopfile_args).await,
_ => unimplemented!("unimplemented subcommand"),
_ => {
eprintln!(
"{}: {}: Unimplemented subcommand.",
argv[0],
ctx.args.sub
);
exit(EX_SOFTWARE);
},
};
}