Started mod `args` for parsing arguments. Fortune for enumerate-ordered's current commit: Future small blessing − 末小吉master
parent
ba2680db8e
commit
e156e2cc1e
@ -0,0 +1,84 @@
|
||||
//! Arg parsing
|
||||
use super::*;
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
path::{
|
||||
Path, PathBuf,
|
||||
},
|
||||
borrow::Cow,
|
||||
};
|
||||
use tokio::{
|
||||
sync::{
|
||||
mpsc,
|
||||
},
|
||||
};
|
||||
use futures::{
|
||||
stream::{self, Stream, BoxStream, StreamExt,},
|
||||
};
|
||||
|
||||
/// Parsed command-line args
|
||||
#[derive(Debug)]
|
||||
pub struct Args
|
||||
{
|
||||
paths: Option<Vec<PathBuf>>,
|
||||
}
|
||||
|
||||
impl Args
|
||||
{
|
||||
/// Paths as an async stream
|
||||
///
|
||||
/// # Non-immediate
|
||||
/// When input paths come from `stdin`, the output stream will be non-immediate.
|
||||
pub fn paths(&self) -> BoxStream<'_, Cow<'_, Path>>
|
||||
{
|
||||
if let Some(paths) = self.paths.as_ref() {
|
||||
stream::iter(paths.iter().map(|x| Cow::Borrowed(Path::new(x)))).boxed()
|
||||
} else {
|
||||
let (tx, rx) = mpsc::channel(128);
|
||||
tokio::spawn(async move {
|
||||
use tokio::io::{
|
||||
self,
|
||||
AsyncReadExt, AsyncBufReadExt
|
||||
};
|
||||
let mut stdin = {
|
||||
tokio::io::BufReader::new(io::stdin())
|
||||
};
|
||||
let mut buf = Vec::with_capacity(1024);
|
||||
loop
|
||||
{
|
||||
buf.clear();
|
||||
use std::os::unix::prelude::*;
|
||||
let n = match stdin.read_until(b'\n', &mut buf).await {
|
||||
Ok(n) => n,
|
||||
Err(e) => {
|
||||
error!("paths: Failed to read input line: {}", e);
|
||||
break;
|
||||
},
|
||||
};
|
||||
if n == 0 {
|
||||
trace!("paths: Stdin exhausted. Stopping read.");
|
||||
break;
|
||||
}
|
||||
let path_bytes = &buf[..n];
|
||||
let path = Path::new(OsStr::from_bytes(path_bytes));
|
||||
if path.exists() {
|
||||
if tx.send(path.to_owned()).await.is_err() {
|
||||
trace!("paths: Stream dropped, cancelling stdin read.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
tokio_stream::wrappers::ReceiverStream::new(rx).map(|x| Cow::Owned(x)).boxed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse_args() -> eyre::Result<Args>
|
||||
{
|
||||
todo!("parse(std::env::args().skip(1))")
|
||||
}
|
||||
|
||||
//TODO: fn parse(args: impl IntoIterator<Item=String>) -> eyre::Result<Args>
|
||||
|
Loading…
Reference in new issue