]> git.donarmstrong.com Git - kiibohd-kll.git/blobdiff - kll.py
Fixing ascii string macro processing
[kiibohd-kll.git] / kll.py
diff --git a/kll.py b/kll.py
index 668b81639819622e1b123d4eee2ef994280b7def..c4386e0bf7cb34bbadfb38da0e7d52dea37602e0 100755 (executable)
--- a/kll.py
+++ b/kll.py
@@ -69,12 +69,12 @@ def checkFileExists( filename ):
 def processCommandLineArgs():
        # Setup argument processor
        pArgs = argparse.ArgumentParser(
-               usage="%(prog)s [options] <file1>...",
-               description="Generates .h file state tables and pointer indices from KLL .kll files.",
-               epilog="Example: {0} mykeyboard.kll -d colemak.kll -p hhkbpro2.kll -p symbols.kll".format( os.path.basename( sys.argv[0] ) ),
-               formatter_class=argparse.RawTextHelpFormatter,
-               add_help=False,
-)
+               usage="%(prog)s [options] <file1>...",
+               description="Generates .h file state tables and pointer indices from KLL .kll files.",
+               epilog="Example: {0} mykeyboard.kll -d colemak.kll -p hhkbpro2.kll -p symbols.kll".format( os.path.basename( sys.argv[0] ) ),
+               formatter_class=argparse.RawTextHelpFormatter,
+               add_help=False,
+       )
 
        # Positional Arguments
        pArgs.add_argument( 'files', type=str, nargs='+',
@@ -147,9 +147,9 @@ def tokenize( string ):
                ( 'ScanCode',         ( r'S((0x[0-9a-fA-F]+)|([0-9]+))', ) ),
                ( 'ScanCodeStart',    ( r'S\[', ) ),
                ( 'CodeEnd',          ( r'\]', ) ),
-               ( 'String',           ( r'"[^"]*"', VERBOSE ) ),
+               ( 'String',           ( r'"[^"]*"', ) ),
                ( 'SequenceString',   ( r"'[^']*'", ) ),
-               ( 'Operator',         ( r'=>|:\+|:-|:|=', ) ),
+               ( 'Operator',         ( r'=>|:\+|:-|::|:|=', ) ),
                ( 'Comma',            ( r',', ) ),
                ( 'Dash',             ( r'-', ) ),
                ( 'Plus',             ( r'\+', ) ),
@@ -182,9 +182,10 @@ capabilities_dict = Capabilities()
 def make_scanCode( token ):
        scanCode = int( token[1:], 0 )
        # Check size, to make sure it's valid
-       if scanCode > 0xFF:
-               print ( "{0} ScanCode value {1} is larger than 255".format( ERROR, scanCode ) )
-               raise
+       # XXX Add better check that takes symbolic names into account (i.e. U"Latch5")
+       #if scanCode > 0xFF:
+       #       print ( "{0} ScanCode value {1} is larger than 255".format( ERROR, scanCode ) )
+       #       raise
        return scanCode
 
 def make_hidCode( type, token ):
@@ -214,9 +215,10 @@ def make_hidCode( type, token ):
                        hidCode = int( token, 0 )
 
        # Check size if a USB Code, to make sure it's valid
-       if type == 'USBCode' and hidCode > 0xFF:
-               print ( "{0} USBCode value {1} is larger than 255".format( ERROR, hidCode ) )
-               raise
+       # XXX Add better check that takes symbolic names into account (i.e. U"Latch5")
+       #if type == 'USBCode' and hidCode > 0xFF:
+       #       print ( "{0} USBCode value {1} is larger than 255".format( ERROR, hidCode ) )
+       #       raise
 
        # Return a tuple, identifying which type it is
        if type == 'USBCode':
@@ -266,17 +268,17 @@ def make_seqString( token ):
                ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0x20 ),
                ( "+",       0x12 ),
                ( "&(",      0x11 ),
-               ( "!#$%<>",  0x10 ),
+               ( "!#$%",    0x10 ),
                ( "*",       0x0E ),
                ( ")",       0x07 ),
                ( '"',       0x05 ),
                ( ":",       0x01 ),
-               ( "^",      -0x10 ),
-               ( "_",      -0x18 ),
-               ( "{}|",    -0x1E ),
-               ( "~",      -0x20 ),
-               ( "@",      -0x32 ),
-               ( "?",      -0x38 ),
+               ( "@",      -0x0E ),
+               ( "<>?",    -0x10 ),
+               ( "~",      -0x1E ),
+               ( "{}|",    -0x20 ),
+               ( "^",      -0x28 ),
+               ( "_",      -0x32 ),
        )
 
        listOfLists = []
@@ -466,14 +468,27 @@ def hidCodeToCapability( items ):
                for sequence in range( 0, len( items[ variant ] ) ):
                        for combo in range( 0, len( items[ variant ][ sequence ] ) ):
                                if items[ variant ][ sequence ][ combo ][0] in backend.requiredCapabilities.keys():
-                                       # Use backend capability name and a single argument
-                                       items[ variant ][ sequence ][ combo ] = tuple(
-                                               [ backend.capabilityLookup( items[ variant ][ sequence ][ combo ][0] ),
-                                               tuple( [ hid_lookup_dictionary[ items[ variant ][ sequence ][ combo ] ] ] ) ]
-                                       )
+                                       try:
+                                               # Use backend capability name and a single argument
+                                               items[ variant ][ sequence ][ combo ] = tuple(
+                                                       [ backend.capabilityLookup( items[ variant ][ sequence ][ combo ][0] ),
+                                                       tuple( [ hid_lookup_dictionary[ items[ variant ][ sequence ][ combo ] ] ] ) ]
+                                               )
+                                       except KeyError:
+                                               print ( "{0} {1} is an invalid HID lookup value".format( ERROR, items[ variant ][ sequence ][ combo ] ) )
+                                               sys.exit( 1 )
        return items
 
 
+# Convert tuple of tuples to list of lists
+def listit( t ):
+       return list( map( listit, t ) ) if isinstance( t, ( list, tuple ) ) else t
+
+# Convert list of lists to tuple of tuples
+def tupleit( t ):
+       return tuple( map( tupleit, t ) ) if isinstance( t, ( tuple, list ) ) else t
+
+
  ## Evaluation Rules
 
 def eval_scanCode( triggers, operator, results ):
@@ -482,8 +497,26 @@ def eval_scanCode( triggers, operator, results ):
        triggers = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in triggers )
        results  = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in results )
 
+       # Lookup interconnect id (Current file scope)
+       # Default to 0 if not specified
+       if 'ConnectId' not in variables_dict.overallVariables.keys():
+               id_num = 0
+       else:
+               id_num = int( variables_dict.overallVariables['ConnectId'] )
+
        # Iterate over all combinations of triggers and results
-       for trigger in triggers:
+       for sequence in triggers:
+               # Convert tuple of tuples to list of lists so each element can be modified
+               trigger = listit( sequence )
+
+               # Create ScanCode entries for trigger
+               for seq_index, combo in enumerate( sequence ):
+                       for com_index, scancode in enumerate( combo ):
+                               trigger[ seq_index ][ com_index ] = macros_map.scanCodeStore.append( ScanCode( scancode, id_num ) )
+
+               # Convert back to a tuple of tuples
+               trigger = tupleit( trigger )
+
                for result in results:
                        # Append Case
                        if operator == ":+":
@@ -494,7 +527,8 @@ def eval_scanCode( triggers, operator, results ):
                                macros_map.removeScanCode( trigger, result )
 
                        # Replace Case
-                       elif operator == ":":
+                       # Soft Replace Case is the same for Scan Codes
+                       elif operator == ":" or operator == "::":
                                macros_map.replaceScanCode( trigger, result )
 
 def eval_usbCode( triggers, operator, results ):
@@ -508,6 +542,10 @@ def eval_usbCode( triggers, operator, results ):
                scanCodes = macros_map.lookupUSBCodes( trigger )
                for scanCode in scanCodes:
                        for result in results:
+                               # Soft Replace needs additional checking to see if replacement is necessary
+                               if operator == "::" and not macros_map.softReplaceCheck( scanCode ):
+                                       continue
+
                                # Cache assignment until file finishes processing
                                macros_map.cacheAssignment( operator, scanCode, result )
 
@@ -625,7 +663,7 @@ capability_expression = name + skip( operator('=>') ) + name + skip( parenthesis
 define_expression = name + skip( operator('=>') ) + name + skip( eol ) >> set_define
 
 #| <trigger> : <result>;
-operatorTriggerResult = operator(':') | operator(':+') | operator(':-')
+operatorTriggerResult = operator(':') | operator(':+') | operator(':-') | operator('::')
 scanCode_expression   = triggerCode_outerList + operatorTriggerResult + resultCode_outerList + skip( eol ) >> map_scanCode
 usbCode_expression    = triggerUSBCode_outerList + operatorTriggerResult + resultCode_outerList + skip( eol ) >> map_usbCode