scribe_core/
lib.rs

1#![cfg_attr(not(tarpaulin), deny(warnings))]
2#![cfg_attr(tarpaulin, allow(warnings))]
3
4//! # Scribe Core
5//! 
6//! Core types, utilities, and foundational components for the Scribe code analysis library.
7//! This crate provides the fundamental data structures and traits used across all other
8//! Scribe crates.
9//!
10//! ## Features
11//! 
12//! - **Comprehensive Error Handling**: Rich error types with proper context and error chaining
13//! - **File Analysis**: File metadata, language detection, and classification
14//! - **Scoring System**: Heuristic scoring components and configurable weights
15//! - **Configuration**: Flexible configuration with validation and serialization
16//! - **Extensibility**: Traits for custom analyzers, scorers, and formatters
17//! - **Utilities**: Common functions for path manipulation, string processing, and more
18//!
19//! ## Basic Usage
20//!
21//! ```rust
22//! use scribe_core::{Config, FileInfo, ScoreComponents, Result};
23//! use std::path::Path;
24//!
25//! # fn main() -> Result<()> {
26//! // Load configuration
27//! let config = Config::default();
28//!
29//! // Analyze a file (this would typically be done by other crates)
30//! // let file_info = analyze_file(Path::new("src/lib.rs"), &config)?;
31//! # Ok(())
32//! # }
33//! ```
34
35// Core modules
36pub mod error;
37pub mod file;
38pub mod types;
39pub mod config;
40pub mod traits;
41pub mod utils;
42
43// Scaling optimizations (optional)
44#[cfg(feature = "scaling")]
45pub mod scaling;
46
47// Re-export commonly used types for convenience
48pub use error::{ScribeError, Result};
49
50pub use file::{
51    FileInfo, FileType, Language, RenderDecision, RenderDecisionCategory,
52    DocumentationFormat, ConfigurationFormat, GitStatus, GitFileStatus,
53    bytes_to_human, BINARY_EXTENSIONS, MARKDOWN_EXTENSIONS,
54};
55
56pub use types::{
57    // Core positioning and ranges
58    Position, Range,
59    
60    // Scoring system
61    ScoreComponents, HeuristicWeights,
62    
63    // Repository information
64    RepositoryInfo, SizeStatistics, LanguageStats, FileTypeStats,
65    GitStatistics, ChurnInfo,
66    
67    // Graph analysis
68    CentralityScores, GraphStats,
69    
70    // Analysis results
71    AnalysisResult, AnalysisMetadata,
72};
73
74pub use config::{
75    Config, GeneralConfig, FilteringConfig, AnalysisConfig, ScoringConfig,
76    PerformanceConfig, GitConfig, FeatureFlags, OutputConfig,
77    CustomScoringRule, ScoreModifier, OutputFormat,
78};
79
80pub use traits::{
81    // Core analysis traits
82    FileAnalyzer, HeuristicScorer, RepositoryAnalyzer, GitIntegration,
83    CentralityComputer, LanguageExtension,
84    
85    // Infrastructure traits
86    PatternMatcher, OutputFormatter, CacheStorage, ProgressReporter,
87    PluginRegistry,
88    
89    // Data structures
90    DependencyGraph, DependencyNodeMetadata, GitRepositoryInfo,
91    DocumentationBlock, DocumentationType, CacheStats,
92};
93
94// Utility re-exports for common functionality
95pub use utils::{
96    path::{normalize_path, relative_path, is_under_directory, path_depth, is_hidden, find_repo_root},
97    string::{truncate, dedent, count_lines, is_likely_binary, extract_identifier},
98    time::{duration_to_human, current_timestamp},
99    math::{mean, median, std_deviation, normalize, clamp},
100    validation::{validate_readable_path, validate_directory, validate_file},
101    hash::{generate_hash, hash_file_content},
102};
103
104/// Current version of the Scribe library
105pub const VERSION: &str = env!("CARGO_PKG_VERSION");
106
107/// Library metadata and build information
108pub mod meta {
109    /// Library name
110    pub const NAME: &str = env!("CARGO_PKG_NAME");
111    
112    /// Library version
113    pub const VERSION: &str = env!("CARGO_PKG_VERSION");
114    
115    /// Library description
116    pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
117    
118    /// Authors
119    pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
120    
121    /// Repository URL
122    pub const REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
123    
124    /// License
125    pub const LICENSE: &str = env!("CARGO_PKG_LICENSE");
126    
127    /// Target triple (if available)
128    pub const TARGET: Option<&str> = option_env!("TARGET");
129    
130    /// Build timestamp (if available)
131    pub const BUILD_TIMESTAMP: Option<&str> = option_env!("BUILD_TIMESTAMP");
132    
133    /// Git commit hash (if available)
134    pub const GIT_HASH: Option<&str> = option_env!("GIT_HASH");
135    
136    /// Get library information as a formatted string
137    pub fn info() -> String {
138        format!(
139            "{} v{} - {}",
140            NAME,
141            VERSION, 
142            DESCRIPTION
143        )
144    }
145    
146    /// Get detailed build information
147    pub fn build_info() -> String {
148        let mut info = format!("{} v{}", NAME, VERSION);
149        
150        if let Some(target) = TARGET {
151            info.push_str(&format!(" ({})", target));
152        }
153        
154        if let Some(git_hash) = GIT_HASH {
155            info.push_str(&format!(" [{}]", &git_hash[..8]));
156        }
157        
158        if let Some(timestamp) = BUILD_TIMESTAMP {
159            info.push_str(&format!(" built on {}", timestamp));
160        }
161        
162        info
163    }
164}
165
166/// Prelude module for convenient imports
167pub mod prelude {
168    //! Commonly used imports for Scribe applications
169    
170    pub use crate::{
171        // Core types
172        Result, ScribeError,
173        FileInfo, FileType, Language, RenderDecision,
174        ScoreComponents, HeuristicWeights,
175        Config, FeatureFlags,
176        
177        // Essential traits
178        FileAnalyzer, HeuristicScorer, RepositoryAnalyzer,
179        OutputFormatter, ProgressReporter,
180        
181        // Common utilities
182        normalize_path, duration_to_human, generate_hash,
183    };
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189
190    #[test]
191    fn test_version() {
192        assert!(!VERSION.is_empty());
193        assert!(VERSION.parse::<semver::Version>().is_ok());
194    }
195
196    #[test]
197    fn test_meta_info() {
198        let info = meta::info();
199        assert!(info.contains("scribe-core"));
200        assert!(info.contains(VERSION));
201    }
202
203    #[test]
204    fn test_build_info() {
205        let build_info = meta::build_info();
206        assert!(build_info.contains("scribe-core"));
207        assert!(build_info.contains(VERSION));
208    }
209
210    #[test]
211    fn test_prelude_imports() {
212        // Test that prelude imports work
213        use crate::prelude::*;
214        
215        let config = Config::default();
216        assert!(config.general.verbosity <= 4);
217        
218        let decision = RenderDecision::include("test");
219        assert!(decision.should_include());
220        
221        let hash = generate_hash(&"test");
222        assert!(!hash.is_empty());
223    }
224
225    #[test]
226    fn test_core_functionality() {
227        // Test error creation
228        let err = ScribeError::config("test error");
229        assert!(err.to_string().contains("test error"));
230        
231        // Test language detection
232        let lang = Language::from_extension("rs");
233        assert_eq!(lang, Language::Rust);
234        
235        // Test path utilities
236        let depth = path_depth("src/lib/mod.rs");
237        assert_eq!(depth, 3);
238        
239        // Test string utilities
240        let truncated = truncate("hello world", 5);
241        assert_eq!(truncated, "he...");
242    }
243
244    #[test]
245    fn test_score_components() {
246        let mut scores = ScoreComponents::zero();
247        scores.doc_score = 0.8;
248        scores.import_score = 0.6;
249        
250        let weights = HeuristicWeights::default();
251        scores.compute_final_score(&weights);
252        
253        assert!(scores.final_score > 0.0);
254        assert!(scores.final_score <= 1.0);
255    }
256
257    #[test]
258    fn test_configuration() {
259        let config = Config::default();
260        assert!(config.validate().is_ok());
261        
262        let hash1 = config.compute_hash();
263        let hash2 = config.compute_hash();
264        assert_eq!(hash1, hash2);
265    }
266}