aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/macros/KeyComboTrie.kt
blob: 57ff2898573f35ada803abed8f89c56c67c5c096 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package moe.nea.firmament.features.macros

import kotlinx.serialization.Serializable
import net.minecraft.text.Text
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.ErrorUtil

sealed interface KeyComboTrie {
	val label: Text

	companion object {
		fun fromComboList(
			combos: List<ComboKeyAction>,
		): Branch {
			val root = Branch(mutableMapOf())
			for (combo in combos) {
				var p = root
				if (combo.keys.isEmpty()) {
					ErrorUtil.softUserError("Key Combo for ${combo.action.label.string} is empty")
					continue
				}
				for ((index, key) in combo.keys.withIndex()) {
					val m = (p.nodes as MutableMap)
					if (index == combo.keys.lastIndex) {
						if (key in m) {
							ErrorUtil.softUserError("Overlapping actions found for ${combo.keys.joinToString(" > ")} (another action ${m[key]} already exists).")
							break
						}

						m[key] = Leaf(combo.action)
					} else {
						val c = m.getOrPut(key) { Branch(mutableMapOf()) }
						if (c !is Branch) {
							ErrorUtil.softUserError("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already")
							break
						} else {
							p = c
						}
					}
				}
			}
			return root
		}
	}
}


@Serializable
data class ComboKeyAction(
	val action: HotkeyAction,
	val keys: List<SavedKeyBinding>,
)

data class Leaf(val action: HotkeyAction) : KeyComboTrie {
	override val label: Text
		get() = action.label

	fun execute() {
		action.execute()
	}
}

data class Branch(
	val nodes: Map<SavedKeyBinding, KeyComboTrie>
) : KeyComboTrie {
	override val label: Text
		get() = Text.literal("...") // TODO: better labels
}