main.go (6208B)
- package main
- import (
- "io/ioutil"
- "fmt"
- "encoding/json"
- "os"
- "path/filepath"
- "strings"
- "sort"
- "hash/crc64"
- //"encoding/base64"
- )
- func main() {
- // Show Usage
- if len(os.Args) < 3 {
- fmt.Println("Usage: ./keymap-gen src-dir out-dir")
- fmt.Println("Outputs c files in out-dir")
- fmt.Println("Make sure the dirs exist.")
- return
- }
- files, err := filepath.Glob(os.Args[1] + "/*.json")
- if err != nil {
- fmt.Printf("Could not open src-dir: %v\n", err)
- return
- }
- for _, fname := range(files) {
- fmt.Println("Processing: ", fname)
- // Read the source
- data, err := ioutil.ReadFile(fname)
- if err != nil {
- panic(err)
- }
- // Unbundle Data
- var FullDict map[string]Entry
- json.Unmarshal(data, &FullDict)
- // Loop over entries and store
- var output []string
- for i,v := range FullDict {
- if i == "0" {
- continue
- }
- // Special handling for numbermap
- var entry string
- if strings.Contains(fname, "num") {
- entry = v.toKeymap("NUM|")
- } else {
- entry = v.toKeymap("")
- }
- if entry != "" {
- output = append(output, entry)
- }
- }
- // Sort by length, then amount of whitespace lol
- sort.Slice(output, func (i,j int) bool {
- var maxLen int
- if len(output[i]) > len(output[j]) {
- maxLen = len(output[i])
- } else {
- maxLen = len(output[j])
- }
- return maxLen-strings.Count(output[i][:40], " ") < maxLen-strings.Count(output[j][:40], " ")
- })
- // Whack a disclaimer
- output = append([]string{"// This file is automatically generated. Do not edit it!\n\n"}, output...)
- // Write all data out
- outName := filepath.Base(fname)
- outName = os.Args[2] + outName[:len(outName)-5]+".def"
- fmt.Println("Saving: ", outName)
- ioutil.WriteFile(outName, []byte(strings.Join(output, "")), 0755)
- }
- }
- func (e Entry) toKeymap(prefix string) (string) {
- // storage for parts
- var command, chord, arg string
- wordInfo := parseWords(e)
- // Handle prefix
- if prefix != "" {
- chord = prefix
- }
- // Format the chord
- keys := []string{"AA", "AS", "AE", "AT", "AN", "AI", "AO", "AP"}
- for i, v := range e.Input {
- chord += keys[v-1]
- if i != len(e.Input)-1 {
- chord += "|"
- }
- }
- // Handle specials/base first
- var ok bool
- var v []string
- if e.Special != "" {
- v, ok = QMKLookup[e.Special]
- }
- if !ok && e.Base != "" {
- v, ok = QMKLookup[e.Base]
- }
- if ok {
- // Determine way to send key
- if len(v) == 1 {
- command = "PRES("
- } else {
- command = "KEYS("
- }
- }
- if ok {
- if len(v) > 1 {
- arg += "{"
- }
- // String together args
- for ii, vv := range(v) {
- arg += vv
- if ii == len(v)-1 && len(v) > 1 {
- arg += ", COMBO_END}"
- } else if ii != len(v)-1 {
- arg += ", "
- }
- }
- hash := crc64.Checksum([]byte(fmt.Sprintf("%v%v", arg, chord)), crc64.MakeTable(crc64.ECMA))
- hashStr := fmt.Sprintf("cmb_%x", hash)
- wordSpacer := strings.Repeat(" ", 42-len(arg))
- if command == "KEYS(" {
- arg = fmt.Sprintf("%v, %v %v", hashStr, wordSpacer, arg)
- } else {
- arg = fmt.Sprintf("%65v", arg)
- }
- goto Found
- }
- // Parse out word info
- if wordInfo.LRank == 0 && wordInfo.RRank == 0 {
- goto Blank
- }
- if wordInfo.LRank != 0 || wordInfo.RRank != 0 {
- if wordInfo.LRank != 0 && wordInfo.RRank != 0 {
- // Just blank the structure and recall
- left, right := e, e
- left.Trw = nil
- right.Tlw = nil
- return fmt.Sprintf("%v%v", left.toKeymap("LFT|"), right.toKeymap("RGT|"))
- }
- var word string
- if wordInfo.LRank > wordInfo.RRank {
- word = wordInfo.LWord
- } else {
- word = wordInfo.RWord
- }
- // Add in thumb
- chord = "AR|" + chord
- // generate function name
- hash := crc64.Checksum([]byte(word), crc64.MakeTable(crc64.ECMA))
- hashStr := fmt.Sprintf("str_%016X", hash)
- command = "SUBS("
- wordSpacer := strings.Repeat(" ", 40-len(word))
- arg = fmt.Sprintf("%v, %v \"%v \"", hashStr, wordSpacer, word)
- goto Found
- }
- panic(e.String())
- Found:
- chord += ","
- return fmt.Sprintf("%v%-35v%v)\n", command, chord, arg)
- Blank:
- return ""
- }
- type Entry struct {
- Input []int
- Base string
- Tlw []interface{}
- Trw []interface{}
- Special string
- }
- type Word struct {
- LWord string
- LRank float64
- RWord string
- RRank float64
- }
- func parseWords(e Entry) (ret Word) {
- if len(e.Tlw) > 0 {
- ret.LWord = e.Tlw[0].(string)
- ret.LRank= e.Tlw[1].(float64)
- }
- if len(e.Trw) > 0 {
- ret.RWord = e.Trw[0].(string)
- ret.RRank= e.Trw[1].(float64)
- }
- return ret
- }
- func (e Entry) String() (ret string) {
- ret = fmt.Sprintln("Input: ", e.Input)
- ret += fmt.Sprintln("Base: ", e.Base)
- ret += fmt.Sprintln("Left: ", e.Tlw)
- ret += fmt.Sprintln("Right: ", e.Trw)
- ret += fmt.Sprintln("Special: ", e.Special)
- return ret
- }
- var QMKLookup = map[string][]string {
- "!":[]string{"KC_LSFT", "KC_1"},
- "'":[]string{"KC_QUOT"},
- "(":[]string{"KC_LSFT", "KC_9"},
- ")":[]string{"KC_LSFT", "KC_0"},
- ",":[]string{"KC_COMM"},
- "-":[]string{"KC_MINS"},
- ".":[]string{"KC_DOT"},
- ";":[]string{"KC_SCLN"},
- "?":[]string{"KC_QUOT"},
- "a":[]string{"KC_A"},
- "b":[]string{"KC_B"},
- "c":[]string{"KC_C"},
- "d":[]string{"KC_D"},
- "e":[]string{"KC_E"},
- "f":[]string{"KC_F"},
- "g":[]string{"KC_G"},
- "h":[]string{"KC_H"},
- "i":[]string{"KC_I"},
- "j":[]string{"KC_J"},
- "k":[]string{"KC_K"},
- "l":[]string{"KC_L"},
- "m":[]string{"KC_M"},
- "n":[]string{"KC_N"},
- "o":[]string{"KC_O"},
- "p":[]string{"KC_P"},
- "q":[]string{"KC_Q"},
- "r":[]string{"KC_R"},
- "s":[]string{"KC_S"},
- "t":[]string{"KC_T"},
- "u":[]string{"KC_U"},
- "v":[]string{"KC_V"},
- "w":[]string{"KC_W"},
- "x":[]string{"KC_X"},
- "y":[]string{"KC_Y"},
- "z":[]string{"KC_Z"},
- //specials
- "bksp":[]string{"KC_BSPC"},
- "enter":[]string{"KC_ENT"},
- //"numsym":[]string{"NUM)"}, //TODO: Sticky
- //"LETTERS":[]string{"KC_SPC"},
- //symbols
- "[":[]string{"KC_LBRC"},
- "]":[]string{"KC_RBRC"},
- " ":[]string{"KC_SPC"},
- "1":[]string{"KC_1"},
- "2":[]string{"KC_2"},
- "3":[]string{"KC_3"},
- "4":[]string{"KC_4"},
- "5":[]string{"KC_5"},
- "6":[]string{"KC_6"},
- "7":[]string{"KC_7"},
- "8":[]string{"KC_8"},
- "9":[]string{"KC_9"},
- "0":[]string{"KC_0"},
- "=":[]string{"KC_EQL"},
- "Fn":[]string{"KC_NO"},
- "SPACE":[]string{"KC_SPC"},
- "Home":[]string{"KC_HOME"},
- "End":[]string{"KC_END"},
- " ":[]string{"KC_TAB"},
- " ":[]string{"KC_TAB"},
- "\t":[]string{"KC_TAB"},
- "`":[]string{"KC_GRV"},
- }