]> git.donarmstrong.com Git - kiibohd-kll.git/blobdiff - kll.py
Adding support for "Soft Replace" kll 0.3c
[kiibohd-kll.git] / kll.py
diff --git a/kll.py b/kll.py
index 668b81639819622e1b123d4eee2ef994280b7def..07a822cd149ad876283ce94b3dda7389ca9ff0f8 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='+',
@@ -149,7 +149,7 @@ def tokenize( string ):
                ( 'CodeEnd',          ( r'\]', ) ),
                ( 'String',           ( r'"[^"]*"', VERBOSE ) ),
                ( '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':
@@ -273,8 +275,7 @@ def make_seqString( token ):
                ( ":",       0x01 ),
                ( "^",      -0x10 ),
                ( "_",      -0x18 ),
-               ( "{}|",    -0x1E ),
-               ( "~",      -0x20 ),
+               ( "{}|~",   -0x1E ),
                ( "@",      -0x32 ),
                ( "?",      -0x38 ),
        )
@@ -466,14 +467,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 +496,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 +526,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 +541,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 +662,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