scribe_core/
lib.rs

1//! Core crate for Scribe
2
3//! # Scribe Core
4//! 
5//! Core types, utilities, and foundational components for the Scribe code analysis library.
6//! This crate provides the fundamental data structures and traits used across all other
7//! Scribe crates.
8//!
9//! ## Features
10//! 
11//! - **Comprehensive Error Handling**: Rich error types with proper context and error chaining
12//! - **File Analysis**: File metadata, language detection, and classification
13//! - **Scoring System**: Heuristic scoring components and configurable weights
14//! - **Configuration**: Flexible configuration with validation and serialization
15//! - **Extensibility**: Traits for custom analyzers, scorers, and formatters
16//! - **Utilities**: Common functions for path manipulation, string processing, and more
17//!
18//! ## Basic Usage
19//!
20//! ```rust
21//! use scribe_core::{Config, FileInfo, ScoreComponents, Result};
22//! use std::path::Path;
23//!
24//! # fn main() -> Result<()> {
25//! // Load configuration
26//! let config = Config::default();
27//!
28//! // Analyze a file (this would typically be done by other crates)
29//! // let file_info = analyze_file(Path::new("src/lib.rs"), &config)?;
30//! # Ok(())
31//! # }
32//! ```
33
34// Core modules
35pub mod error;
36pub mod file;
37pub mod types;
38pub mod config;
39pub mod traits;
40pub mod utils;
41pub mod tokenization;
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
104pub use tokenization::{
105    TokenCounter, TokenizerConfig, TokenBudget, 
106    ContentType, TokenizationComparison,
107};
108
109/// Current version of the Scribe library
110pub const VERSION: &str = env!("CARGO_PKG_VERSION");
111
112/// Library metadata and build information
113pub mod meta {
114    /// Library name
115    pub const NAME: &str = env!("CARGO_PKG_NAME");
116    
117    /// Library version
118    pub const VERSION: &str = env!("CARGO_PKG_VERSION");
119    
120    /// Library description
121    pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
122    
123    /// Authors
124    pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
125    
126    /// Repository URL
127    pub const REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
128    
129    /// License
130    pub const LICENSE: &str = env!("CARGO_PKG_LICENSE");
131    
132    /// Target triple (if available)
133    pub const TARGET: Option<&str> = option_env!("TARGET");
134    
135    /// Build timestamp (if available)
136    pub const BUILD_TIMESTAMP: Option<&str> = option_env!("BUILD_TIMESTAMP");
137    
138    /// Git commit hash (if available)
139    pub const GIT_HASH: Option<&str> = option_env!("GIT_HASH");
140    
141    /// Get library information as a formatted string
142    pub fn info() -> String {
143        format!(
144            "{} v{} - {}",
145            NAME,
146            VERSION, 
147            DESCRIPTION
148        )
149    }
150    
151    /// Get detailed build information
152    pub fn build_info() -> String {
153        let mut info = format!("{} v{}", NAME, VERSION);
154        
155        if let Some(target) = TARGET {
156            info.push_str(&format!(" ({})", target));
157        }
158        
159        if let Some(git_hash) = GIT_HASH {
160            info.push_str(&format!(" [{}]", &git_hash[..8]));
161        }
162        
163        if let Some(timestamp) = BUILD_TIMESTAMP {
164            info.push_str(&format!(" built on {}", timestamp));
165        }
166        
167        info
168    }
169}
170
171/// Prelude module for convenient imports
172pub mod prelude {
173    //! Commonly used imports for Scribe applications
174    
175    pub use crate::{
176        // Core types
177        Result, ScribeError,
178        FileInfo, FileType, Language, RenderDecision,
179        ScoreComponents, HeuristicWeights,
180        Config, FeatureFlags,
181        
182        // Essential traits
183        FileAnalyzer, HeuristicScorer, RepositoryAnalyzer,
184        OutputFormatter, ProgressReporter,
185        
186        // Common utilities
187        normalize_path, duration_to_human, generate_hash,
188    };
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn test_version() {
197        assert!(!VERSION.is_empty());
198        assert!(VERSION.parse::<semver::Version>().is_ok());
199    }
200
201    #[test]
202    fn test_meta_info() {
203        let info = meta::info();
204        assert!(info.contains("scribe-core"));
205        assert!(info.contains(VERSION));
206    }
207
208    #[test]
209    fn test_build_info() {
210        let build_info = meta::build_info();
211        assert!(build_info.contains("scribe-core"));
212        assert!(build_info.contains(VERSION));
213    }
214
215    #[test]
216    fn test_prelude_imports() {
217        // Test that prelude imports work
218        use crate::prelude::*;
219        
220        let config = Config::default();
221        assert!(config.general.verbosity <= 4);
222        
223        let decision = RenderDecision::include("test");
224        assert!(decision.should_include());
225        
226        let hash = generate_hash(&"test");
227        assert!(!hash.is_empty());
228    }
229
230    #[test]
231    fn test_core_functionality() {
232        // Test error creation
233        let err = ScribeError::config("test error");
234        assert!(err.to_string().contains("test error"));
235        
236        // Test language detection
237        let lang = Language::from_extension("rs");
238        assert_eq!(lang, Language::Rust);
239        
240        // Test path utilities
241        let depth = path_depth("src/lib/mod.rs");
242        assert_eq!(depth, 3);
243        
244        // Test string utilities
245        let truncated = truncate("hello world", 5);
246        assert_eq!(truncated, "he...");
247    }
248
249    #[test]
250    fn test_score_components() {
251        let mut scores = ScoreComponents::zero();
252        scores.doc_score = 0.8;
253        scores.import_score = 0.6;
254        
255        let weights = HeuristicWeights::default();
256        scores.compute_final_score(&weights);
257        
258        assert!(scores.final_score > 0.0);
259        assert!(scores.final_score <= 1.0);
260    }
261
262    #[test]
263    fn test_configuration() {
264        let config = Config::default();
265        assert!(config.validate().is_ok());
266        
267        let hash1 = config.compute_hash();
268        let hash2 = config.compute_hash();
269        assert_eq!(hash1, hash2);
270    }
271}