fide/keybindings.py

101 lines
2.5 KiB
Python

from fide import *
from typing import List, Dict, Callable
from dataclasses import dataclass, field
@dataclass(slots=True, frozen=True)
class Keybinding:
key: str
modifiers: int
@dataclass(slots=True)
class Keymap:
name: str
pinned: bool
passthrough: bool
pop_not_found: bool
mapping: Dict[[int,str],Callable] = field(default_factory=dict)
global keymappings
global keymap_stack
def modsym_to_flag(sym: str):
match sym:
case 'S': return 1
case 'C': return 64
case 'RC': return 128
case 'A': return 256
case 'RA': return 512
case 'M': return 1024
# TODO Get which keycode these are
case 'right meta':
return 'RM'
case 'right shift':
return 'RS'
return None
def symbol_to_num(sym: str):
match sym:
case '!': return '1'
case '@': return '2'
case '#': return '3'
case '$': return '4'
case '%': return '5'
case '^': return '6'
case '&': return '7'
case '*': return '8'
case '(': return '9'
case ')': return '0'
# TODO Get which keycode these are
return sym
def parse_keybinding(keybinding: str) -> str:
keys = keybinding.replace(' ', '').split('-')
if not keys:
# TODO: We need to return some kind of error
return None
keys_len = len(keys)
if keys_len > 1: # We have modifiers
modifiers = 0
for i in range(keys_len - 1):
flag = modsym_to_flag(keys[i])
if flag:
modifiers |= flag
else:
# TODO: Also throw some kind of parsing error
return None
else:
modifiers = 0
if len(keys[-1]) > 1: # We have a multi-stroke keybinding, we don't handle that yet
key = keys[-1]
else:
key = keys[-1][0]
if key.isupper():
modifiers |= 1
key = key.lower()
if not key.isalnum():
key = symbol_to_num(key)
return Keybinding(key, modifiers)
keymap_stack = [
Keymap('insert', pinned=True, passthrough=False, pop_not_found=False),
Keymap('normal', pinned=True, passthrough=False, pop_not_found=False),
]
keymappings = {
'insert': keymap_stack[0],
'normal': keymap_stack[1],
}
def kb(mode: str, binding: str, f: Callable):
b = parse_keybinding(binding)
keymappings[mode].mapping[b] = f
def keymap_push(keymap: Keymap):
keymap_stack.append(keymap_push)
def keymap_pop():
keymap_stack.pop()