Parse multiple URLs via command line
Closes: #44, #47 I used pico-args over clap because the former only adds about 1KB of binary bloat whereas clap adds almost 1MB.
This commit is contained in:
parent
f441d24760
commit
3fd8641df2
4 changed files with 76 additions and 19 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1083,6 +1083,7 @@ dependencies = [
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"log",
|
"log",
|
||||||
"mpris-server",
|
"mpris-server",
|
||||||
|
"pico-args",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
"smol_str",
|
"smol_str",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ serde = { version = "1", features = ["serde_derive"] }
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
tokio = "1"
|
tokio = "1"
|
||||||
url = "2"
|
url = "2"
|
||||||
|
pico-args = "0.5"
|
||||||
# Internationalization
|
# Internationalization
|
||||||
icu_collator = "1.5"
|
icu_collator = "1.5"
|
||||||
icu_provider = { version = "1.5", features = ["sync"] }
|
icu_provider = { version = "1.5", features = ["sync"] }
|
||||||
|
|
|
||||||
71
src/argparse.rs
Normal file
71
src/argparse.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2024 System76 <info@system76.com>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use std::{fs, io};
|
||||||
|
|
||||||
|
use log::warn;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Arguments {
|
||||||
|
/// URLs to play with associated metadata
|
||||||
|
pub urls: Vec<Url>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arguments {
|
||||||
|
pub fn from_args() -> Result<Self, pico_args::Error> {
|
||||||
|
let mut parser = pico_args::Arguments::from_env();
|
||||||
|
|
||||||
|
// Freestanding arguments are treated as URLs
|
||||||
|
let urls: Vec<Url> = std::iter::from_fn(|| {
|
||||||
|
parser
|
||||||
|
.opt_free_from_fn(|arg| Source::try_from(arg))
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.map(|source| source.0)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let remainder = parser.finish();
|
||||||
|
for arg in remainder {
|
||||||
|
warn!("Unused argument: {arg:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Arguments { urls })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
|
// pub enum Source {
|
||||||
|
// File(Url),
|
||||||
|
// Directory(Url),
|
||||||
|
// // TODO: GStreamer handles streaming out of the box
|
||||||
|
// Other(Url),
|
||||||
|
// }
|
||||||
|
|
||||||
|
struct Source(Url);
|
||||||
|
|
||||||
|
impl TryFrom<&str> for Source {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn try_from(arg: &str) -> Result<Self, Self::Error> {
|
||||||
|
match url::Url::parse(arg) {
|
||||||
|
Ok(url) => Ok(Source(url)),
|
||||||
|
Err(_) => match fs::canonicalize(arg) {
|
||||||
|
Ok(path) => {
|
||||||
|
match Url::from_file_path(&path).or_else(|_| Url::from_directory_path(&path)) {
|
||||||
|
Ok(url) => Ok(Source(url)),
|
||||||
|
Err(()) => {
|
||||||
|
warn!("failed to parse path {:?}", path);
|
||||||
|
Err(io::Error::other("Invalid URL and path"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("failed to parse argument {:?}: {}", arg, err);
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main.rs
22
src/main.rs
|
|
@ -37,6 +37,7 @@ use crate::{
|
||||||
project::ProjectNode,
|
project::ProjectNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod argparse;
|
||||||
mod config;
|
mod config;
|
||||||
mod key_bind;
|
mod key_bind;
|
||||||
mod localize;
|
mod localize;
|
||||||
|
|
@ -110,25 +111,8 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
settings = settings.theme(config.app_theme.theme());
|
settings = settings.theme(config.app_theme.theme());
|
||||||
settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0));
|
settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0));
|
||||||
|
|
||||||
let url_opt = match std::env::args().nth(1) {
|
let args = argparse::Arguments::from_args().unwrap_or_default();
|
||||||
Some(arg) => match url::Url::parse(&arg) {
|
let url_opt = args.urls.into_iter().next();
|
||||||
Ok(url) => Some(url),
|
|
||||||
Err(_) => match fs::canonicalize(&arg) {
|
|
||||||
Ok(path) => match url::Url::from_file_path(&path).or_else(|_| url::Url::from_directory_path(&path)) {
|
|
||||||
Ok(url) => Some(url),
|
|
||||||
Err(()) => {
|
|
||||||
log::warn!("failed to parse path {:?}", path);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
log::warn!("failed to parse argument {:?}: {}", arg, err);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let flags = Flags {
|
let flags = Flags {
|
||||||
config_handler,
|
config_handler,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue