Archived
1
0

Adding support for relative movement mouse keys

- Includes kll.py cleanup
- Fixed negative number generation and parsing
This commit is contained in:
Jacob Alexander 2016-03-21 22:22:13 -07:00
parent 55ffc6bdc5
commit d3e0c3d7a7
2 changed files with 73 additions and 48 deletions

84
kll.py
View File

@ -1,8 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# KLL Compiler '''
# Keyboard Layout Langauge KLL Compiler
# Keyboard Layout Langauge
# Copyright (C) 2014-2015 by Jacob Alexander '''
# Copyright (C) 2014-2016 by Jacob Alexander
# #
# This file is free software: you can redistribute it and/or modify # This file is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -21,32 +23,27 @@
import argparse import argparse
import importlib import importlib
import io
import os import os
import re
import sys import sys
import token
from pprint import pformat
from re import VERBOSE from re import VERBOSE
from tokenize import generate_tokens
from kll_lib.containers import * from kll_lib.containers import *
from kll_lib.hid_dict import * from kll_lib.hid_dict import *
from funcparserlib.lexer import make_tokenizer, Token, LexerError from funcparserlib.lexer import make_tokenizer, Token, LexerError
from funcparserlib.parser import (some, a, many, oneplus, skip, finished, maybe, skip, forward_decl, NoParseError) from funcparserlib.parser import (some, a, many, oneplus, finished, maybe, skip, NoParseError)
### Decorators ### ### Decorators ###
## Print Decorator Variables ## Print Decorator Variables
ERROR = '\033[5;1;31mERROR\033[0m:' ERROR = '\033[5;1;31mERROR\033[0m:'
## Python Text Formatting Fixer... ## Python Text Formatting Fixer...
## Because the creators of Python are averse to proper capitalization. ## Because the creators of Python are averse to proper capitalization.
textFormatter_lookup = { textFormatter_lookup = {
"usage: " : "Usage: ", "usage: " : "Usage: ",
"optional arguments" : "Optional Arguments", "optional arguments" : "Optional Arguments",
@ -150,12 +147,12 @@ def tokenize( string ):
( 'String', ( r'"[^"]*"', ) ), ( 'String', ( r'"[^"]*"', ) ),
( 'SequenceString', ( r"'[^']*'", ) ), ( 'SequenceString', ( r"'[^']*'", ) ),
( 'Operator', ( r'=>|:\+|:-|::|:|=', ) ), ( 'Operator', ( r'=>|:\+|:-|::|:|=', ) ),
( 'Number', ( r'(-[ \t]*)?((0x[0-9a-fA-F]+)|(0|([1-9][0-9]*)))', VERBOSE ) ),
( 'Comma', ( r',', ) ), ( 'Comma', ( r',', ) ),
( 'Dash', ( r'-', ) ), ( 'Dash', ( r'-', ) ),
( 'Plus', ( r'\+', ) ), ( 'Plus', ( r'\+', ) ),
( 'Parenthesis', ( r'\(|\)', ) ), ( 'Parenthesis', ( r'\(|\)', ) ),
( 'None', ( r'None', ) ), ( 'None', ( r'None', ) ),
( 'Number', ( r'-?(0x[0-9a-fA-F]+)|(0|([1-9][0-9]*))', VERBOSE ) ),
( 'Name', ( r'[A-Za-z_][A-Za-z_0-9]*', ) ), ( 'Name', ( r'[A-Za-z_][A-Za-z_0-9]*', ) ),
( 'VariableContents', ( r'''[^"' ;:=>()]+''', ) ), ( 'VariableContents', ( r'''[^"' ;:=>()]+''', ) ),
( 'EndOfLine', ( r';', ) ), ( 'EndOfLine', ( r';', ) ),
@ -171,13 +168,13 @@ def tokenize( string ):
### Parsing ### ### Parsing ###
## Map Arrays ## Map Arrays
macros_map = Macros() macros_map = Macros()
variables_dict = Variables() variables_dict = Variables()
capabilities_dict = Capabilities() capabilities_dict = Capabilities()
## Parsing Functions ## Parsing Functions
def make_scanCode( token ): def make_scanCode( token ):
scanCode = int( token[1:], 0 ) scanCode = int( token[1:], 0 )
@ -322,7 +319,7 @@ def make_unseqString( token ):
def make_number( token ): def make_number( token ):
return int( token, 0 ) return int( token, 0 )
# Range can go from high to low or low to high # Range can go from high to low or low to high
def make_scanCode_range( rangeVals ): def make_scanCode_range( rangeVals ):
start = rangeVals[0] start = rangeVals[0]
end = rangeVals[1] end = rangeVals[1]
@ -334,9 +331,9 @@ def make_scanCode_range( rangeVals ):
# Iterate from start to end, and generate the range # Iterate from start to end, and generate the range
return list( range( start, end + 1 ) ) return list( range( start, end + 1 ) )
# Range can go from high to low or low to high # Range can go from high to low or low to high
# Warn on 0-9 for USBCodes (as this does not do what one would expect) TODO # Warn on 0-9 for USBCodes (as this does not do what one would expect) TODO
# Lookup USB HID tags and convert to a number # Lookup USB HID tags and convert to a number
def make_hidCode_range( type, rangeVals ): def make_hidCode_range( type, rangeVals ):
# Check if already integers # Check if already integers
if isinstance( rangeVals[0], int ): if isinstance( rangeVals[0], int ):
@ -371,7 +368,7 @@ def make_consCode_range( rangeVals ):
return make_hidCode_range( 'ConsCode', rangeVals ) return make_hidCode_range( 'ConsCode', rangeVals )
## Base Rules ## Base Rules
const = lambda x: lambda _: x const = lambda x: lambda _: x
unarg = lambda f: lambda x: f(*x) unarg = lambda f: lambda x: f(*x)
@ -389,7 +386,7 @@ def listElem( item ):
def listToTuple( items ): def listToTuple( items ):
return tuple( items ) return tuple( items )
# Flatten only the top layer (list of lists of ...) # Flatten only the top layer (list of lists of ...)
def oneLayerFlatten( items ): def oneLayerFlatten( items ):
mainList = [] mainList = []
for sublist in items: for sublist in items:
@ -398,14 +395,27 @@ def oneLayerFlatten( items ):
return mainList return mainList
# Capability arguments may need to be expanded (e.g. 1 16 bit argument needs to be 2 8 bit arguments for the state machine)
def capArgExpander( items ): def capArgExpander( items ):
'''
Capability arguments may need to be expanded
(e.g. 1 16 bit argument needs to be 2 8 bit arguments for the state machine)
If the number is negative, determine width of the final value, mask to max, subtract,
then convert to multiple bytes
'''
newArgs = [] newArgs = []
# For each defined argument in the capability definition # For each defined argument in the capability definition
for arg in range( 0, len( capabilities_dict[ items[0] ][1] ) ): for arg in range( 0, len( capabilities_dict[ items[0] ][1] ) ):
argLen = capabilities_dict[ items[0] ][1][ arg ][1] argLen = capabilities_dict[ items[0] ][1][ arg ][1]
num = items[1][ arg ] num = items[1][ arg ]
byteForm = num.to_bytes( argLen, byteorder='little' ) # XXX Yes, little endian from how the uC structs work
# Set last bit if value is negative
if num < 0:
max_val = 2 ** (argLen * 8)
num += max_val
# XXX Yes, little endian from how the uC structs work
byteForm = num.to_bytes( argLen, byteorder='little' )
# For each sub-argument, split into byte-sized chunks # For each sub-argument, split into byte-sized chunks
for byte in range( 0, argLen ): for byte in range( 0, argLen ):
@ -413,8 +423,8 @@ def capArgExpander( items ):
return tuple( [ items[0], tuple( newArgs ) ] ) return tuple( [ items[0], tuple( newArgs ) ] )
# Expand ranges of values in the 3rd dimension of the list, to a list of 2nd lists # Expand ranges of values in the 3rd dimension of the list, to a list of 2nd lists
# i.e. [ sequence, [ combo, [ range ] ] ] --> [ [ sequence, [ combo ] ], <option 2>, <option 3> ] # i.e. [ sequence, [ combo, [ range ] ] ] --> [ [ sequence, [ combo ] ], <option 2>, <option 3> ]
def optionExpansion( sequences ): def optionExpansion( sequences ):
expandedSequences = [] expandedSequences = []
@ -489,7 +499,7 @@ def tupleit( t ):
return tuple( map( tupleit, t ) ) if isinstance( t, ( tuple, list ) ) else t return tuple( map( tupleit, t ) ) if isinstance( t, ( tuple, list ) ) else t
## Evaluation Rules ## Evaluation Rules
def eval_scanCode( triggers, operator, results ): def eval_scanCode( triggers, operator, results ):
# Convert to lists of lists of lists to tuples of tuples of tuples # Convert to lists of lists of lists to tuples of tuples of tuples
@ -571,7 +581,7 @@ set_capability = unarg( eval_capability )
set_define = unarg( eval_define ) set_define = unarg( eval_define )
## Sub Rules ## Sub Rules
usbCode = tokenType('USBCode') >> make_usbCode usbCode = tokenType('USBCode') >> make_usbCode
scanCode = tokenType('ScanCode') >> make_scanCode scanCode = tokenType('ScanCode') >> make_scanCode
@ -589,10 +599,10 @@ unString = tokenType('String') # When the double quotes are still needed for
seqString = tokenType('SequenceString') >> make_seqString seqString = tokenType('SequenceString') >> make_seqString
unseqString = tokenType('SequenceString') >> make_unseqString # For use with variables unseqString = tokenType('SequenceString') >> make_unseqString # For use with variables
# Code variants # Code variants
code_end = tokenType('CodeEnd') code_end = tokenType('CodeEnd')
# Scan Codes # Scan Codes
scanCode_start = tokenType('ScanCodeStart') scanCode_start = tokenType('ScanCodeStart')
scanCode_range = number + skip( dash ) + number >> make_scanCode_range scanCode_range = number + skip( dash ) + number >> make_scanCode_range
scanCode_listElem = number >> listElem scanCode_listElem = number >> listElem
@ -602,7 +612,7 @@ scanCode_elem = scanCode >> listElem
scanCode_combo = oneplus( ( scanCode_expanded | scanCode_elem ) + skip( maybe( plus ) ) ) scanCode_combo = oneplus( ( scanCode_expanded | scanCode_elem ) + skip( maybe( plus ) ) )
scanCode_sequence = oneplus( scanCode_combo + skip( maybe( comma ) ) ) scanCode_sequence = oneplus( scanCode_combo + skip( maybe( comma ) ) )
# USB Codes # USB Codes
usbCode_start = tokenType('USBCodeStart') usbCode_start = tokenType('USBCodeStart')
usbCode_number = number >> make_usbCode_number usbCode_number = number >> make_usbCode_number
usbCode_range = ( usbCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_usbCode_range usbCode_range = ( usbCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_usbCode_range
@ -614,7 +624,7 @@ usbCode_elem = usbCode >> listElem
usbCode_combo = oneplus( ( usbCode_expanded | usbCode_elem ) + skip( maybe( plus ) ) ) >> listElem usbCode_combo = oneplus( ( usbCode_expanded | usbCode_elem ) + skip( maybe( plus ) ) ) >> listElem
usbCode_sequence = oneplus( ( usbCode_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten usbCode_sequence = oneplus( ( usbCode_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten
# Cons Codes # Cons Codes
consCode_start = tokenType('ConsCodeStart') consCode_start = tokenType('ConsCodeStart')
consCode_number = number >> make_consCode_number consCode_number = number >> make_consCode_number
consCode_range = ( consCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_consCode_range consCode_range = ( consCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_consCode_range
@ -624,7 +634,7 @@ consCode_innerList = oneplus( ( consCode_range | consCode_listElem ) + skip( m
consCode_expanded = skip( consCode_start ) + consCode_innerList + skip( code_end ) consCode_expanded = skip( consCode_start ) + consCode_innerList + skip( code_end )
consCode_elem = consCode >> listElem consCode_elem = consCode >> listElem
# Sys Codes # Sys Codes
sysCode_start = tokenType('SysCodeStart') sysCode_start = tokenType('SysCodeStart')
sysCode_number = number >> make_sysCode_number sysCode_number = number >> make_sysCode_number
sysCode_range = ( sysCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_sysCode_range sysCode_range = ( sysCode_number | unString ) + skip( dash ) + ( number | unString ) >> make_sysCode_range
@ -634,22 +644,22 @@ sysCode_innerList = oneplus( ( sysCode_range | sysCode_listElem ) + skip( mayb
sysCode_expanded = skip( sysCode_start ) + sysCode_innerList + skip( code_end ) sysCode_expanded = skip( sysCode_start ) + sysCode_innerList + skip( code_end )
sysCode_elem = sysCode >> listElem sysCode_elem = sysCode >> listElem
# HID Codes # HID Codes
hidCode_elem = usbCode_expanded | usbCode_elem | sysCode_expanded | sysCode_elem | consCode_expanded | consCode_elem hidCode_elem = usbCode_expanded | usbCode_elem | sysCode_expanded | sysCode_elem | consCode_expanded | consCode_elem
# Capabilities # Capabilities
capFunc_arguments = many( number + skip( maybe( comma ) ) ) >> listToTuple capFunc_arguments = many( number + skip( maybe( comma ) ) ) >> listToTuple
capFunc_elem = name + skip( parenthesis('(') ) + capFunc_arguments + skip( parenthesis(')') ) >> capArgExpander >> listElem capFunc_elem = name + skip( parenthesis('(') ) + capFunc_arguments + skip( parenthesis(')') ) >> capArgExpander >> listElem
capFunc_combo = oneplus( ( hidCode_elem | capFunc_elem ) + skip( maybe( plus ) ) ) >> listElem capFunc_combo = oneplus( ( hidCode_elem | capFunc_elem ) + skip( maybe( plus ) ) ) >> listElem
capFunc_sequence = oneplus( ( capFunc_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten capFunc_sequence = oneplus( ( capFunc_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten
# Trigger / Result Codes # Trigger / Result Codes
triggerCode_outerList = scanCode_sequence >> optionExpansion triggerCode_outerList = scanCode_sequence >> optionExpansion
triggerUSBCode_outerList = usbCode_sequence >> optionExpansion >> hidCodeToCapability triggerUSBCode_outerList = usbCode_sequence >> optionExpansion >> hidCodeToCapability
resultCode_outerList = ( ( capFunc_sequence >> optionExpansion ) | none ) >> hidCodeToCapability resultCode_outerList = ( ( capFunc_sequence >> optionExpansion ) | none ) >> hidCodeToCapability
## Main Rules ## Main Rules
#| <variable> = <variable contents>; #| <variable> = <variable contents>;
variable_contents = name | content | string | number | comma | dash | unseqString variable_contents = name | content | string | number | comma | dash | unseqString

View File

@ -1,17 +1,32 @@
Name = mouseTest; Name = mouseTest;
Version = 0.3d; Version = 0.2;
Author = "HaaTa (Jacob Alexander) 2016"; Author = "HaaTa (Jacob Alexander) 2016";
KLL = 0.3d; KLL = 0.3d;
# Modified Date # Modified Date
Date = 2016-03-20; Date = 2016-03-21;
U"1" : mouseOut( 1 ); # mouseOut
U"2" : mouseOut( 2 ); # Arg1, button, 1-8
U"3" : mouseOut( 3 ); # Arg2, mouse x relative axis -127 to 127
U"4" : mouseOut( 4 ); # Arg3, mouse y relative axis -127 to 127
U"5" : mouseOut( 5 );
U"6" : mouseOut( 6 ); U"1" : mouseOut( 1, 0, 0 );
U"7" : mouseOut( 7 ); U"2" : mouseOut( 2, 0, 0 );
U"8" : mouseOut( 8 ); U"3" : mouseOut( 3, 0, 0 );
U"4" : mouseOut( 4, 0, 0 );
U"5" : mouseOut( 5, 0, 0 );
U"6" : mouseOut( 6, 0, 0 );
U"7" : mouseOut( 7, 0, 0 );
U"8" : mouseOut( 8, 0, 0 );
U"Up" : mouseOut( 0, 0, 1 );
U"Down" : mouseOut( 0, 0, -1 );
U"Left" : mouseOut( 0, -1, 0 );
U"Right" : mouseOut( 0, 1, 0 );
U"W" : mouseOut( 0, 0, 5 );
U"S" : mouseOut( 0, 0, -5 );
U"A" : mouseOut( 0, -5, 0 );
U"D" : mouseOut( 0, 5, 0 );