/ pkg / system / keymaps.go
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  }