Decouple option codes, fix encode bugs, add test suite

Maintainability:
- Choice options now carry a stable `code` separate from the display
  `label`. The command builder and recipe storage key off codes, so
  relabeling a menu entry no longer silently changes the encode or
  breaks a saved recipe. Format/Audio dispatch is now a clean code
  match instead of `starts_with` on display strings. Old recipes that
  stored labels still load via a label fallback.

Correctness:
- Fade start times now scale by the speed factor already applied in the
  filter chain, so Speed + Fade produces a fade in the right place
  regardless of op order (video and audio).
- Two-pass pass 1 uses the platform null device (NUL on Windows).
- The stderr drain thread is joined before Finished is sent, so the
  failure tail reported to the user is never truncated.

Features / cleanup:
- Accept multiple file arguments on the CLI to open batch mode directly.
- try_recv() instead of recv_timeout(ZERO); drop unused import.

Testing:
- 23 unit tests covering build() arg generation, speed/fade ordering,
  recipe round-trip + old-label fallback, and the pure helpers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 15:47:16 +01:00
parent 16acb43daf
commit 4daca8247c
7 changed files with 680 additions and 232 deletions
+5 -4
View File
@@ -14,8 +14,8 @@ use ratatui::DefaultTerminal;
use app::App;
fn main() -> Result<()> {
let mut initial: Option<std::path::PathBuf> = None;
if let Some(arg) = std::env::args().nth(1) {
let mut initial: Vec<std::path::PathBuf> = Vec::new();
for arg in std::env::args().skip(1) {
match arg.as_str() {
"--version" | "-V" => {
println!("lazyff {}", env!("CARGO_PKG_VERSION"));
@@ -23,9 +23,10 @@ fn main() -> Result<()> {
}
"--help" | "-h" => {
println!("lazyff {} — a friendly TUI for FFmpeg", env!("CARGO_PKG_VERSION"));
println!("Usage: lazyff [FILE]");
println!("Usage: lazyff [FILE...]");
println!(" no argument open a file browser in the current directory");
println!(" FILE open this video/audio file straight in the editor");
println!(" FILE FILE... open several files together in batch mode");
return Ok(());
}
_ => {
@@ -33,7 +34,7 @@ fn main() -> Result<()> {
if !path.is_file() {
bail!("{arg}: no such file");
}
initial = Some(path);
initial.push(path);
}
}
}