Proper metadata handling in format strings #34
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/path-sanitization"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds apply_portable_rules(relative: &Path, portable: bool) -> PathBuf, called from album_dir_path and track_dest_path immediately after substitute_tokens assembles the full relative path and before check_name_max measures it. Runs once per relative path over Component::Normal parts, unlike sanitize() which only ever sees one field's isolated value — needed because the default track_format combines {track_number:02} and {title} into a single component, so a title of "CON" must not trigger device-name suffixing on its own. A no-op when portable is false.format!("{title:<width$}") pads by Unicode scalar count, so a truncated CJK-heavy title (fewer characters but at its column budget) got padded with extra spaces on top, overflowing its cell and shifting every column printed after it. A wide enough overflow pushes the row past the terminal width, causing the wrapped line to desync lines_drawn bookkeeping and produce a waterfall of redrawn header lines on every tick. Add pad_to_width (column-width-aware padding) to src/ui/text.rs and fold it into display_title_artist, so both renderers print pre-padded, column-exact cells instead of re-padding through Rust's format width.UnsafePathComponent check, run on the raw substituted string before it becomes a Path Fixes an over-rejection bug where an unreferenced field (e.g. artist under the default album_format/track_format, which never mentions {artist}) could block enqueueing a track, and closes a more severe gap where a field sanitizing to an empty string next to a template-literal '/' produced a leading/interior/trailing empty path segment invisible to Path::components()-based guards — a leading empty segment in particular lets root.join(...) discard the collection root entirely, escaping to the real filesystem root with no '..' required. reject_unsafe_path_segments now runs once per template, against the fully assembled substituted string via str::split('/'), rather than per-field before splicing. UserError::UnsafeMetadata is removed in favor of UnsafePathComponent.