///|
/// Aggregated statistics for one language.
pub(all) struct LangStat {
key : String
name : String
mut files : Int32
mut lines : Int32
mut code : Int32
mut comments : Int32
mut blanks : Int32
}
///|
/// Full report: per-language stats plus the total.
pub(all) struct Report {
langs : Array[LangStat] // ordered per sort_key/reverse
total : LangStat
}
///|
fn stat_sort_value(s : LangStat, key : String) -> Int32 {
match key {
"files" => s.files
"lines" => s.lines
"blanks" => s.blanks
"code" => s.code
"comments" => s.comments
_ => s.code
}
}
///|
/// Build the report from a map of language key -> accumulated counts.
/// Default order: by displayed language name, matching the CLI default.
pub fn build(
lang_counts : Map[String, @counter.Counts],
sort_key : String,
reverse : Bool,
) -> Report {
let total = LangStat::new_total()
let langs : Array[LangStat] = []
for kv in lang_counts {
let lang = @lang.by_key(kv.0)
let name = match lang {
Some(l) => l.name
None => kv.0
}
let c = kv.1
let s = {
key: kv.0,
name,
files: c.files,
lines: c.lines,
code: c.code,
comments: c.comments,
blanks: c.blanks,
}
langs.push(s)
total.files += c.files
total.lines += c.lines
total.code += c.code
total.comments += c.comments
total.blanks += c.blanks
}
let sign = if reverse { -1 } else { 1 }
if sort_key == "language" {
langs.sort_by(fn(a, b) { sign * a.name.lexical_compare(b.name) })
} else {
langs.sort_by(fn(a, b) {
let va = stat_sort_value(a, sort_key)
let vb = stat_sort_value(b, sort_key)
let c = sign * vb.compare(va) // desc by default
if c == 0 {
sign * a.name.lexical_compare(b.name)
} else {
c
}
})
}
{ langs, total, }
}
///|
pub fn LangStat::new_total() -> LangStat {
{
key: "Total",
name: "Total",
files: 0,
lines: 0,
code: 0,
comments: 0,
blanks: 0,
}
}