Skip to content

Replace docopt with clap #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ keywords = ["audio", "codec", "flac"]

[dependencies]

docopt = "^0.6.78"
hound = "^1.1.0"
nom = "^1.0.0"
rustc-serialize = "^0.3.16"

[dev-dependencies]

clap = { version = "^4.5.39", features = ["derive"] }
rust-crypto = "^0.2.34"
38 changes: 17 additions & 21 deletions examples/commands/comments.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
use std::io::{self, Write};
use std::fs::File;

use clap::Args;

use flac::StreamReader;
use flac::metadata::{self, VorbisComment};

pub const USAGE: &'static str = "
Usage: metadata comments [options] <filename>
metadata comments --help

Options:
--vendor Show the vendor string.
--name=NAME Show the comments matching the `NAME`.
--export=FILE Export to file.
-h, --help Show this message.
";

#[derive(Debug, RustcDecodable)]
#[derive(Args)]
pub struct Arguments {
arg_filename: String,
flag_vendor: bool,
flag_name: Option<String>,
flag_export: Option<String>,
#[arg(short, long)]
filename: String,
#[arg(short, long)]
vendor: bool,
#[arg(short, long, value_name = "NAME")]
name: Option<String>,
#[arg(short, long, value_name = "FILE")]
export: Option<String>,
}


fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
let no_flags = (args.flag_vendor || args.flag_name.is_some()) == false;
let no_flags = (args.vendor || args.name.is_some()) == false;

if no_flags || args.flag_vendor {
if no_flags || args.vendor {
format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
no_flags);
}
Expand All @@ -42,7 +38,7 @@ fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
index += 1;
}
} else {
if let Some(ref name) = args.flag_name {
if let Some(ref name) = args.name {
let error_str = format!("Couldn't find tag name: \"{}\"", name);
let result = vorbis_comment.comments.get(name).unwrap_or(&error_str);

Expand All @@ -63,13 +59,13 @@ fn export_vorbis_comments(vorbis_comment: &VorbisComment, filename: &str)
}

pub fn run(args: &Arguments) {
let stream = StreamReader::<File>::from_file(&args.arg_filename)
let stream = StreamReader::<File>::from_file(&args.filename)
.expect("Couldn't parse file");

for meta in stream.metadata() {
match meta.data {
metadata::Data::VorbisComment(ref v) => {
if let Some(ref filename) = args.flag_export {
if let Some(ref filename) = args.export {
export_vorbis_comments(v, filename)
.expect("couldn't write to file")
} else {
Expand Down
29 changes: 12 additions & 17 deletions examples/commands/picture.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
use std::io::{self, Write};
use std::fs::File;

use clap::Args;

use flac::stream::StreamReader;
use flac::metadata::{self, Picture};

pub const USAGE: &'static str = "
Usage: metadata picture [options] <filename>
metadata picture --help

Options:
--export=FILE Export to file.
--index=NUMBER Index of the current metadata type.
-h, --help Show this message.
";

#[derive(Debug, RustcDecodable)]
#[derive(Args)]
pub struct Arguments {
arg_filename: String,
flag_export: Option<String>,
flag_index: Option<usize>,
#[arg(short, long, required = true, value_name = "FILE")]
filename: String,
#[arg(short, long, value_name = "FILE")]
export: Option<String>,
#[arg(short, long)]
index: Option<usize>,
}

fn export_picture(picture: &Picture, filename: &str) -> io::Result<()> {
Expand All @@ -36,11 +31,11 @@ fn print_picture(picture: &Picture) {
}

pub fn run(args: &Arguments) {
let stream = StreamReader::<File>::from_file(&args.arg_filename)
let stream = StreamReader::<File>::from_file(&args.filename)
.expect("Couldn't parse file");

let mut index = 0;
let end_index = args.flag_index.unwrap_or(0);
let end_index = args.index.unwrap_or(0);

for meta in stream.metadata() {
match meta.data {
Expand All @@ -51,7 +46,7 @@ pub fn run(args: &Arguments) {
continue;
}

if let Some(ref filename) = args.flag_export {
if let Some(ref filename) = args.export {
export_picture(p, filename).expect("couldn't write to file");

break;
Expand Down
17 changes: 6 additions & 11 deletions examples/commands/seektable.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
use std::fs::File;

use clap::Args;

use flac::StreamReader;
use flac::metadata::{self, SeekPoint};

pub const USAGE: &'static str = "
Usage: metadata seektable <filename>
metadata seektable --help

Options:
-h, --help Show this message.
";

#[derive(Debug, RustcDecodable)]
#[derive(Args)]
pub struct Arguments {
arg_filename: String,
#[arg(short, long, value_name = "FILE")]
filename: String,
}

fn print_seek_table(seek_points: &[SeekPoint]) {
Expand All @@ -31,7 +26,7 @@ fn print_seek_table(seek_points: &[SeekPoint]) {
}

pub fn run(args: &Arguments) {
let stream = StreamReader::<File>::from_file(&args.arg_filename)
let stream = StreamReader::<File>::from_file(&args.filename)
.expect("Couldn't parse file");

for meta in stream.metadata() {
Expand Down
66 changes: 30 additions & 36 deletions examples/commands/streaminfo.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,37 @@
use std::fs::File;

use clap::Args;
use flac::{Stream, StreamProducer, StreamReader};

pub const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
metadata streaminfo --help

Options:
--block-size Show both the max and min block size from StreamInfo.
--frame-size Show both the max and min frame size from StreamInfo.
--sample-rate Show the sample rate from StreamInfo.
--channels Show the number of channels from StreamInfo.
--bits-per-sample Show the size in bits for each sample from StreamInfo.
--total-samples Show total number of samples from StreamInfo.
--md5 Show the MD5 signature from StreamInfo.
-h, --help Show this message.
";

#[derive(Debug, RustcDecodable)]
#[derive(Args)]
pub struct Arguments {
arg_filename: String,
flag_block_size: bool,
flag_frame_size: bool,
flag_sample_rate: bool,
flag_channels: bool,
flag_bits_per_sample: bool,
flag_total_samples: bool,
flag_md5: bool,
#[arg(short, long, required = true)]
filename: String,
#[arg(long)]
block_size: bool,
#[arg(long)]
frame_size: bool,
#[arg(long)]
sample_rate: bool,
#[arg(long)]
channels: bool,
#[arg(long)]
bits_per_sample: bool,
#[arg(long)]
total_samples: bool,
#[arg(long)]
md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
where P: StreamProducer {
let info = stream.info();
let no_flags = (args.flag_block_size || args.flag_frame_size ||
args.flag_sample_rate || args.flag_channels ||
args.flag_bits_per_sample || args.flag_total_samples ||
args.flag_md5) == false;
let no_flags = (args.block_size || args.frame_size ||
args.sample_rate || args.channels ||
args.bits_per_sample || args.total_samples ||
args.md5) == false;

if no_flags || args.flag_block_size {
if no_flags || args.block_size {
let block_size_str = if info.is_fixed_block_size() {
format!("{} samples", info.max_block_size)
} else {
Expand All @@ -47,29 +41,29 @@ fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
format_print!("{}{}", "Block size: ", block_size_str, no_flags);
}

if no_flags || args.flag_frame_size {
if no_flags || args.frame_size {
println!("Frame size: {} - {} bytes", info.min_frame_size,
info.max_frame_size);
}

if no_flags || args.flag_sample_rate {
if no_flags || args.sample_rate {
format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
}

if no_flags || args.flag_channels {
if no_flags || args.channels {
format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
}

if no_flags || args.flag_bits_per_sample {
if no_flags || args.bits_per_sample {
format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
no_flags);
}

if no_flags || args.flag_total_samples {
if no_flags || args.total_samples {
format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
}

if no_flags || args.flag_md5 {
if no_flags || args.md5 {
let mut md5 = String::with_capacity(32);

for byte in &info.md5_sum {
Expand All @@ -83,7 +77,7 @@ fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
}

pub fn run(args: &Arguments) {
let stream = StreamReader::<File>::from_file(&args.arg_filename)
let stream = StreamReader::<File>::from_file(&args.filename)
.expect("Couldn't parse file");

print_stream_info(&stream, &args);
Expand Down
12 changes: 0 additions & 12 deletions examples/commands/utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@ macro_rules! format_print (
);
);

macro_rules! command (
($name: ident) => (
{
let args: $name::Arguments = Docopt::new($name::USAGE)
.and_then(|d| d.argv(env::args()).decode())
.unwrap_or_else(|e| e.exit());

$name::run(&args)
}
);
);

pub fn list_block_names(filename: &str) {
let stream = StreamReader::<File>::from_file(filename)
.expect("Couldn't parse file");
Expand Down
41 changes: 16 additions & 25 deletions examples/decode.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
extern crate docopt;
extern crate clap;
extern crate flac;
extern crate hound;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ErrorKind, StreamReader};

use std::env;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

const USAGE: &'static str = "
Usage: decode <input> <output>
decode <input>... <dir>
decode --help

Options:
-h, --help Show this message.
";

#[derive(RustcDecodable)]
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Arguments {
arg_input: Vec<String>,
arg_output: Option<String>,
arg_dir: Option<String>,
#[arg(short, long, required = true, num_args = 1.., value_delimiter = ' ', value_name = "FILE")]
input: Vec<String>,
#[arg(short, long, required = true, value_name = "FILE/DIR")]
output: String,
}

fn to_io_error(kind: ErrorKind) -> hound::Error {
Expand Down Expand Up @@ -124,21 +117,19 @@ fn decode_all_files(input_files: &Vec<String>, directory: &str)
}

fn main() {
let args: Arguments = Docopt::new(USAGE)
.and_then(|d| d.argv(env::args()).decode())
.unwrap_or_else(|e| e.exit());
let args = Arguments::parse();

if let Some(ref output_file) = args.arg_output {
let input_file = args.arg_input.get(0)
.expect("No input file");
if args.input.len() == 1 {
let input_file = args.input.get(0)
.expect("No input file");

if let Err(e) = decode_file(input_file, output_file) {
if let Err(e) = decode_file(input_file, &args.output) {
println!("{:?}", e);
} else {
println!("decoded: {} -> {}", input_file, output_file);
println!("decoded: {} -> {}", input_file, args.output);
}
} else if let Some(ref directory) = args.arg_dir {
if let Err(e) = decode_all_files(&args.arg_input, directory) {
} else {
if let Err(e) = decode_all_files(&args.input, &args.output) {
println!("{:?}", e);
}
}
Expand Down
Loading