Shell completions and refactors
Output shell completions with `clap_complete`, moving the cli args types into a new file `cli_args.rs`, and add them to the nix package defined in the flake output. Update clap to 4.5.21. Various minor refactors in main.rs, including a removal of `itertools` as a dependency.
This commit is contained in:
parent
5be313863e
commit
f9df43f5e7
34
Cargo.lock
generated
34
Cargo.lock
generated
|
@ -53,9 +53,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
version = "4.5.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
||||
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -63,9 +63,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.20"
|
||||
version = "4.5.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
||||
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -73,6 +73,15 @@ dependencies = [
|
|||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.18"
|
||||
|
@ -97,12 +106,6 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
|
@ -115,15 +118,6 @@ version = "1.70.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.89"
|
||||
|
@ -153,7 +147,7 @@ name = "subtitle-merge"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"itertools",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -4,5 +4,8 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
itertools = "0.13.0"
|
||||
clap = { version = "4.5.21", features = ["derive"] }
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "4.5.21", features = ["derive"] }
|
||||
clap_complete = "4.5.38"
|
||||
|
|
22
build.rs
Normal file
22
build.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use std::{env, io};
|
||||
|
||||
use clap_complete::{generate_to, Shell};
|
||||
use cli_args::Args;
|
||||
use clap::{CommandFactory, ValueEnum};
|
||||
|
||||
mod cli_args {
|
||||
include!("src/cli_args.rs");
|
||||
}
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let Some(outdir) = env::var_os("OUT_DIR") else {
|
||||
return Ok(());
|
||||
};
|
||||
let mut command = Args::command();
|
||||
|
||||
for shell in Shell::value_variants() {
|
||||
generate_to(*shell, &mut command, "subtitle-merge", &outdir)?;
|
||||
// println!("cargo:warning=completion file is generated: {path:?}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
15
flake.nix
15
flake.nix
|
@ -18,15 +18,24 @@
|
|||
overlays.default = final: prev: {
|
||||
subtitle-merge = final.rustPlatform.buildRustPackage {
|
||||
name = "subtitle-merge";
|
||||
version = "1.0";
|
||||
version = "0.1";
|
||||
src = ./.;
|
||||
cargoLock.lockFile = ./Cargo.lock;
|
||||
buildInputs = [ final.mkvtoolnix-cli ];
|
||||
buildInputs = builtins.attrValues {
|
||||
inherit (final) installShellFiles mkvtoolnix-cli;
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --cmd subtitle-merge \
|
||||
--bash ./target/release-tmp/build/*/out/subtitle-merge.bash \
|
||||
--fish ./target/release-tmp/build/*/out/subtitle-merge.fish \
|
||||
--zsh ./target/release-tmp/build/*/out/_subtitle-merge
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
packages."${system}" = rec {
|
||||
subtitle-merge = (overlays.default pkgs pkgs).subtitle-merge;
|
||||
inherit (overlays.default pkgs pkgs) subtitle-merge;
|
||||
default = subtitle-merge;
|
||||
};
|
||||
};
|
||||
|
|
25
src/cli_args.rs
Normal file
25
src/cli_args.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser)]
|
||||
pub enum Args {
|
||||
Single(Single),
|
||||
Dir(Dir),
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Single {
|
||||
pub source: PathBuf,
|
||||
#[arg(long)]
|
||||
pub subtitles: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
pub fonts_dir: Option<PathBuf>,
|
||||
pub output: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Dir {
|
||||
pub input_dir: PathBuf,
|
||||
pub output_dir: PathBuf,
|
||||
}
|
66
src/main.rs
66
src/main.rs
|
@ -1,36 +1,16 @@
|
|||
mod cli_args;
|
||||
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
fs::ReadDir,
|
||||
io,
|
||||
os::unix::{ffi::OsStrExt, process::CommandExt},
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, ExitCode, ExitStatus},
|
||||
process::{Command, ExitCode},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use itertools::Either;
|
||||
|
||||
#[derive(Parser)]
|
||||
enum Args {
|
||||
Single(Single),
|
||||
Dir(Dir),
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Single {
|
||||
source: PathBuf,
|
||||
#[arg(long)]
|
||||
subtitles: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
fonts_dir: Option<PathBuf>,
|
||||
output: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Dir {
|
||||
input_dir: PathBuf,
|
||||
output_dir: PathBuf,
|
||||
}
|
||||
use cli_args::{Args, Single};
|
||||
|
||||
fn find_subs(root: &Path, match_str: &OsStr) -> io::Result<Option<PathBuf>> {
|
||||
for entry in root.read_dir()? {
|
||||
|
@ -59,7 +39,10 @@ fn find_subs(root: &Path, match_str: &OsStr) -> io::Result<Option<PathBuf>> {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
fn find_files(root: &Path, extension: &OsStr) -> impl Iterator<Item = io::Result<PathBuf>> {
|
||||
fn find_files(
|
||||
root: &Path,
|
||||
extension: &OsStr,
|
||||
) -> io::Result<impl Iterator<Item = io::Result<PathBuf>>> {
|
||||
struct FindFonts {
|
||||
read_dirs: Vec<ReadDir>,
|
||||
extension: OsString,
|
||||
|
@ -74,11 +57,10 @@ fn find_files(root: &Path, extension: &OsStr) -> impl Iterator<Item = io::Result
|
|||
continue;
|
||||
};
|
||||
let entry = match next {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Ok(entry) => entry,
|
||||
Err(e) => return Some(Err(e)),
|
||||
};
|
||||
let file_type = entry.file_type();
|
||||
let file_type = match file_type {
|
||||
let file_type = match entry.file_type() {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Ok(file_type) => file_type,
|
||||
};
|
||||
|
@ -101,14 +83,10 @@ fn find_files(root: &Path, extension: &OsStr) -> impl Iterator<Item = io::Result
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
match root.read_dir() {
|
||||
Ok(read_dir) => Either::Left(FindFonts {
|
||||
read_dirs: vec![read_dir],
|
||||
extension: extension.to_owned(),
|
||||
}),
|
||||
Err(e) => Either::Right(std::iter::once(Err(e))),
|
||||
}
|
||||
Ok(FindFonts {
|
||||
read_dirs: vec![root.read_dir()?],
|
||||
extension: extension.to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_single(
|
||||
|
@ -119,18 +97,18 @@ fn convert_single(
|
|||
output,
|
||||
}: Single,
|
||||
) -> io::Result<Command> {
|
||||
let subtitles = if let Some(subtitles) = subtitles {
|
||||
subtitles
|
||||
} else {
|
||||
find_subs(&source.parent().unwrap(), source.file_stem().unwrap())?.unwrap()
|
||||
};
|
||||
let subtitles = subtitles.map_or_else(|| {
|
||||
find_subs(source.parent().unwrap(), source.file_stem().unwrap())
|
||||
.transpose()
|
||||
.unwrap()
|
||||
}, Ok)?;
|
||||
let fonts: Vec<PathBuf> = if let Some(fonts_dir) = fonts_dir {
|
||||
fonts_dir
|
||||
.read_dir()?
|
||||
.map(|r| r.map(|entry| entry.path()))
|
||||
.collect::<io::Result<_>>()?
|
||||
} else {
|
||||
find_files(source.parent().unwrap(), OsStr::new("ttf")).collect::<io::Result<_>>()?
|
||||
find_files(source.parent().unwrap(), OsStr::new("ttf"))?.collect::<io::Result<_>>()?
|
||||
};
|
||||
|
||||
let mut command = Command::new("mkvmerge");
|
||||
|
@ -141,7 +119,7 @@ fn convert_single(
|
|||
]);
|
||||
for font in fonts {
|
||||
command
|
||||
.args(&["--attachment-mime-type", "font/ttf", "--attach-file"])
|
||||
.args(["--attachment-mime-type", "font/ttf", "--attach-file"])
|
||||
.arg(font.into_os_string());
|
||||
}
|
||||
Ok(command)
|
||||
|
@ -155,7 +133,7 @@ fn main() -> io::Result<ExitCode> {
|
|||
Err(command.exec())
|
||||
}
|
||||
Args::Dir(dir) => {
|
||||
let files = find_files(&dir.input_dir, OsStr::new("mkv"));
|
||||
let files = find_files(&dir.input_dir, OsStr::new("mkv"))?;
|
||||
let mut commands = Vec::new();
|
||||
for file in files {
|
||||
let input_file = file?;
|
||||
|
|
Loading…
Reference in a new issue