///|
/// Keymap metrics used to track maintainability over time.
pub(all) struct KeymapMetrics {
binding_count : Int
enabled_count : Int
context_count : Int
platform_count : Int
command_count : Int
max_chord_length : Int
average_chord_length : Int
modifierless_count : Int
documented_count : Int
duplicate_command_count : Int
density_score : Int
} derive(Eq, @debug.Debug)
///|
fn unique_strings(values : Array[String]) -> Array[String] {
let result : Array[String] = []
for value in values {
if !array_contains(result, value) {
result.push(value)
}
}
result
}
///|
/// Calculate counts without relying on hash maps, keeping the library small.
pub fn keymap_metrics(keymap : Keymap) -> KeymapMetrics {
let commands : Array[String] = []
let platforms : Array[String] = []
let mut enabled = 0
let mut max_length = 0
let mut total_length = 0
let mut modifierless = 0
let mut documented = 0
for binding in keymap.bindings {
commands.push(binding.command)
platforms.push(lower_ascii(binding.platform))
if binding.enabled {
enabled += 1
}
if binding.keys.steps.length() > max_length {
max_length = binding.keys.steps.length()
}
total_length += binding.keys.steps.length()
if !binding.keys.has_modifier {
modifierless += 1
}
if binding.description.length() > 0 {
documented += 1
}
}
let unique_commands = unique_strings(commands)
let duplicate_commands = keymap.bindings.length() - unique_commands.length()
let average = if keymap.bindings.length() == 0 {
0
} else {
total_length / keymap.bindings.length()
}
let density = if keymap.bindings.length() == 0 {
0
} else {
enabled * 100 / keymap.bindings.length()
}
{
binding_count: keymap.bindings.length(),
enabled_count: enabled,
context_count: keymap.contexts.length(),
platform_count: unique_strings(platforms).length(),
command_count: unique_commands.length(),
max_chord_length: max_length,
average_chord_length: average,
modifierless_count: modifierless,
documented_count: documented,
duplicate_command_count: duplicate_commands,
density_score: density,
}
}
///|
pub fn metrics_to_json(metrics : KeymapMetrics) -> String {
"{" +
"\"bindings\":" +
metrics.binding_count.to_string() +
"," +
"\"enabled\":" +
metrics.enabled_count.to_string() +
"," +
"\"contexts\":" +
metrics.context_count.to_string() +
"," +
"\"platforms\":" +
metrics.platform_count.to_string() +
"," +
"\"commands\":" +
metrics.command_count.to_string() +
"," +
"\"max_chord_length\":" +
metrics.max_chord_length.to_string() +
"," +
"\"average_chord_length\":" +
metrics.average_chord_length.to_string() +
"," +
"\"modifierless\":" +
metrics.modifierless_count.to_string() +
"," +
"\"documented\":" +
metrics.documented_count.to_string() +
"," +
"\"duplicate_commands\":" +
metrics.duplicate_command_count.to_string() +
"," +
"\"density_score\":" +
metrics.density_score.to_string() +
"}"
}