bong CLI template
This commit is contained in:
parent
52c15986a8
commit
6bb627d77b
7 changed files with 136 additions and 45 deletions
|
@ -40,7 +40,7 @@ mod dynamic {
|
|||
use cfg_if::cfg_if;
|
||||
#[cfg(feature = "fonts")]
|
||||
use font_kit::error::FontLoadingError;
|
||||
use infer::MatcherType;
|
||||
pub use infer::MatcherType;
|
||||
#[cfg(feature = "documents")]
|
||||
use printpdf::PdfDocument;
|
||||
#[cfg(feature = "documents")]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub use symphonia::core::sample::Sample;
|
||||
pub use symphonia::core::*;
|
||||
mod raw;
|
||||
pub use raw::*;
|
||||
mod simphonia;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use super::Sample;
|
||||
use super::sample::Sample;
|
||||
use cfg_if::cfg_if;
|
||||
use derive_wrapper::{AsRef, From};
|
||||
use num::{
|
||||
|
|
|
@ -17,7 +17,7 @@ use thiserror::Error;
|
|||
|
||||
use crate::IntoDataBytes;
|
||||
|
||||
use super::{RawSamples, Sample};
|
||||
use super::{sample::Sample, RawSamples};
|
||||
|
||||
/// Audio, unlike DynamicImage, isn't directly bendable
|
||||
/// because its underlying data format isn't decided automatically
|
||||
|
|
|
@ -11,7 +11,10 @@ keywords.workspace = true
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
anyhow = "*"
|
||||
bingus = { path = "../bingus" }
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
unwrap-infallible = "0.1"
|
||||
strum = { version = "*", features = ["derive"] }
|
||||
derive-new = "*"
|
||||
clap = { version = "4.5.40", features = ["derive"] }
|
||||
derive_wrapper = "0.1.7"
|
||||
# unwrap-infallible = "0.1"
|
||||
|
|
129
bong/src/cli.rs
129
bong/src/cli.rs
|
@ -1,11 +1,130 @@
|
|||
use std::path::PathBuf;
|
||||
use std::{
|
||||
io::{self, stdin, stdout},
|
||||
ops::Not,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use derive_new::new;
|
||||
use derive_wrapper::AsRef;
|
||||
use strum::{AsRefStr, EnumIter, EnumString};
|
||||
|
||||
#[derive(new, Parser)]
|
||||
#[clap(version, author, about)]
|
||||
/// CLI from the Bent project
|
||||
#[derive(Parser)]
|
||||
pub(super) struct Cli {
|
||||
/// Input file or standard input.
|
||||
pub(super) input: PathBuf,
|
||||
pub(super) output: PathBuf,
|
||||
/// Input format (leave empty for auto mode)
|
||||
#[arg(short, long)]
|
||||
pub(super) input_format: Option<MatcherType>,
|
||||
/// Input file or standard input ("-").
|
||||
pub(super) input: FileOrStd<Stdin>,
|
||||
// /// List of commands (process or bend to another format)
|
||||
// pub(super) commands: Vec<Command>,
|
||||
/// Onput file or standard output ("-").
|
||||
pub(super) output: FileOrStd<Stdout>,
|
||||
}
|
||||
|
||||
#[derive(AsRef)]
|
||||
#[cfg_attr(debug_assertions, derive(Debug))]
|
||||
struct File(std::fs::File);
|
||||
|
||||
impl Clone for File {
|
||||
fn clone(&self) -> Self {
|
||||
File(
|
||||
self.0
|
||||
.try_clone()
|
||||
.expect("can't clone this file's handle :("),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for File {
|
||||
type Err = io::Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
std::fs::File::open(s).map(File)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct Stdin;
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct Stdout;
|
||||
|
||||
trait New {
|
||||
type Real;
|
||||
fn new() -> Self::Real;
|
||||
}
|
||||
|
||||
impl New for Stdin {
|
||||
type Real = std::io::Stdin;
|
||||
fn new() -> Self::Real {
|
||||
stdin()
|
||||
}
|
||||
}
|
||||
|
||||
impl New for Stdout {
|
||||
type Real = std::io::Stdout;
|
||||
fn new() -> Self::Real {
|
||||
stdout()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Default> FromStr for FileOrStd<S> {
|
||||
type Err = io::Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
s.is_empty()
|
||||
.not()
|
||||
.then_some(s.parse().map(FileOrStd::File))
|
||||
.unwrap_or(Ok(FileOrStd::Std(Default::default())))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(debug_assertions, derive(Debug))]
|
||||
pub(super) enum FileOrStd<S: Clone> {
|
||||
File(File),
|
||||
Std(S),
|
||||
}
|
||||
|
||||
pub(super) enum OutputFormat {}
|
||||
|
||||
// #[derive(Clone)]
|
||||
// pub(super) enum Command {
|
||||
// Into(Bendable),
|
||||
// Process(Process),
|
||||
// }
|
||||
|
||||
#[derive(EnumString, AsRefStr, Clone)]
|
||||
pub(super) enum Bendable {
|
||||
#[strum(serialize = "bin", serialize = "binary")]
|
||||
Binary,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(super) enum Process {}
|
||||
|
||||
#[derive(EnumString, EnumIter, Clone, Copy)]
|
||||
enum MatcherType {
|
||||
Audio,
|
||||
Doc,
|
||||
Font,
|
||||
Image,
|
||||
Pdf,
|
||||
Text,
|
||||
Raw,
|
||||
}
|
||||
|
||||
impl From<MatcherType> for bingus::MatcherType {
|
||||
fn from(value: MatcherType) -> Self {
|
||||
use bingus::MatcherType::*;
|
||||
match value {
|
||||
MatcherType::Audio => Audio,
|
||||
MatcherType::Doc => Doc,
|
||||
MatcherType::Font => Font,
|
||||
MatcherType::Image => Image,
|
||||
MatcherType::Pdf => Archive,
|
||||
MatcherType::Text => Text,
|
||||
MatcherType::Raw => Custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +1,9 @@
|
|||
use std::fs::File;
|
||||
|
||||
use anyhow::{anyhow, Context, Error};
|
||||
use bingus::{
|
||||
img::{Dimensions, RgbImage},
|
||||
txt::{DocumentType, ShivaDocument, ShivaFormat},
|
||||
Bendable, Bytes,
|
||||
};
|
||||
use clap::Parser;
|
||||
use cli::Cli;
|
||||
use unwrap_infallible::UnwrapInfallible;
|
||||
|
||||
mod cli;
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let args = Cli::parse();
|
||||
let bytes = File::open(args.input_file)
|
||||
.context("opening file")?
|
||||
.bend_into::<ShivaDocument>(
|
||||
ShivaFormat::new(DocumentType::PDF, DocumentType::DOCX),
|
||||
Default::default(),
|
||||
)
|
||||
.map_err(|e| anyhow!("parsing PDF: {e}"))?
|
||||
.bend_into::<Bytes>((), Default::default())
|
||||
.unwrap_infallible();
|
||||
let dimensions = {
|
||||
let c = bytes.len().isqrt().try_into().context("image too big")?;
|
||||
Dimensions {
|
||||
width: c,
|
||||
height: c,
|
||||
}
|
||||
};
|
||||
bytes
|
||||
.bend_into::<RgbImage>(dimensions, Default::default())
|
||||
.context("bending into an image")?
|
||||
.save(args.output_file)
|
||||
.context("saving output file")?;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
Cli::parse();
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue