qmk find: expand operator support (#24468)
				
					
				
			This commit is contained in:
		
							parent
							
								
									c7a04bd930
								
							
						
					
					
						commit
						65a8a5ff69
					
				
					 3 changed files with 43 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -239,11 +239,11 @@ def _filter_keymap_targets(target_list: List[KeyboardKeymapDesc], filters: List[
 | 
			
		|||
        valid_targets = parallel_map(_load_keymap_info, target_list)
 | 
			
		||||
 | 
			
		||||
        function_re = re.compile(r'^(?P<function>[a-zA-Z]+)\((?P<key>[a-zA-Z0-9_\.]+)(,\s*(?P<value>[^#]+))?\)$')
 | 
			
		||||
        equals_re = re.compile(r'^(?P<key>[a-zA-Z0-9_\.]+)\s*=\s*(?P<value>[^#]+)$')
 | 
			
		||||
        comparison_re = re.compile(r'^(?P<key>[a-zA-Z0-9_\.]+)\s*(?P<op>[\<\>\!=]=|\<|\>)\s*(?P<value>[^#]+)$')
 | 
			
		||||
 | 
			
		||||
        for filter_expr in filters:
 | 
			
		||||
            function_match = function_re.match(filter_expr)
 | 
			
		||||
            equals_match = equals_re.match(filter_expr)
 | 
			
		||||
            comparison_match = comparison_re.match(filter_expr)
 | 
			
		||||
 | 
			
		||||
            if function_match is not None:
 | 
			
		||||
                func_name = function_match.group('function').lower()
 | 
			
		||||
| 
						 | 
				
			
			@ -259,23 +259,43 @@ def _filter_keymap_targets(target_list: List[KeyboardKeymapDesc], filters: List[
 | 
			
		|||
                value_str = f", {{fg_cyan}}{value}{{fg_reset}}" if value is not None else ""
 | 
			
		||||
                cli.log.info(f'Filtering on condition: {{fg_green}}{func_name}{{fg_reset}}({{fg_cyan}}{key}{{fg_reset}}{value_str})...')
 | 
			
		||||
 | 
			
		||||
            elif equals_match is not None:
 | 
			
		||||
                key = equals_match.group('key')
 | 
			
		||||
                value = equals_match.group('value')
 | 
			
		||||
                cli.log.info(f'Filtering on condition: {{fg_cyan}}{key}{{fg_reset}} == {{fg_cyan}}{value}{{fg_reset}}...')
 | 
			
		||||
            elif comparison_match is not None:
 | 
			
		||||
                key = comparison_match.group('key')
 | 
			
		||||
                op = comparison_match.group('op')
 | 
			
		||||
                value = comparison_match.group('value')
 | 
			
		||||
                cli.log.info(f'Filtering on condition: {{fg_cyan}}{key}{{fg_reset}} {op} {{fg_cyan}}{value}{{fg_reset}}...')
 | 
			
		||||
 | 
			
		||||
                def _make_filter(k, v):
 | 
			
		||||
                def _make_filter(k, o, v):
 | 
			
		||||
                    expr = fnmatch.translate(v)
 | 
			
		||||
                    rule = re.compile(f'^{expr}$', re.IGNORECASE)
 | 
			
		||||
 | 
			
		||||
                    def f(e: KeyboardKeymapDesc):
 | 
			
		||||
                        lhs = e.dotty.get(k)
 | 
			
		||||
                        lhs = str(False if lhs is None else lhs)
 | 
			
		||||
                        return rule.search(lhs) is not None
 | 
			
		||||
                        rhs = v
 | 
			
		||||
 | 
			
		||||
                        if o in ['<', '>', '<=', '>=']:
 | 
			
		||||
                            lhs = int(False if lhs is None else lhs)
 | 
			
		||||
                            rhs = int(rhs)
 | 
			
		||||
 | 
			
		||||
                            if o == '<':
 | 
			
		||||
                                return lhs < rhs
 | 
			
		||||
                            elif o == '>':
 | 
			
		||||
                                return lhs > rhs
 | 
			
		||||
                            elif o == '<=':
 | 
			
		||||
                                return lhs <= rhs
 | 
			
		||||
                            elif o == '>=':
 | 
			
		||||
                                return lhs >= rhs
 | 
			
		||||
                        else:
 | 
			
		||||
                            lhs = str(False if lhs is None else lhs)
 | 
			
		||||
 | 
			
		||||
                            if o == '!=':
 | 
			
		||||
                                return rule.search(lhs) is None
 | 
			
		||||
                            elif o == '==':
 | 
			
		||||
                                return rule.search(lhs) is not None
 | 
			
		||||
 | 
			
		||||
                    return f
 | 
			
		||||
 | 
			
		||||
                valid_targets = filter(_make_filter(key, value), valid_targets)
 | 
			
		||||
                valid_targets = filter(_make_filter(key, op, value), valid_targets)
 | 
			
		||||
            else:
 | 
			
		||||
                cli.log.warning(f'Unrecognized filter expression: {filter_expr}')
 | 
			
		||||
                continue
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -390,7 +390,7 @@ def test_find_contains():
 | 
			
		|||
def test_find_multiple_conditions():
 | 
			
		||||
    # this is intended to match at least 'crkbd/rev1'
 | 
			
		||||
    result = check_subcommand(
 | 
			
		||||
        'find', '-f', 'exists(rgb_matrix.split_count)', '-f', 'contains(matrix_pins.cols, B1)', '-f', 'length(matrix_pins.cols, 6)', '-f', 'absent(eeprom.driver)', '-f', 'ws2812.pin=D3', '-p', 'rgb_matrix.split_count', '-p', 'matrix_pins.cols', '-p',
 | 
			
		||||
        'find', '-f', 'exists(rgb_matrix.split_count)', '-f', 'contains(matrix_pins.cols, B1)', '-f', 'length(matrix_pins.cols, 6)', '-f', 'absent(eeprom.driver)', '-f', 'ws2812.pin == D3', '-p', 'rgb_matrix.split_count', '-p', 'matrix_pins.cols', '-p',
 | 
			
		||||
        'eeprom.driver', '-p', 'ws2812.pin'
 | 
			
		||||
    )
 | 
			
		||||
    check_returncode(result)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue