| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- import { isDeepEqual } from "remeda"
- export namespace Keybind {
- export type Info = {
- ctrl: boolean
- meta: boolean
- shift: boolean
- leader: boolean
- name: string
- }
- export function match(a: Info, b: Info): boolean {
- return isDeepEqual(a, b)
- }
- export function toString(info: Info): string {
- const parts: string[] = []
- if (info.ctrl) parts.push("ctrl")
- if (info.meta) parts.push("alt")
- if (info.shift) parts.push("shift")
- if (info.name) {
- if (info.name === "delete") parts.push("del")
- else parts.push(info.name)
- }
- let result = parts.join("+")
- if (info.leader) {
- result = result ? `<leader> ${result}` : `<leader>`
- }
- return result
- }
- export function parse(key: string): Info[] {
- if (key === "none") return []
- return key.split(",").map((combo) => {
- // Handle <leader> syntax by replacing with leader+
- const normalized = combo.replace(/<leader>/g, "leader+")
- const parts = normalized.toLowerCase().split("+")
- const info: Info = {
- ctrl: false,
- meta: false,
- shift: false,
- leader: false,
- name: "",
- }
- for (const part of parts) {
- switch (part) {
- case "ctrl":
- info.ctrl = true
- break
- case "alt":
- case "meta":
- case "option":
- info.meta = true
- break
- case "shift":
- info.shift = true
- break
- case "leader":
- info.leader = true
- break
- case "esc":
- info.name = "escape"
- break
- default:
- info.name = part
- break
- }
- }
- return info
- })
- }
- }
|