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 }