subx-cli 2.0.0

AI subtitle processing CLI tool, which automatically matches, renames, and converts subtitle files.
Documentation
# Workspace root. `subx-core` is a git submodule mounted at subx-core/
# (https://github.com/jim60105/subx-core); run
# `git submodule update --init --recursive` after cloning subx-cli.
[workspace]
members = [".", "subx-core"]
# Cover both crates for bare cargo commands typed in this directory
# (`cargo nextest run`, `cargo clippy`): without this key the default
# member set is the root package alone and a bare command silently skips
# the subx-core crate and its test suite. CI scripts additionally pass
# `--workspace` explicitly, so the manifest key protects the human and the
# flag protects the gate.
default-members = [".", "subx-core"]
resolver = "3"

[package]
name = "subx-cli"
version = "2.0.0"
edition = "2024"
authors = ["Jim Chen <Jim@ChenJ.im>"]
description = "AI subtitle processing CLI tool, which automatically matches, renames, and converts subtitle files."
license = "GPL-3.0-or-later"
repository = "https://github.com/jim60105/subx-cli"
homepage = "https://github.com/jim60105/subx-cli"
keywords = ["subtitle", "cli", "ai", "video"]
categories = ["command-line-utilities", "multimedia"]

exclude = [
    "assets/",
    ".github/",
    "tests/",
    "target/",
    "*.mp4",
    "*.mp3",
    "*.mov",
    "*.avi",
    "*.mkv",
    "plans/",
    "scripts/test_*.sh",
    "benches/",
    "**/*.log",
    "**/*.tmp",
    "**/.DS_Store",
    "Cargo.lock",
]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

# Test-only feature flags. Both are pass-throughs: the gated sources live in
# the subx-core crate, and each declaration both enables the core feature and
# remains a real `subx-cli` feature (tests/ still write
# #[cfg(feature = "slow-tests")] against this crate's feature set).
[features]
default = []
slow-tests = ["subx-core/slow-tests"]
archive-rar = ["subx-core/archive-rar"]

# Documentation quality linting
[lints.rustdoc]
broken_intra_doc_links = "deny"
private_doc_tests = "warn"
invalid_rust_codeblocks = "warn"
bare_urls = "warn"

[lints.clippy]
missing_docs_in_private_items = "allow" # Allow missing private docs
doc_markdown = "allow"                  # Allow markdown formatting warnings

[lints.rust]
missing_docs = "allow" # Allow missing docs at rust level

[dependencies]
# SubX core library (git submodule at subx-core/)
subx-core = { path = "subx-core", version = "1.0" }

# CLI framework
clap = { version = "4.5.40", features = ["derive", "cargo"] }
clap_complete = "4.5.54"

# Async runtime
# `time`: src/commands/match_command.rs uses tokio::time in production code;
# it must not rely on subx-core enabling the feature through unification.
# fs/sync are needed only by test targets and are declared under
# [dev-dependencies] below.
tokio = { version = "1.0", features = [
    "rt-multi-thread",
    "macros",
    "time",
] }

# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "1"

# Logging
log = "0.4"
env_logger = "0.11"

# User interface
colored = "3.0"
tabled = "0.20"
indicatif = "0.18"

# Config-directory resolution (src/commands/cache_command.rs). subx-core
# depends on `dirs` too; declaring the same registry crate twice is normal.
dirs = "6.0"

[dev-dependencies]
# Enable subx-core's `test-support` feature for this crate's test targets
# only. Under resolver 3 a dev-dependency's features never unify into a
# build that has no dev target, so `cargo build --release` cannot see the
# gated module or its optional dependencies. `test-support` is deliberately
# NOT a subx-cli feature, so no `--features` flag can turn it on either.
subx-core = { path = "subx-core", version = "1.0", features = ["test-support"] }

# Registry crates that tests/, benches/ and the #[cfg(test)] modules inside
# src/ name directly. Before the crate split they compiled through
# [dependencies]; the split moved them to subx-core, so they must be declared
# for the test targets here rather than inherited through the workspace
# dependency graph. B3 prunes whatever its test move leaves over.
anyhow = "1.0"
async-trait = "0.1"
encoding_rs = "0.8"
flate2 = "1"
reqwest = { version = "0.13", features = ["json", "stream", "rustls"] }
sevenz-rust2 = "0.22.2"
tar = "0.4"
tempfile = "3.10"
tokio = { version = "1.0", features = ["fs", "sync"] }
uuid = { version = "1.3", features = ["v7"] }
zip = "8"

# testing frameworks and utilities
assert_cmd = "2.0"
predicates = "3.0"

regex = "1.10"    # For test output validation

# coverage and HTTP mocking
wiremock = "0.6"

[[bin]]
name = "subx-cli"
path = "src/main.rs"

[profile.release]
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"
strip = true

[profile.dev]
opt-level = 0
debug = true
split-debuginfo = "unpacked"