changeset 4:9fe08ddb4fdd

Adding list to tuple conversion and USBCode to Capabiltiy conversion.
author Jacob Alexander <haata@kiibohd.com>
date Sat, 06 Sep 2014 12:35:22 -0700
parents 409ddf71b86b
children 4bea03bae7eb
files backends/kiibohd.py examples/simple2.kll kll.py kll_lib/containers.py
diffstat 4 files changed, 113 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/backends/kiibohd.py	Tue Sep 02 23:45:07 2014 -0700
+++ b/backends/kiibohd.py	Sat Sep 06 12:35:22 2014 -0700
@@ -60,6 +60,11 @@
 					self.tagList.append( item )
 
 
+	# USB Code Capability Name
+	def usbCodeCapability( self ):
+		return "usbKeyOut";
+
+
 	# Processes content for fill tags and does any needed dataset calculations
 	def process( self, capabilities ):
 		## Capabilities ##
--- a/examples/simple2.kll	Tue Sep 02 23:45:07 2014 -0700
+++ b/examples/simple2.kll	Sat Sep 06 12:35:22 2014 -0700
@@ -2,16 +2,21 @@
 Author = "HaaTa (Jacob Alexander) 2014";
 KLL = 0.3;
 
+usbKeyOut => Output_usbCodeSend_capability( usbCode : 1 );
 myCapability2 => myFunc2();
 myCapability3 => myFunc3( myArg1 : 2 );
 myCapability  => myFunc( myArg1 : 1, myArg2 : 4 );
 
 S0x3 : myCapability2();
+S0x4 : myCapability( 0x8, 0x25 );
+S0x12 : U[122] + U[123];
 S0x6 : 'abcdDfF';
 S0x40 : U[0x1];
 S0x40 : U[0x1-0x4];
 S0x0B : U["Esc"];
+S0x0B :+ U["Q"];
 S[ 0x7 - 0x9 ] : U"6";
 S[ 0x7 - 0x9 ], S[0x2,0x3] : U"6";
-S[ 0x2 - 0x9, 0x10 ] : U"r";
+S[ 0x2 - 0x9, 0x10 ] :+ U"r";
+S0x0B :- U["Esc"];
 
--- a/kll.py	Tue Sep 02 23:45:07 2014 -0700
+++ b/kll.py	Sat Sep 06 12:35:22 2014 -0700
@@ -83,9 +83,9 @@
 		help="Specify .kll files to generate partial map, multiple files per flag.\n"
 		"Each -p defines another partial map.\n"
 		"Base .kll files (that define the scan code maps) must be defined for each partial map." )
-	pArgs.add_argument( '-t', '--template', type=str, default="templateKeymap.h",
+	pArgs.add_argument( '-t', '--template', type=str, default="templates/kiibohdKeymap.h",
 		help="Specify template used to generate the keymap.\n"
-		"Default: templateKeymap.h" )
+		"Default: templates/kiibohdKeymap.h" )
 	pArgs.add_argument( '-o', '--output', type=str, default="templateKeymap.h",
 		help="Specify output file. Writes to current working directory by default.\n"
 		"Default: generatedKeymap.h" )
@@ -133,10 +133,10 @@
 		( 'CodeEnd',          ( r'\]', ) ),
 		( 'String',           ( r'"[^"]*"', VERBOSE ) ),
 		( 'SequenceString',   ( r"'[^']*'", ) ),
+		( 'Operator',         ( r'=>|:\+|:-|:|=', ) ),
 		( 'Comma',            ( r',', ) ),
 		( 'Dash',             ( r'-', ) ),
 		( 'Plus',             ( r'\+', ) ),
-		( 'Operator',         ( r'=>|:|=', ) ),
 		( 'Parenthesis',      ( r'\(|\)', ) ),
 		( 'Number',           ( r'-?(0x[0-9a-fA-F]+)|(0|([1-9][0-9]*))', VERBOSE ) ),
 		( 'Name',             ( r'[A-Za-z_][A-Za-z_0-9]*', ) ),
@@ -155,8 +155,7 @@
 ### Parsing ###
 
  ## Map Arrays
-scanCode_map      = [ None ] * 0xFF # Define 8 bit address width
-usbCode_map       = [ None ] * 0xFF # Define 8 bit address width
+macros_map        = Macros()
 variable_dict     = dict()
 capabilities_dict = Capabilities()
 
@@ -301,6 +300,9 @@
 def listElem( item ):
 	return [ item ]
 
+def listToTuple( items ):
+	return tuple( items )
+
   # Flatten only the top layer (list of lists of ...)
 def oneLayerFlatten( items ):
 	mainList = []
@@ -357,26 +359,72 @@
 	return expandedSequences
 
 
+# Converts USB Codes into Capabilities
+def usbCodeToCapability( items ):
+	# Items already converted to variants using optionExpansion
+	for variant in range( 0, len( items ) ):
+		# Sequence of Combos
+		for sequence in range( 0, len( items[ variant ] ) ):
+			for combo in range( 0, len( items[ variant ][ sequence ] ) ):
+				# Only convert if an integer, otherwise USB Code doesn't need converting
+				if isinstance( items[ variant ][ sequence ][ combo ], int ):
+					# Use backend capability name and a single argument
+					items[ variant ][ sequence ][ combo ] = tuple( [ backend.usbCodeCapability(), tuple( [ items[ variant ][ sequence ][ combo ] ] ) ] )
+
+	return items
+
+
  ## Evaluation Rules
 
-def eval_scanCode( trigger, result ):
+def eval_scanCode( triggers, operator, results ):
 	# Convert to lists of lists of lists to tuples of tuples of tuples
-	trigger = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in trigger )
-	result  = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in result )
+	# Tuples are non-mutable, and can be used has index items
+	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 )
+
+	# Iterate over all combinations of triggers and results
+	for trigger in triggers:
+		for result in results:
+			# Append Case
+			if operator == ":+":
+				macros_map.appendScanCode( trigger, result )
+
+			# Remove Case
+			elif operator == ":-":
+				macros_map.removeScanCode( trigger, result )
+
+			# Replace Case
+			elif operator == ":":
+				macros_map.replaceScanCode( trigger, result )
+
+	print ( triggers )
+	print ( results )
 
-	# Add to the base scanCode map, overwrite if already defined
-#	if scanCode_map[ trigger ] != None:
-#		print ( "ScanCodeMap - Replacing '{0}' with '{1}' -> {2}".format( scanCode_map[ trigger ], result, trigger ) )
-#	scanCode_map[ trigger ] = result
+def eval_usbCode( triggers, operator, results ):
+	# Convert to lists of lists of lists to tuples of tuples of tuples
+	# Tuples are non-mutable, and can be used has index items
+	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 )
 
-def eval_usbCode( trigger, result ):
-	# Check if trigger is list
+	# Iterate over all combinations of triggers and results
+	for trigger in triggers:
+		scanCodes = macros_map.lookupUSBCodes( trigger )
+		for scanCode in scanCodes:
+			for result in results:
+				# Append Case
+				if operator == ":+":
+					macros_map.appendScanCode( scanCode, result )
 
-	# Add to the base usbCode map, overwrite if already defined
-	if usbCode_map[ trigger ] != None:
-		print ( "USBCodeMap - Replacing '{0}' with '{1}' -> {2}".format( usbCode_map[ trigger ], result, trigger ) )
-	usbCode_map[ trigger ] = result
-	print ( trigger )
+				# Remove Case
+				elif operator == ":-":
+					macros_map.removeScanCode( scanCode, result )
+
+				# Replace Case
+				elif operator == ":":
+					macros_map.replaceScanCode( scanCode, result )
+
+	#print ( triggers )
+	print ( results )
 
 def eval_variable( name, content ):
 	# Content might be a concatenation of multiple data types, convert everything into a single string
@@ -435,15 +483,15 @@
 usbCode_sequence    = oneplus( ( usbCode_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten
 
   # Capabilities
-capFunc_arguments = number + skip( maybe( comma ) )
-capFunc_elem      = name + skip( parenthesis('(') ) + many( capFunc_arguments ) + skip( parenthesis(')') ) >> listElem
+capFunc_arguments = many( number + skip( maybe( comma ) ) ) >> listToTuple
+capFunc_elem      = name + skip( parenthesis('(') ) + capFunc_arguments + skip( parenthesis(')') ) >> listElem
 capFunc_combo     = oneplus( ( usbCode_expanded | usbCode_elem | capFunc_elem ) + skip( maybe( plus ) ) ) >> listElem
 capFunc_sequence  = oneplus( ( capFunc_combo | seqString ) + skip( maybe( comma ) ) ) >> oneLayerFlatten
 
   # Trigger / Result Codes
 triggerCode_outerList    = scanCode_sequence >> optionExpansion
-triggerUSBCode_outerList = usbCode_sequence >> optionExpansion
-resultCode_outerList     = capFunc_sequence >> optionExpansion
+triggerUSBCode_outerList = usbCode_sequence >> optionExpansion >> usbCodeToCapability
+resultCode_outerList     = capFunc_sequence >> optionExpansion >> usbCodeToCapability
 
 
  ## Main Rules
@@ -457,8 +505,9 @@
 capability_expression = name + skip( operator('=>') ) + name + skip( parenthesis('(') ) + many( capability_arguments ) + skip( parenthesis(')') ) + skip( eol ) >> set_capability
 
 #| <trigger> : <result>;
-scanCode_expression = triggerCode_outerList + skip( operator(':') ) + resultCode_outerList + skip( eol ) >> map_scanCode
-usbCode_expression  = triggerUSBCode_outerList + skip( operator(':') ) + resultCode_outerList + skip( eol ) #>> map_usbCode
+operatorTriggerResult = 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
 
 def parse( tokenSequence ):
 	"""Sequence(Token) -> object"""
@@ -489,15 +538,14 @@
 			data = file.read()
 
 			tokenSequence = tokenize( data )
-			print ( pformat( tokenSequence ) )
+			print ( pformat( tokenSequence ) ) # Display tokenization
 			tree = parse( tokenSequence )
 			#print ( tree )
-			#print ( scanCode_map )
-			#print ( usbCode_map )
 			print ( variable_dict )
 			print ( capabilities_dict )
 
 	# TODO Move
+	#macros_map.usbCodeToCapability( backend.usbCodeCapability() )
 	backend.process( capabilities_dict )
 
 	# Successful Execution
--- a/kll_lib/containers.py	Tue Sep 02 23:45:07 2014 -0700
+++ b/kll_lib/containers.py	Sat Sep 06 12:35:22 2014 -0700
@@ -84,31 +84,40 @@
 		self.layer = 0
 
 		# Macro Storage
-		self.macros = [ [] ]
+		self.macros = [ dict() ]
+
+	def __repr__( self ):
+		return "{0}".format( self.macros )
 
 	def setLayer( self, layer ):
 		self.layer = layer
 
 	# Use for ScanCode trigger macros
 	def appendScanCode( self, trigger, result ):
-		self.macros[ self.layer ][ trigger ] = result
+		if not trigger in self.macros[ self.layer ]:
+			self.replaceScanCode( trigger, result )
+		else:
+			self.macros[ self.layer ][ trigger ].append( result )
+
+	# Remove the given trigger/result pair
+	def removeScanCode( self, trigger, result ):
+		# Remove all instances of the given trigger/result pair
+		while result in self.macros[ self.layer ][ trigger ]:
+			self.macros[ self.layer ][ trigger ].remove( result )
 
-	# Use for USBCode trigger macros
-	# An extra lookup is required
-	def appendUSBCode( self, trigger, result ):
-		noSuccess = True
+	# Replaces the given trigger with the given result
+	# If multiple results for a given trigger, clear, then add
+	def replaceScanCode( self, trigger, result ):
+		self.macros[ self.layer ][ trigger ] = [ result ]
 
+	# Return a list of ScanCode triggers with the given USB Code trigger
+	def lookupUSBCodes( self, usbCode ):
+		scanCodeList = []
+
+		# Scan current layer for USB Codes
 		for macro in self.macros[ self.layer ].keys():
-			# USB Code Found
-			if trigger == self.macros[ self.layer ][ macro ]:
-				print ( "USBCode - Replacing '{0}' with '{1}' -> '{2}'".format( trigger, macro, result ) )
-				self.macros[ self.layer ][ macro ] = result
-				noSuccess = False
+			if usbCode == self.macros[ self.layer ][ macro ]:
+				scanCodeList.append( macro )
 
-		# Only show warning if no replacements were done
-		if noSuccess:
-			print ( "Warning: '{1}' USB Code not found in layer {1}".format( trigger, self.layer ) )
-			return False
+		return scanCodeList
 
-		return True
-