diff --git a/ghid/keyboard.go b/ghid/keyboard.go index 426393e..145531d 100644 --- a/ghid/keyboard.go +++ b/ghid/keyboard.go @@ -68,6 +68,17 @@ var ( "RSUPER": RSUPER, "NONE": NONE, } + AllModifiers = []string{ + "LSHIFT", + "LCTRL", + "LALT", + "LSUPER", + "RSHIFT", + "RCTRL", + "RALT", + "RSUPER", + "NONE", + } ) func NewKeyboard(Modifiers map[string]byte, kemapOrder []string, KeymapPath string, hidg0 io.Writer) *Keyboard { @@ -251,7 +262,7 @@ func (k *Keyboard) Hold(press [8]byte, file io.Writer) error { func (k *Keyboard) keymapto0() error { if len(k.KeymapOrder) > 1 { for i := 0; i < len(k.KeymapOrder)-(k.currentKeyMap); i++ { - err := k.Press([8]byte{LALT, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00}, k.Hidg0) + err := k.Press(k.KeymapShortcut, k.Hidg0) if err != nil { return err } diff --git a/ghid/keys.go b/ghid/keys.go new file mode 100644 index 0000000..3939e66 --- /dev/null +++ b/ghid/keys.go @@ -0,0 +1,120 @@ +package hid + +var ( + StandardKeys = map[string]byte{ + "␀": 0x00, + "a": 0x04, + "A": 0x04, + "b": 0x05, + "B": 0x05, + "c": 0x06, + "C": 0x06, + "d": 0x07, + "D": 0x07, + "e": 0x08, + "E": 0x08, + "f": 0x09, + "F": 0x09, + "g": 0x0A, + "G": 0x0A, + "h": 0x0B, + "H": 0x0B, + "i": 0x0C, + "I": 0x0C, + "j": 0x0D, + "J": 0x0D, + "k": 0x0E, + "K": 0x0E, + "l": 0x0F, + "L": 0x0F, + "m": 0x10, + "M": 0x10, + "n": 0x11, + "N": 0x11, + "o": 0x12, + "O": 0x12, + "p": 0x13, + "P": 0x13, + "q": 0x14, + "Q": 0x14, + "r": 0x15, + "R": 0x15, + "s": 0x16, + "S": 0x16, + "t": 0x17, + "T": 0x17, + "u": 0x18, + "U": 0x18, + "v": 0x19, + "V": 0x19, + "w": 0x1A, + "W": 0x1A, + "x": 0x1B, + "X": 0x1B, + "y": 0x1C, + "Y": 0x1C, + "z": 0x1D, + "Z": 0x1D, + "!": 0x1E, + "1": 0x1E, + "2": 0x1F, + "@": 0x1F, + "#": 0x20, + "3": 0x20, + "$": 0x21, + "4": 0x21, + "%": 0x22, + "5": 0x22, + "6": 0x23, + "^": 0x23, + "&": 0x24, + "7": 0x24, + "*": 0x25, + "8": 0x25, + "(": 0x26, + "9": 0x26, + ")": 0x27, + "0": 0x27, + "\n": 0x28, + "⎋": 0x29, // esc + "␛": 0x29, // esc + "⌫": 0x2A, // backspace + "\t": 0x2B, + " ": 0x2C, + "-": 0x2D, + "_": 0x2D, + "+": 0x2E, + "=": 0x2E, + "[": 0x2F, + "{": 0x2F, + "]": 0x30, + "}": 0x30, + "\\": 0x31, + "|": 0x31, + ":": 0x33, + ";": 0x33, + "'": 0x34, + "\"": 0x34, + "`": 0x35, + "~": 0x35, + ",": 0x36, + "<": 0x36, + ".": 0x37, + ">": 0x37, + "/": 0x38, + "?": 0x38, + "⇪": 0x39, + "⎙": 0x46, + "⏸️": 0x48, + "⎀": 0x49, + "↖": 0x4A, + "⇞": 0x4B, + "⌦": 0x4C, + "↘": 0x4D, + "⇟": 0x4E, + "→": 0x4F, + "←": 0x50, + "↑": 0x51, + "↓": 0x52, + } +) diff --git a/main.go b/main.go index ebe75e3..4114ada 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,57 @@ package main import ( + "errors" "flag" "fmt" "io" "os" "path" + "strings" "time" hid "github.com/lordwelch/hid/ghid" ) +func contains(str string, find []string) bool { + str = strings.ToLower(str) + for _, s := range find { + if strings.Contains(str, strings.ToLower(s)) { + return true + } + } + return false +} + +func parse_shortcut(shortcut string) ([8]byte, error) { + var ( + modifiers = []string{} + key = "" + curModifier byte = 0 + curKey byte = 0 + ) + strs := strings.SplitN(strings.ToLower(shortcut), " ", 2) + if len(strs) > 1 { + if contains(strs[0], hid.AllModifiers) { + modifiers = strings.Split(strs[0], "|") + } else { + key = strings.TrimSpace(strs[0]) + } + } else { + modifiers = strings.Split(strs[0], "|") + key = strings.TrimSpace(strs[1]) + } + for _, v := range modifiers { + curModifier |= hid.Modifiers[strings.TrimSpace(v)] + } + if id, ok := hid.StandardKeys[key]; ok { + curKey = id + } else { + return [8]byte{}, errors.New("Key not found") + } + return [8]byte{curModifier, 0x0, curKey}, nil +} + func main() { var ( Shortcut string @@ -23,12 +64,13 @@ func main() { ghid *os.File tmp *os.File keyboard *hid.Keyboard + keymaps []string ) if _, exists := os.LookupEnv("XDG_CONFIG_HOME"); !exists { _ = os.Setenv("XDG_CONFIG_HOME", path.Join(os.ExpandEnv("$HOME"), ".config")) } flag.StringVar(&Shortcut, "shortcut", "", "Keymap cycle shortcut") - flag.StringVar(&Shortcut, "s", "", "Keymap cycle shortcut") + flag.StringVar(&Shortcut, "s", "LALT ⇪", "Keymap cycle shortcut") flag.StringVar(&keymapPath, "path", path.Join(os.ExpandEnv("$XDG_CONFIG_HOME"), "hid"), "Path to config dir default: $XDG_CONFIG_HOME") flag.StringVar(&keymapPath, "p", path.Join(os.ExpandEnv("$XDG_CONFIG_HOME"), "hid"), "Path to config dir default: $XDG_CONFIG_HOME") flag.StringVar(&filePath, "f", "-", "The file to read content from. Defaults to stdin") @@ -43,6 +85,21 @@ func main() { os.Exit(1) } fmt.Println(keymapPath) + dirs, err := os.ReadDir(keymapPath) + if err != nil { + panic(err) + } + +keymap: + for _, requestedKeymap := range flag.Args() { + for _, dir := range dirs { + if strings.HasPrefix(strings.ToLower(dir.Name()), strings.ToLower(requestedKeymap)) { + keymaps = append(keymaps, dir.Name()) + break keymap + } + } + panic(fmt.Sprintf("Keymap %q not found", requestedKeymap)) + } if filePath != "-" { tmp, err = os.Open(path.Clean(filePath)) @@ -58,9 +115,13 @@ func main() { } defer ghid.Close() - keyboard = hid.NewKeyboard(hid.Modifiers, flag.Args(), keymapPath, ghid) + keyboard = hid.NewKeyboard(hid.Modifiers, keymaps, keymapPath, ghid) keyboard.PressDelay = pressDelay keyboard.ReleaseDelay = releaseDelay + keyboard.KeymapShortcut, err = parse_shortcut(Shortcut) + if err != nil { + panic(fmt.Errorf("error parsing shortcut: %w", err)) + } _, err = io.Copy(keyboard, os.Stdin)