github.com/secoba/wails/v2@v2.6.4/pkg/menu/keys/parser.go (about)

     1  package keys
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/leaanthony/slicer"
     9  )
    10  
    11  var namedKeys = slicer.String([]string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
    12  
    13  func parseKey(key string) (string, bool) {
    14  	// Lowercase!
    15  	key = strings.ToLower(key)
    16  
    17  	// Check special case
    18  	if key == "plus" {
    19  		return "+", true
    20  	}
    21  
    22  	// Handle named keys
    23  	if namedKeys.Contains(key) {
    24  		return key, true
    25  	}
    26  
    27  	// Check we only have a single character
    28  	if len(key) != 1 {
    29  		return "", false
    30  	}
    31  
    32  	runeKey := rune(key[0])
    33  
    34  	// This may be too inclusive
    35  	if strconv.IsPrint(runeKey) {
    36  		return key, true
    37  	}
    38  
    39  	return "", false
    40  }
    41  
    42  func Parse(shortcut string) (*Accelerator, error) {
    43  	var result Accelerator
    44  
    45  	// Split the shortcut by +
    46  	components := strings.Split(shortcut, "+")
    47  
    48  	// If we only have one it should be a key
    49  	// We require components
    50  	if len(components) == 0 {
    51  		return nil, fmt.Errorf("no components given to validateComponents")
    52  	}
    53  
    54  	// Keep track of modifiers we have processed
    55  	var modifiersProcessed slicer.StringSlicer
    56  
    57  	// Check components
    58  	for index, component := range components {
    59  
    60  		// If last component
    61  		if index == len(components)-1 {
    62  			processedkey, validKey := parseKey(component)
    63  			if !validKey {
    64  				return nil, fmt.Errorf("'%s' is not a valid key", component)
    65  			}
    66  			result.Key = processedkey
    67  			continue
    68  		}
    69  
    70  		// Not last component - needs to be modifier
    71  		lowercaseComponent := strings.ToLower(component)
    72  		thisModifier, valid := modifierMap[lowercaseComponent]
    73  		if !valid {
    74  			return nil, fmt.Errorf("'%s' is not a valid modifier", component)
    75  		}
    76  		// Needs to be unique
    77  		if modifiersProcessed.Contains(lowercaseComponent) {
    78  			return nil, fmt.Errorf("Modifier '%s' is defined twice for shortcut: %s", component, shortcut)
    79  		}
    80  
    81  		// Save this data
    82  		result.Modifiers = append(result.Modifiers, thisModifier)
    83  		modifiersProcessed.Add(lowercaseComponent)
    84  	}
    85  
    86  	return &result, nil
    87  }