made usage info, fixed configuration parsing, and made a better error for unimplemented subcommands
This commit is contained in:
parent
261b40cc0b
commit
53bd5ce4b3
22
src/args.rs
22
src/args.rs
|
@ -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),
|
||||
|
|
|
@ -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())];
|
||||
|
|
|
@ -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,
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
49
src/main.rs
49
src/main.rs
|
@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue