fret_runtime/keymap/
conflicts.rs1use crate::CommandId;
2use std::collections::{HashMap, HashSet};
3
4use super::{
5 Keymap, KeymapBindingSignature, KeymapConflict, KeymapConflictEntry, KeymapConflictKind,
6};
7
8impl Keymap {
9 pub fn conflicts(&self) -> Vec<KeymapConflict> {
14 let mut by_sig: HashMap<KeymapBindingSignature, Vec<KeymapConflictEntry>> = HashMap::new();
15
16 for (index, b) in self.bindings.iter().enumerate() {
17 let sig = KeymapBindingSignature {
18 platform: b.platform,
19 sequence: b.sequence.clone(),
20 when: b.when.clone(),
21 };
22 by_sig.entry(sig).or_default().push(KeymapConflictEntry {
23 index,
24 command: b.command.clone(),
25 });
26 }
27
28 let mut out: Vec<KeymapConflict> = Vec::new();
29 for (signature, mut entries) in by_sig {
30 if entries.len() <= 1 {
31 continue;
32 }
33
34 entries.sort_by_key(|e| e.index);
35
36 let mut commands: HashSet<Option<&CommandId>> = HashSet::new();
37 let mut any_unbind = false;
38 for e in &entries {
39 any_unbind |= e.command.is_none();
40 commands.insert(e.command.as_ref());
41 }
42
43 let kind = if commands.len() <= 1 {
44 KeymapConflictKind::Redundant
45 } else if any_unbind {
46 KeymapConflictKind::Unbind
47 } else {
48 KeymapConflictKind::Override
49 };
50
51 out.push(KeymapConflict {
52 signature,
53 kind,
54 entries,
55 });
56 }
57
58 out.sort_by(|a, b| {
59 let ka = a.entries.last().map(|e| e.index).unwrap_or_default();
60 let kb = b.entries.last().map(|e| e.index).unwrap_or_default();
61 ka.cmp(&kb)
62 });
63 out
64 }
65}