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;
|
use cfg_if::cfg_if;
|
||||||
#[cfg(feature = "fonts")]
|
#[cfg(feature = "fonts")]
|
||||||
use font_kit::error::FontLoadingError;
|
use font_kit::error::FontLoadingError;
|
||||||
use infer::MatcherType;
|
pub use infer::MatcherType;
|
||||||
#[cfg(feature = "documents")]
|
#[cfg(feature = "documents")]
|
||||||
use printpdf::PdfDocument;
|
use printpdf::PdfDocument;
|
||||||
#[cfg(feature = "documents")]
|
#[cfg(feature = "documents")]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub use symphonia::core::sample::Sample;
|
pub use symphonia::core::*;
|
||||||
mod raw;
|
mod raw;
|
||||||
pub use raw::*;
|
pub use raw::*;
|
||||||
mod simphonia;
|
mod simphonia;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::Sample;
|
use super::sample::Sample;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use derive_wrapper::{AsRef, From};
|
use derive_wrapper::{AsRef, From};
|
||||||
use num::{
|
use num::{
|
||||||
|
|
|
@ -17,7 +17,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::IntoDataBytes;
|
use crate::IntoDataBytes;
|
||||||
|
|
||||||
use super::{RawSamples, Sample};
|
use super::{sample::Sample, RawSamples};
|
||||||
|
|
||||||
/// Audio, unlike DynamicImage, isn't directly bendable
|
/// Audio, unlike DynamicImage, isn't directly bendable
|
||||||
/// because its underlying data format isn't decided automatically
|
/// 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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "*"
|
||||||
bingus = { path = "../bingus" }
|
bingus = { path = "../bingus" }
|
||||||
clap = { version = "4.5", features = ["derive"] }
|
strum = { version = "*", features = ["derive"] }
|
||||||
unwrap-infallible = "0.1"
|
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 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
|
/// CLI from the Bent project
|
||||||
#[derive(Parser)]
|
|
||||||
pub(super) struct Cli {
|
pub(super) struct Cli {
|
||||||
/// Input file or standard input.
|
/// Input format (leave empty for auto mode)
|
||||||
pub(super) input: PathBuf,
|
#[arg(short, long)]
|
||||||
pub(super) output: PathBuf,
|
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 clap::Parser;
|
||||||
use cli::Cli;
|
use cli::Cli;
|
||||||
use unwrap_infallible::UnwrapInfallible;
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = Cli::parse();
|
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")?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue