luff/printer/mod.rs
1//! File printing implementations
2
3mod colors;
4#[cfg(feature = "cli")]
5mod markdown;
6mod tree;
7
8use crate::{config::IgnorePatterns, format::OutputFormat};
9#[cfg(feature = "cli")]
10use crate::{error::Result, walker::WalkerEntry};
11use std::path::PathBuf;
12
13// Re-exports
14pub use colors::Colors;
15#[cfg(feature = "cli")]
16pub use markdown::MarkdownPrinter;
17pub use tree::{TreePrinter, format_tree};
18
19/// Type-safe wrapper for pattern filtering behavior
20///
21/// This newtype eliminates boolean blindness and makes the intent explicit
22/// at call sites. Instead of passing `true` or `false`, callers use
23/// `SkipPatterns::ENABLED` or `SkipPatterns::DISABLED`.
24///
25/// # Examples
26///
27/// ```
28/// use luff::printer::SkipPatterns;
29///
30/// // Clear intent at call site
31/// let patterns = SkipPatterns::ENABLED;
32/// assert!(patterns.should_skip());
33///
34/// let patterns = SkipPatterns::DISABLED;
35/// assert!(!patterns.should_skip());
36/// ```
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub struct SkipPatterns(bool);
39
40impl SkipPatterns {
41 /// Enable pattern-based filtering
42 ///
43 /// Files matching ignore patterns (binary extensions, etc.) will be
44 /// filtered out before processing.
45 pub const ENABLED: Self = Self(true);
46
47 /// Disable pattern-based filtering
48 ///
49 /// All files will be processed regardless of extension or pattern
50 /// matches. This is typically used when files are explicitly specified
51 /// via the `-f` flag.
52 pub const DISABLED: Self = Self(false);
53
54 /// Check if pattern filtering should be applied
55 ///
56 /// Returns `true` if files should be filtered based on ignore patterns,
57 /// `false` if all files should be processed.
58 #[must_use]
59 pub const fn should_skip(self) -> bool {
60 self.0
61 }
62}
63
64/// Options for configuring printer output
65#[derive(Debug, Clone)]
66pub struct PrinterOptions {
67 /// The output format to use
68 pub format: OutputFormat,
69 /// Root directory for calculating relative paths
70 pub root: PathBuf,
71 /// Whether to apply pattern-based filtering
72 pub skip_patterns: SkipPatterns,
73 /// Ignore patterns to use for filtering
74 pub patterns: IgnorePatterns,
75}
76
77/// Print a file entry using the appropriate printer
78///
79/// # Errors
80///
81/// Returns an error if:
82/// - File cannot be read
83/// - File is not valid UTF-8 (for text formats)
84/// - Output cannot be written to stdout
85#[cfg(feature = "cli")]
86pub fn print_file(entry: &WalkerEntry, options: &PrinterOptions) -> Result<()> {
87 match options.format {
88 OutputFormat::Markdown => MarkdownPrinter::print(
89 entry,
90 &options.root,
91 &options.patterns,
92 options.skip_patterns,
93 ),
94 OutputFormat::Tree => TreePrinter::print(entry, &options.root),
95 }
96}