keymaps.go
1 package system 2 3 import ( 4 "bufio" 5 "os/exec" 6 "regexp" 7 "sort" 8 "strings" 9 ) 10 11 type Keymap struct { 12 Name string `json:"name"` 13 Value string `json:"value"` 14 } 15 16 func GetKeymaps() ([]Keymap, error) { 17 // Execute the xkbcli command 18 cmd := exec.Command("xkbcli", "list", "--load-exotic") 19 output, err := cmd.Output() 20 if err != nil { 21 return nil, err 22 } 23 24 // Convert output to a string and create a scanner 25 scanner := bufio.NewScanner(strings.NewReader(string(output))) 26 27 // Regular expressions to match layout and description 28 layoutRegex := regexp.MustCompile(`layout: *'([^']+)'`) 29 descriptionRegex := regexp.MustCompile(`description: *(.*)`) 30 31 var layouts []Keymap 32 layoutMap := make(map[string]bool) 33 var currentLayout string 34 35 for scanner.Scan() { 36 line := scanner.Text() 37 38 // Match the layout line 39 if layoutMatch := layoutRegex.FindStringSubmatch(line); layoutMatch != nil { 40 layout := layoutMatch[1] 41 if layoutMap[layout] { 42 continue 43 } 44 currentLayout = layout 45 layoutMap[layout] = true 46 } 47 48 // Match the description line and add to the slice 49 if currentLayout != "" { 50 if descMatch := descriptionRegex.FindStringSubmatch(line); descMatch != nil { 51 description := descMatch[1] 52 layouts = append(layouts, Keymap{Name: currentLayout, Value: description}) 53 currentLayout = "" 54 } 55 } 56 } 57 58 // Sort layouts by name for consistent output 59 sort.Slice(layouts, func(i, j int) bool { 60 return layouts[i].Name < layouts[j].Name 61 }) 62 63 // Remove layouts with name "custom" 64 filteredLayouts := make([]Keymap, 0, len(layouts)) 65 for _, layout := range layouts { 66 if layout.Name != "custom" { 67 filteredLayouts = append(filteredLayouts, layout) 68 } 69 } 70 71 return filteredLayouts, nil 72 }