Source code for augmenty.keyboard

"""Function for defining and handling keyboard layouts."""

from typing import Dict, List, Tuple

from pydantic import BaseModel

from .util import registry


[docs]class Keyboard(BaseModel): """A Pydantic dataclass object for constructing Keyboard setup. Args: keyboard_array: An array corresponding to a keyboard. This should include two keys a "default" and a "shift". Each containing an array of non-shifted and shifted keys respectively. shift_distance: The distance given by the shift operator. Returns: Keyboard: a Keyboard object """ keyboard_array: Dict[str, List[List[str]]] shift_distance: int = 3
[docs] def coordinate(self, key: str) -> Tuple[int, int]: """Get coordinate for key. Args: key: keyboard key Returns: key coordinate on keyboard """ for arr in self.keyboard_array: for x, row in enumerate(self.keyboard_array[arr]): for y, k in enumerate(row): if key == k: return (x, y) raise ValueError(f"key {key} was not found in keyboard array")
[docs] def is_shifted(self, key: str) -> bool: """Is the key shifted? Args: key (str): keyboard key Returns: bool: a boolean indicating whether key is shifted. """ for x in self.keyboard_array["shift"]: # noqa if key in x: return True return False
[docs] def euclidian_distance(self, key_a: str, key_b: str) -> int: """Returns euclidian distance between two keys. Args: key_a: keyboard key key_b: keyboard key Returns: The euclidian distance between two keyboard keys. """ x1, y1 = self.coordinate(key_a) x2, y2 = self.coordinate(key_b) shift_cost = ( 0 if self.is_shifted(key_a) == self.is_shifted(key_b) else self.shift_distance ) return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5 + shift_cost
[docs] def all_keys(self): """Yields all keys in keyboard. Yields: all keys in keyboard. """ for arr in self.keyboard_array: for x, _ in enumerate(self.keyboard_array[arr]): yield from self.keyboard_array[arr][x]
[docs] def get_neighbours(self, key: str, distance: int = 1) -> List[int]: """Gets the neighbours of a key with a specified distance. Args: key: A keyboard key distance: The euclidian distance of neightbours. Returns: The neighbours of a key with a specified distance. """ l = [] # noqa: E741 for k in self.all_keys(): if k == key: continue if self.euclidian_distance(key, k) <= distance: l.append(k) return l
[docs] def create_distance_dict(self, distance: int = 1) -> dict: return {k: self.get_neighbours(k, distance=distance) for k in self.all_keys()}
[docs] @staticmethod def from_registry(entry: str, shift_distance: int = 3) -> "Keyboard": """Creates a keyboard from a registry.""" array = registry.keyboards.get(entry)() return Keyboard(keyboard_array=array, shift_distance=shift_distance)