### Example Workflow: Analyzing Multiple Files Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md A complete workflow example showing how to load a license store and analyze multiple files to identify their licenses based on a confidence score threshold. ```rust use askalono::{Store, TextData}; use std::fs::File; fn main() -> Result<(), Box> { // Load store once let store = Store::from_cache(File::open("askalono-cache.bin.zstd")?)?; // Identify multiple files let files = vec![ "LICENSE", "COPYING", "LICENSE.txt", ]; for filepath in files { let content = std::fs::read_to_string(filepath)?; let input = TextData::from(content); let result = store.analyze(&input); if result.score > 0.8 { println!("{}: {} ({})", filepath, result.name, result.score); } else { println!("{}: Unknown", filepath); } } Ok(()) } ``` -------------------------------- ### Example Workflow Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md This example demonstrates a common workflow for loading a license store and analyzing multiple files to identify their licenses. ```APIDOC ## Example Workflow ```rust use askalono::{Store, TextData}; use std::fs::File; fn main() -> Result<(), Box> { // Load store once let store = Store::from_cache(File::open("askalono-cache.bin.zstd")?)?; // Identify multiple files let files = vec![ "LICENSE", "COPYING", "LICENSE.txt", ]; for filepath in files { let content = std::fs::read_to_string(filepath)?; let input = TextData::from(content); let result = store.analyze(&input); if result.score > 0.8 { println!("{}: {} ({})", filepath, result.name, result.score); } else { println!("{}: Unknown", filepath); } } Ok(()) } ``` ``` -------------------------------- ### Askalo Cache Load-SPDX Example Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Shows how to load SPDX license data into the cache, with an option to store the normalized license text. ```bash askalono cache load-spdx ./spdx-license-list-data/json/details --store ``` -------------------------------- ### Build askalono WASM Library Source: https://github.com/jpeddicord/askalono/blob/master/extras/wasm/README.md Use this command to build the WASM library. Ensure you have wasm-pack installed. ```bash wasm-pack build --out-name askalono ``` -------------------------------- ### Build askalono Demo Application Source: https://github.com/jpeddicord/askalono/blob/master/extras/wasm/README.md After building the library, navigate to the demo directory and use this command to build the demo application. Alternatively, use 'npm start' for a development server. ```bash cd demo && npm run build ``` -------------------------------- ### Install Ascalono CLI with Cargo Source: https://github.com/jpeddicord/askalono/blob/master/README.md Rust developers can install the Ascalono command-line tool using Cargo. This command fetches and installs the latest version. ```bash cargo install askalono-cli ``` -------------------------------- ### Batch Process Files Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md This example shows how to iterate through multiple files, process each with a ScanStrategy, and report any identified licenses. ```APIDOC ## Batch Process Files ### Description Processes a collection of files by loading each one, scanning it for licenses using a ScanStrategy, and printing the identified license name if found. ### Usage ```rust let store = Store::from_cache(cache)?; let strategy = ScanStrategy::new(&store); for filepath in files { let result = strategy.scan(&TextData::from(std::fs::read_to_string(filepath)?))?; if let Some(lic) = result.license { println!("{}: {}", filepath, lic.name); } } ``` ### Related See: [Batch Processing](USAGE_EXAMPLES.md#batch-processing) ``` -------------------------------- ### Identify a License File Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md This example demonstrates how to load a license store from cache, create TextData from file contents, and analyze the input to identify a license. ```APIDOC ## Identify a License File ### Description Loads a license store, processes input text, and analyzes it to identify the most likely license. ### Usage ```rust let store = Store::from_cache(cache_file)?; let input = TextData::from(file_contents); let result = store.analyze(&input); if result.score > 0.85 { println!("License: {}", result.name); } ``` ### Related See: [Basic License Identification](USAGE_EXAMPLES.md#basic-license-identification) ``` -------------------------------- ### Askalo Crawl Subcommand Examples Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Illustrates how to use the 'crawl' subcommand to scan directories for license files, including options to follow symbolic links and use custom glob patterns. ```bash # Scan directory for license files askalono crawl . ``` ```bash # Follow symlinks askalono crawl --follow /usr ``` ```bash # Custom glob pattern askalono crawl --glob "*.txt" . ``` -------------------------------- ### Find License Location in Source Code Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md This example shows how to configure a ScanStrategy with a confidence threshold and then use it to scan source text to find license locations. ```APIDOC ## Find License Location in Source Code ### Description Configures a scanning strategy and applies it to source text to find the locations of identified licenses. ### Usage ```rust let strategy = ScanStrategy::new(&store) .optimize(true) .confidence_threshold(0.80); let result = strategy.scan(&source_text)?; for contained in result.containing { let (start, end) = contained.line_range; println!("Found {} at lines {}-{}", contained.license.name, start, end); } ``` ### Related See: [Find License Locations](USAGE_EXAMPLES.md#find-license-locations-in-source-files) ``` -------------------------------- ### Detect Multiple Licenses Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md This example demonstrates how to set a ScanMode and confidence threshold for a ScanStrategy to detect multiple licenses within a document. ```APIDOC ## Detect Multiple Licenses ### Description Uses a configured scanning strategy to detect and report multiple licenses found within a given text document. ### Usage ```rust let strategy = ScanStrategy::new(&store) .mode(ScanMode::TopDown) .confidence_threshold(0.85); let result = strategy.scan(&attribution_doc)?; for lic in result.containing { println!("Found: {} at lines {}-{}", lic.license.name, lic.line_range.0, lic.line_range.1); } ``` ### Related See: [Detect Multiple Licenses](USAGE_EXAMPLES.md#detect-multiple-licenses-in-document) ``` -------------------------------- ### Askalo Identify Subcommand Examples Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Demonstrates various ways to use the 'identify' subcommand for license detection, including simple identification, finding license locations, batch processing, detecting multiple licenses, and using JSON output. ```bash # Simple identification askalono identify LICENSE ``` ```bash # Find license location askalono id -o src/main.rs ``` ```bash # Batch process find . -name "LICENSE*" | askalono identify -b ``` ```bash # Multiple licenses askalono id -m COPYING ``` ```bash # JSON output askalono --format json identify LICENSE ``` -------------------------------- ### LicenseType Example Usage Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/types.md Demonstrates how to use the LicenseType enum with the Store and TextData, including matching against variants and using the Display trait. ```rust use askalono::{Store, TextData, LicenseType}; let store = Store::from_cache(cache)?; let input = TextData::from("License text"); let result = store.analyze(&input); match result.license_type { LicenseType::Original => println!("Full license matched"), LicenseType::Header => println!("License header matched"), LicenseType::Alternate => println!("Alternate format matched"), } // Display trait println!("Type: {}", result.license_type); // "original text", "license header", etc. ``` -------------------------------- ### Match Lifetime Constraint Example Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md Demonstrates the lifetime constraint of a Match, which is tied to the Store it was generated from. The store must remain alive while the match is in use. ```rust let store = Store::from_cache(cache)?; let input = TextData::from("License text"); let result = store.analyze(&input); // Result references store's data, so must not outlive store drop(result); // Safe: explicitly drop before store drop(store); // OK // This would NOT compile: // let store = Store::from_cache(cache)?; // let result = store.analyze(&input); // drop(store); // println!("{}", result.name); // ERROR: result outlived store ``` -------------------------------- ### Ascalono Crate Features Configuration Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Shows how to specify Ascalono crate versions and features in Cargo.toml. Includes examples for the default 'spdx' feature and enabling 'gzip' compression. ```toml askalono = "0.5" # includes spdx askalono = { version = "0.5", features = ["gzip"] } # gzip instead of zstd ``` -------------------------------- ### Get Line View Bounds after Optimization Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/textdata.md Retrieve the 0-indexed (start, end) line bounds after optimizing the match. This indicates where a matched license was located in the input text. ```rust use askalono::{Store, TextData}; let store = Store::from_cache(cache)?; let input = TextData::from("code here\n\nMIT License\n\nmore code"); let matched = store.analyze(&input); let (optimized, score) = input.optimize_bounds(matched.data); let (start, end) = optimized.lines_view(); println!("License found at lines {}-{}", start, end); ``` -------------------------------- ### Create a Store with Custom Licenses Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Demonstrates how to initialize a new Ascalono store and add custom licenses with their text and header variants. This is useful when the default licenses are insufficient. The store can then be used to analyze text and identify the best matching license. It also shows how to save the store to a cache file for future use. ```rust use askalono::{Store, TextData, LicenseType}; fn main() -> Result<(), Box> { let mut store = Store::new(); // Add custom license let mit_text = TextData::from( "MIT License\n\nCopyright (c) 2024\n\nPermission is hereby granted..." ); store.add_license("MIT".to_string(), mit_text); // Add header variant let mit_header = TextData::from("SPDX-License-Identifier: MIT"); store.add_variant("MIT", LicenseType::Header, mit_header)?; // Add another license let apache_text = TextData::from("Apache License, Version 2.0\n\n..."); store.add_license("Apache-2.0".to_string(), apache_text); println!("Store has {} licenses", store.len()); // Use the store let input = TextData::from("SPDX-License-Identifier: MIT"); let result = store.analyze(&input); println!("Best match: {}", result.name); // Save to cache for reuse let cache_file = std::fs::File::create("custom.cache.bin.zstd")?; store.to_cache(cache_file)?; Ok(()) } ``` -------------------------------- ### TextData::lines_view Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/textdata.md Returns the bounds of the current line view as a 0-indexed `(start, end)` tuple, with inclusive start and exclusive end indices. This is useful after running `optimize_bounds()` to discover where a matched license was located in the input text. ```APIDOC ## TextData::lines_view ### Description Returns the bounds of the current line view as a 0-indexed `(start, end)` tuple, with inclusive start and exclusive end indices. This is useful after running `optimize_bounds()` to discover where a matched license was located in the input text. ### Signature ```rust pub fn lines_view(&self) -> (usize, usize) ``` ### Return type `(usize, usize)` — Tuple of (start_line, end_line). ### Example ```rust use askalono::{Store, TextData}; let store = Store::from_cache(cache)?; let input = TextData::from("code here\n\nMIT License\n\nmore code"); let matched = store.analyze(&input); let (optimized, score) = input.optimize_bounds(matched.data); let (start, end) = optimized.lines_view(); println!("License found at lines {}-", start, end); ``` ``` -------------------------------- ### Creating a Match from Store::analyze() Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md Demonstrates how to load a license store from a cache file and analyze input text to obtain a Match result. ```rust use askalono::{Store, TextData}; use std::fs::File; let store = Store::from_cache(File::open("cache.bin.zstd")?)?; let input = TextData::from("The MIT License..."); let result = store.analyze(&input); println!("Matched: {}", result.name); println!("Score: {:.2}", result.score); println!("Type: {:?}", result.license_type); ``` -------------------------------- ### Askalo Configuration with Gzip Compression Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Enable gzip compression for caches by specifying the 'gzip' feature. This adds the 'flate2' dependency and uses gzip instead of zstd. SPDX loading is enabled by default with this feature. ```toml askalono = { version = "0.5", features = ["gzip"] } ``` -------------------------------- ### ScanResult JSON Serialization Example Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/types.md Illustrates the structure of a ScanResult when serialized to JSON. This format is used for CLI output. ```json { "score": 0.95, "license": { "name": "MIT", "kind": "original", "data": { /* TextData fields */ } }, "containing": [ { "score": 0.88, "license": { "name": "Apache-2.0", "kind": "header" }, "line_range": [10, 15] } ] } ``` -------------------------------- ### Create a new empty Store Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Use this to initialize an empty store when no licenses are pre-loaded. The store is ready to accept licenses via `add_license`. ```rust use askalono::Store; let store = Store::new(); ``` -------------------------------- ### Get Store Size (Rust) Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Returns the number of unique licenses stored. Aliases, headers, and alternates are not counted separately. ```rust let store = Store::from_cache(cache_file)?; println!("Store contains {} licenses", store.len()); ``` -------------------------------- ### Load Askalono Store from Cache Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Load a pre-built Askalono store from a cache file. Ensure the file is correctly formatted and compressed (e.g., zstd). ```rust use std::fs::File; use askalono::Store; let cache_file = File::open("askalono-cache.bin.zstd")?; let store = Store::from_cache(cache_file)?; ``` -------------------------------- ### Build Askalono Cache from SPDX Data (CLI) Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Use the Askalono CLI to load SPDX JSON data and build a cache file. The `--store` option includes normalized license text for larger cache files. ```bash askalono cache load-spdx /path/to/spdx/json/details [--store] ``` -------------------------------- ### Retrieve License Aliases Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Use this function to get all alternative names for a specific license identifier. Ensure the license exists in the store. ```rust pub fn aliases(&self, name: &str) -> Result<&Vec, Error> ``` -------------------------------- ### Load and Analyze License with askalono Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Use this snippet to load a license store from a cache file and analyze a given text file to identify its license. Ensure the cache file and the input file exist and are readable. ```rust use askalono::{Store, TextData}; use std::fs::File; // Load cache let store = Store::from_cache(File::open("cache.bin.zstd")?)?; // Identify let input = TextData::from(std::fs::read_to_string("LICENSE")?); let result = store.analyze(&input); println!("License: {} ({})", result.name, result.score); ``` -------------------------------- ### Get Normalized Lines Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/textdata.md Retrieves a slice of normalized text lines within the current view. This method respects any view set by `with_view()` or `optimize_bounds()`. ```rust use askalono::TextData; let text = TextData::from("Line one\nLine two\nLine three"); for (i, line) in text.lines().iter().enumerate() { println!("{}: {}", i, line); } ``` -------------------------------- ### Load License Store Without Pre-Built Cache Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Creates a new license store and loads it from SPDX data. This process can be slow and is not recommended for production use; consider using a pre-built cache instead. ```rust use askalono::Store; use askalono::TextData; use std::path::Path; fn main() -> Result<(), Box> { // Create a new store and load from SPDX data // Note: This is slow (~20 seconds), use cache for production let mut store = Store::new(); store.load_spdx( Path::new("spdx-license-list-data/json/details"), false, // don't store normalized text to save memory )?; println!("Loaded {} licenses", store.len()); // Analyze... Ok(()) } ``` -------------------------------- ### Load Store from Cache Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Recommended for loading licenses from a pre-compiled binary cache file. This method is faster than parsing text data and verifies compatibility. ```rust use std::fs::File; use askalono::Store; let cache = File::open("askalono-cache.bin.zstd")?; let store = Store::from_cache(cache)?; ``` -------------------------------- ### Handle Cache Version Mismatch Errors Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Provides a handler for cache version mismatch errors, guiding the user to rebuild the cache with the current askalono version. ```rust use std::fs::File; use askalono::Store; let cache = File::open("old-cache.bin.zstd")?; match Store::from_cache(cache) { Ok(store) => println!("Loaded successfully"), Err(e) if e.to_string().contains("cache version mismatch") => { eprintln!("Cache is outdated. Please rebuild:"); eprintln!(" askalono cache load-spdx ./spdx-data --output cache.bin.zstd"); } Err(e) => Err(e)?, } ``` -------------------------------- ### Configure ScanStrategy Options Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Demonstrates how to configure the ScanStrategy using a builder pattern. Options include scan mode, confidence threshold, and optimization settings. Requires an initialized store. ```rust ScanStrategy::new(&store) .mode(ScanMode::Elimination) // Elimination or TopDown .confidence_threshold(0.9) // 0.0–1.0 .shallow_limit(0.99) // Fast exit threshold .optimize(false) // Find exact boundaries .max_passes(10) // Max licenses per document .step_size(5) // TopDown line interval ``` -------------------------------- ### Minimal Askalo Build Configuration Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Configure Askalo for a minimal build by disabling default features. This excludes SPDX loading and uses zstd compression, resulting in the smallest dependency tree. ```toml askalono = { version = "0.5", default-features = false } ``` -------------------------------- ### Build Askalono Cache from SPDX Data (Programmatic) Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Programmatically build an Askalono store from SPDX JSON data and save it to a cache file. Set `include_texts` to `false` for a smaller cache. ```rust use askalono::Store; use std::path::Path; let mut store = Store::new(); store.load_spdx( Path::new("/path/to/spdx/json/details"), false, // include_texts: false for smaller cache )?; let file = std::fs::File::create("cache.bin.zstd")?; store.to_cache(file)?; ``` -------------------------------- ### License Boundary Detection Data Flow Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/ARCHITECTURE.md Describes the process of optimizing license boundaries within a file that contains both code and license text, improving accuracy by refining start and end lines. ```text Input File (with code + license + more code) ↓ TextData::new() → full text with bigrams ↓ Store::analyze() → best match (lower score due to extra text) ↓ TextData::optimize_bounds(matched_license) ├─ Binary search on line boundaries ├─ Try end bounds first ├─ Then optimize start bounds └─ Return (TextData_with_view, score) ↓ Output: License location (lines 10-30) + high score ``` -------------------------------- ### Store::from_cache() Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Loads a Store from a binary cache file. This method is recommended for performance as it bypasses license parsing. ```APIDOC ## Store::from_cache(readable: R) ### Description Loads a store from a binary cache file. This is the recommended way to load licenses, as it avoids the time-consuming process of parsing text data. The cache file must have been created with `to_cache()` and will be verified against a version marker to ensure compatibility. ### Method `from_cache(mut readable: R) -> Result` where `R: Read + Sized` ### Parameters #### Path Parameters - **readable** (`R: Read + Sized`) - Required - An open file handle or readable stream containing a cached store (typically a `.bin.zstd` file) ### Return type `Result` — A loaded store if successful, or an error if the cache version mismatches or the file is corrupted. ### Throws/rejects - `anyhow::Error` - Cache version mismatch (file was created with an incompatible version of askalono) - `anyhow::Error` - I/O error reading the file - `anyhow::Error` - Deserialization failure (corrupted cache) ### Example ```rust use std::fs::File; use askalono::Store; let cache = File::open("askalono-cache.bin.zstd")?; let store = Store::from_cache(cache)?; ``` ``` -------------------------------- ### Askalo CLI Basic Usage Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md The fundamental command structure for the Askalo CLI, showing global options and subcommand usage. ```bash askalono [OPTIONS] ``` -------------------------------- ### Load Store from Cache Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/00_START_HERE.txt Loads a license store from a compressed cache file. Ensure the file exists and is a valid cache. ```rust let store = Store::from_cache(File::open("cache.bin.zstd")?)?; ``` -------------------------------- ### Add Askalo with Default Features Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Include Askalo in your project's dependencies with default features enabled, which includes SPDX loading. ```toml [dependencies] askalono = "0.5" # includes: spdx ``` -------------------------------- ### Parallel License Analysis with Rayon Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/ARCHITECTURE.md Demonstrates parallel iteration, thread-local accumulation, and parallel sorting using the Rayon crate for non-wasm32 builds. This approach is used in Store::analyze() to efficiently process multiple licenses. ```rust let res = self .licenses .par_iter() // Parallel iteration .fold( // Thread-local accumulation Vec::new, |mut acc, (name, data)| { // Each thread scores all variants acc.push(score_original); acc.push(score_headers); acc.push(score_alternates); acc } ) .reduce( // Combine results Vec::new, |mut a, b| { a.extend(b); a } ); res.par_sort_unstable_by(...); // Parallel sort ``` -------------------------------- ### Optimize License Detection from Command Line Source: https://github.com/jpeddicord/askalono/blob/master/README.md Employ the --optimize flag when analyzing files that might contain license text within source code, such as headers or footers. This allows Ascalono to dig deeper into the content. ```bash askalono id --optimize ``` -------------------------------- ### Build Askalo for WebAssembly Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/configuration.md Compile Askalo for wasm32 targets. This automatically disables rayon for parallel processing, uses gzip compression (as zstd is not compatible with wasm32), and results in single-threaded analysis. ```bash cargo build --target wasm32-unknown-unknown ``` -------------------------------- ### Build and Test Ascalono Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Commands to build the Ascalono library in release mode and run its tests. Debug logging can be enabled for tests. ```bash # Build library cargo build --release # Run tests cargo test # Enable debug logging RUST_LOG=debug cargo test -- --nocapture ``` -------------------------------- ### Add License Aliases Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Shows how to set aliases for an existing license in the Ascalono store. Aliases provide alternative names or identifiers for a license, improving search flexibility. This snippet also demonstrates how to retrieve the configured aliases for a given license. ```rust use askalono::Store; fn main() -> Result<(), Box> { let mut store = Store::new(); // ... add licenses ... // Set aliases for a license let aliases = vec![ "Apache License 2.0".to_string(), "Apache 2.0".to_string(), "ALv2".to_string(), ]; store.set_aliases("Apache-2.0", aliases)?; // Query aliases let apache_aliases = store.aliases("Apache-2.0")?; println!("Apache aliases: {:?}", apache_aliases); Ok(()) } ``` -------------------------------- ### Handling Different License Types Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md Illustrates how to use a match statement to differentiate between various license types (Original, Header, Alternate) identified by the Match. ```rust use askalono::LicenseType; match result.license_type { LicenseType::Original => println!("Full license text matched"), LicenseType::Header => println!("License header matched"), LicenseType::Alternate => println!("Alternate format matched"), } ``` -------------------------------- ### Store::new() Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Creates a new, empty Store instance. This is useful for initializing a store that will be populated programmatically. ```APIDOC ## Store::new() ### Description Creates an empty store with no licenses loaded. This is the starting point for building a custom license database. ### Method `new()` ### Return type `Store` — An empty license store ready to accept licenses. ### Example ```rust use askalono::Store; let store = Store::new(); ``` ``` -------------------------------- ### Creating a Match Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/match.md A Match is typically obtained from the `Store::analyze()` method, which compares input text against a store of licenses. ```APIDOC ## Creating a Match A `Match` is typically obtained from `Store::analyze()`: ```rust use askalono::{Store, TextData}; use std::fs::File; let store = Store::from_cache(File::open("cache.bin.zstd")?)?; let input = TextData::from("The MIT License..."); let result = store.analyze(&input); println!("Matched: {}", result.name); println!("Score: {:.2}", result.score); println!("Type: {:?}", result.license_type); ``` ``` -------------------------------- ### Handle License Not Found Error in Ascalono Store Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Demonstrates how to handle the 'License Not Found' error when adding a variant to a license that does not yet exist in the store. It shows adding the base license first before adding the variant. ```rust use askalono::{Store, TextData, LicenseType}; let mut store = Store::new(); // This will fail because "MIT" doesn't exist yet match store.add_variant("MIT", LicenseType::Header, TextData::from("header")) { Ok(()) => println!("Added variant"), Err(e) => { eprintln!("Cannot add variant: {}", e); // Add the base license first store.add_license("MIT".to_string(), TextData::from("full text")); store.add_variant("MIT", LicenseType::Header, TextData::from("header")).ok(); } } ``` -------------------------------- ### Crawl Directory for License Files from Command Line Source: https://github.com/jpeddicord/askalono/blob/master/README.md Use the crawl action to discover license files within a directory tree. This is useful for scanning entire projects. ```bash askalono crawl ``` -------------------------------- ### Handle Askalono Errors with Context Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Demonstrates how to access and display error context using anyhow's chain mechanism when loading a store from cache fails. ```rust use askalono::Store; use std::fs::File; match Store::from_cache(File::open("cache.bin.zstd")) { Ok(store) => println!("Loaded store"), Err(e) => { eprintln!("Error: {}", e); eprintln!("Caused by:"); for cause in e.chain().skip(1) { eprintln!(" - {}", cause); } } } ``` -------------------------------- ### Load Cache and Identify License Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Loads a pre-built license store from a cache file and identifies the license of a given text file. Ensure the cache file and the license file exist. ```rust use askalono::Store; use askalono::TextData; use std::fs::File; fn main() -> Result<(), Box> { // Load the license store from cache let cache = File::open("askalono-cache.bin.zstd")?; let store = Store::from_cache(cache)?; // Read a license file let license_text = std::fs::read_to_string("LICENSE")?; let input = TextData::from(license_text); // Analyze let result = store.analyze(&input); // Check result if result.score > 0.8 { println!("License: {}", result.name); println!("Confidence: {:.2}%", result.score * 100.0); } else { println!("Unknown license"); } Ok(()) } ``` -------------------------------- ### Basic Scan with ScanStrategy Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/scanstrategy.md Demonstrates basic license identification using a pre-loaded store and a confidence threshold. Requires a cache file and a LICENSE file. ```rust use askalono::{Store, ScanStrategy, TextData}; use std::fs::File; let store = Store::from_cache(File::open("cache.bin.zstd")?)?; let strategy = ScanStrategy::new(&store) .confidence_threshold(0.85); let license_text = std::fs::read_to_string("LICENSE")?; let result = strategy.scan(&TextData::from(license_text))?; match result.license { Some(lic) => println!("Identified: {}", lic.name), None => println!("Could not identify license"), } ``` -------------------------------- ### Load SPDX Cache Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Commands to load the Ascalono cache from SPDX JSON data. The `--store` flag includes text for diffing, resulting in a larger cache. ```bash # From SPDX JSON data askalono cache load-spdx /path/to/spdx/json/details # With text included (larger, allows diffs) askalono cache load-spdx /path/to/spdx/json/details --store ``` -------------------------------- ### Compare Multiple Candidate Licenses Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Compares the best license match against a specific known license (e.g., Apache-2.0) to determine similarity scores. This is useful for detailed analysis or when a precise match is required. ```rust use askalono::{Store, TextData}; fn main() -> Result<(), Box> { let store = Store::from_cache(std::fs::File::open("cache.bin.zstd")?)?; let input = TextData::from("License text..."); // Get the best match let best = store.analyze(&input); // Compare against specific license if let Some(apache) = store.get_original("Apache-2.0") { let score_vs_apache = input.match_score(apache); println!("Best match: {} ({})", best.name, best.score); println!("vs Apache-2.0: {}", score_vs_apache); } Ok(()) } ``` -------------------------------- ### Handle Cache File Not Found Error Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md When the cache file is not found, you can either specify an explicit cache path or build the cache first by loading SPDX data. ```bash # Specify explicit cache path askalono -c /path/to/cache.bin.zstd identify LICENSE ``` ```bash # Or build cache first askalono cache load-spdx ./spdx-data askalono identify LICENSE ``` -------------------------------- ### Identify Multiple Licenses with askalono CLI Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Command-line interface command to identify licenses from multiple specified files. ```bash askalono identify -m ATTRIBUTION.md ``` -------------------------------- ### ScanStrategy Configuration Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/scanstrategy.md Demonstrates how to create and configure a ScanStrategy with a confidence threshold. ```APIDOC ## ScanStrategy::new ### Description Initializes a new ScanStrategy with a given license store. ### Method `ScanStrategy::new(&store)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use askalono::{Store, ScanStrategy, TextData}; use std::fs::File; let store = Store::from_cache(File::open("cache.bin.zstd")?)?; let strategy = ScanStrategy::new(&store) .confidence_threshold(0.85); ``` ### Response #### Success Response (200) `ScanStrategy` object configured with the provided store and parameters. #### Response Example None ``` ```APIDOC ## ScanStrategy::confidence_threshold ### Description Sets the minimum confidence score required to identify a license. ### Method `confidence_threshold(threshold: f64)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let strategy = ScanStrategy::new(&store) .confidence_threshold(0.85); ``` ### Response #### Success Response (200) Returns the modified `ScanStrategy` object. #### Response Example None ``` ```APIDOC ## ScanStrategy::optimize ### Description Enables or disables optimization for multi-license detection. ### Method `optimize(enabled: bool)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let strategy = ScanStrategy::new(&store) .optimize(true) .confidence_threshold(0.80); ``` ### Response #### Success Response (200) Returns the modified `ScanStrategy` object. #### Response Example None ``` ```APIDOC ## ScanStrategy::mode ### Description Sets the scanning mode for license detection. ### Method `mode(mode: ScanMode)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use askalono::ScanMode; let strategy = ScanStrategy::new(&store) .mode(ScanMode::TopDown) .confidence_threshold(0.85); ``` ### Response #### Success Response (200) Returns the modified `ScanStrategy` object. #### Response Example None ``` ```APIDOC ## ScanStrategy::step_size ### Description Sets the step size for scanning, determining how often to check for licenses. ### Method `step_size(size: usize)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let strategy = ScanStrategy::new(&store) .mode(ScanMode::TopDown) .step_size(2) .max_passes(20); ``` ### Response #### Success Response (200) Returns the modified `ScanStrategy` object. #### Response Example None ``` ```APIDOC ## ScanStrategy::max_passes ### Description Sets the maximum number of passes for the scanning process. ### Method `max_passes(passes: usize)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let strategy = ScanStrategy::new(&store) .mode(ScanMode::TopDown) .step_size(2) .max_passes(20); ``` ### Response #### Success Response (200) Returns the modified `ScanStrategy` object. #### Response Example None ``` -------------------------------- ### Identify a License File Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Load a license store from cache, create TextData from file contents, and analyze for a license. Use this when you need to determine the primary license of a given file. ```rust let store = Store::from_cache(cache_file)?; let input = TextData::from(file_contents); let result = store.analyze(&input); if result.score > 0.85 { println!("License: {}", result.name); } ``` -------------------------------- ### Validate Store Before Use Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Before using a license store, validate that it is not empty and optionally check if it contains a sufficient number of licenses. Return an error if the store is empty. ```rust use askalono::Store; let store = Store::from_cache(cache)?; if store.is_empty() { return Err("Store contains no licenses".into()); } if store.len() < 100 { eprintln!("Warning: Store has only {} licenses", store.len()); } ``` -------------------------------- ### is_empty Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Checks if the store contains any licenses. ```APIDOC ## `is_empty(&self) -> bool` ### Description Checks if the store contains any licenses. ### Parameters There are no parameters for this method. ### Return type `bool` - true if empty, false otherwise. ### Example ```rust let store = Store::from_cache(cache_file)?; if store.is_empty() { println!("The store is empty."); } ``` ``` -------------------------------- ### Batch Process Files for License Identification using askalono CLI Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Command-line interface command to batch process multiple files found by a find command for license identification. ```bash find . -name "LICENSE*" | askalono identify -b ``` -------------------------------- ### JSON Output for License Identification with askalono CLI Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Command-line interface command to perform license identification and output the results in JSON format. ```bash askalono --format json identify LICENSE ``` -------------------------------- ### Process Multiple License Files Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Scans a predefined list of common license file names in the current directory. Ensure the cache file exists and is valid. ```rust use askalono::{Store, ScanStrategy, TextData}; use std::fs; use std::path::Path; fn main() -> Result<(), Box> { let store = Store::from_cache(fs::File::open("cache.bin.zstd")?)?; let strategy = ScanStrategy::new(&store).confidence_threshold(0.85); let license_files = vec!["LICENSE", "COPYING", "LICENSE.md"]; for filepath in license_files { match fs::read_to_string(filepath) { Ok(content) => { let result = strategy.scan(&TextData::from(content))?; if let Some(lic) = result.license { println!("{}: {}", filepath, lic.name); } else { println!("{}: Unknown", filepath); } } Err(e) => println!("{}: Error - {}", filepath, e), } } Ok(()) } ``` -------------------------------- ### Verify License Compliance Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/USAGE_EXAMPLES.md Checks if the license file in a project directory complies with a list of required licenses. It scans the main LICENSE file and compares the detected license against the allowed ones, reporting compliance or mismatch. ```rust use askalono::{Store, ScanStrategy, TextData}; use std::fs; fn check_license_compliance( project_dir: &str, required_licenses: &["&str"], ) -> Result<(), Box> { let store = Store::from_cache(fs::File::open("cache.bin.zstd")?)?; let strategy = ScanStrategy::new(&store) .confidence_threshold(0.85); // Scan main LICENSE file let license_text = fs::read_to_string( format!("{}/LICENSE", project_dir) )?; let result = strategy.scan(&TextData::from(license_text))?; if let Some(detected) = result.license { if required_licenses.contains(&detected.name) { println!("✓ License is compliant: {}", detected.name); } else { println!("✗ License mismatch: found {}, expected one of {:?}", detected.name, required_licenses); } } else { println!("✗ Could not identify license"); } Ok(()) } fn main() -> Result<(), Box> { check_license_compliance(".", &["MIT", "Apache-2.0"])?; Ok(()) } ``` -------------------------------- ### Find License Location in Source File using askalono CLI Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Command-line interface command to identify the license and its location within a source code file. ```bash askalono identify -o src/main.rs ``` -------------------------------- ### Initialize ScanStrategy Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/scanstrategy.md Constructs a new scanning strategy tied to a given Store. Uses default conservative settings. ```rust use askalono::{Store, ScanStrategy}; let store = Store::from_cache(cache_file)?; let strategy = ScanStrategy::new(&store); ``` -------------------------------- ### Multiple Licenses Data Flow Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/ARCHITECTURE.md Explains how to identify and locate multiple distinct licenses within a single input file by iteratively processing and 'white-outing' previously found licenses. ```text Input File (license1 + code + license2) ↓ Store::analyze() → License1 ↓ optimize_bounds() → find lines 0-20 ↓ TextData::white_out() → blank lines 0-20 ↓ Store::analyze() → License2 ↓ optimize_bounds() → find lines 40-60 ↓ Output: [License1 (lines 0-20), License2 (lines 40-60)] ``` -------------------------------- ### Handle I/O Errors During Cache Loading Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Illustrates handling potential I/O errors, such as file not found or permission issues, when attempting to load a cache file. ```rust use std::fs::File; use askalono::Store; let result = File::open("askalono-cache.bin.zstd") .and_then(|f| Store::from_cache(f).map_err(|e| std::io::Error::other(e))); match result { Ok(store) => println!("Loaded successfully"), Err(e) => eprintln!("Could not load cache: {}", e), } ``` -------------------------------- ### Identify License File from Command Line Source: https://github.com/jpeddicord/askalono/blob/master/README.md Use this command to analyze the text of a specific license file and determine its identity. Ensure the file contains license text. ```bash askalono id ``` -------------------------------- ### Batch Process Files Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Iterate through a list of file paths, reading each file's content and scanning it for licenses using a configured ScanStrategy. This enables efficient processing of multiple files. ```rust let store = Store::from_cache(cache)?; let strategy = ScanStrategy::new(&store); for filepath in files { let result = strategy.scan(&TextData::from(std::fs::read_to_string(filepath)?))?; if let Some(lic) = result.license { println!("{}: {}", filepath, lic.name); } } ``` -------------------------------- ### Enable Optimization Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/scanstrategy.md Enables deeper optimization to locate license bounds within larger text. This is useful for source files with headers or multiple licenses. ```rust let strategy = ScanStrategy::new(&store) .optimize(true) .confidence_threshold(0.8); ``` -------------------------------- ### licenses Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Returns an iterator over all license names in the store. ```APIDOC ## `licenses(&self) -> impl Iterator` ### Description Returns an iterator over all license names in the store. ### Parameters There are no parameters for this method. ### Return type `impl Iterator` - An iterator yielding references to license names. ### Example ```rust let store = Store::from_cache(cache)?; for name in store.licenses() { println!("License: {}", name); } ``` ``` -------------------------------- ### Convert Error to String, Source, and Chain Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/errors.md Demonstrates converting an `anyhow::Error` to a string, accessing its source error, and iterating through the error chain. Useful for detailed error logging and debugging. ```rust use anyhow::Error; use std::error::Error as StdError; fn example(err: Error) { // As string let msg = err.to_string(); // As source if let Some(cause) = err.source() { println!("Caused by: {}", cause); } // As chain for cause in err.chain() { println!(" {}", cause); } } ``` -------------------------------- ### Identify License from Single File using askalono CLI Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/README.md Command-line interface command to identify the license of a single file. ```bash askalono identify LICENSE ``` -------------------------------- ### Check if Store is Empty (Rust) Source: https://github.com/jpeddicord/askalono/blob/master/_autodocs/api-reference/store.md Determines if the license store contains any licenses. ```rust let store = Store::new(); if store.is_empty() { println!("The store is empty."); } ```