Skip to main content

llmwiki_tooling/cmd/
mod.rs

1pub mod agent;
2pub mod frontmatter_cmd;
3pub mod init;
4pub mod links;
5pub mod lint;
6pub mod refs;
7pub mod rename;
8pub mod sections;
9
10use std::collections::{HashMap, HashSet};
11use std::ops::Range;
12use std::path::PathBuf;
13
14/// Edits collected during read phase for later application.
15pub(crate) type FileEdits = Vec<(PathBuf, String, Vec<(Range<usize>, String)>)>;
16
17/// Per-directory statistics from scanning markdown files.
18#[derive(Default)]
19pub(crate) struct DirStats {
20    pub file_count: usize,
21    pub frontmatter_fields: HashMap<String, usize>,
22    pub section_headings: HashMap<String, usize>,
23}
24
25/// Check if two slash-separated paths share at least one path component.
26pub(crate) fn share_name_component(a: &str, b: &str) -> bool {
27    let a_parts: HashSet<&str> = a.split('/').collect();
28    let b_parts: HashSet<&str> = b.split('/').collect();
29    !a_parts.is_disjoint(&b_parts)
30}
31
32/// Detect potential mirror directory pairs based on file count and shared name components.
33pub(crate) fn detect_mirror_candidates(dirs: &[(String, usize)]) -> Vec<(&str, &str, usize)> {
34    let mut candidates = Vec::new();
35    for i in 0..dirs.len() {
36        for j in (i + 1)..dirs.len() {
37            let (dir_a, count_a) = &dirs[i];
38            let (dir_b, count_b) = &dirs[j];
39            if count_a == count_b && *count_a > 0 && share_name_component(dir_a, dir_b) {
40                candidates.push((dir_a.as_str(), dir_b.as_str(), *count_a));
41            }
42        }
43    }
44    candidates
45}