aboutsummaryrefslogtreecommitdiffhomepage
path: root/api/services/zmk/keymap.js
blob: 943262742afc6c9fe5bec40b0a40f2963c7b8a01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
const filter = require('lodash/filter')
const get = require('lodash/get')
const map = require('lodash/map')

const paramsPattern = /\((.+)\)/

function parse(code) {
  const params = filter(
    get(code.match(paramsPattern), '[1]', '')
      .split(',')
      .map(s => s.trim())
  )

  return {
    value: code.replace(paramsPattern, ''),
    params: params.map(parse)
  }
}

/**
 * Parse a key binding into a nested structure of values and parameters
 * @param {String} binding the raw bind string (e.g. `&kp LS(A)`)
 * @returns {Array}
 */
function parseKeyBinding (binding) {
  const value = binding.match(/^(&.+?)\b/)[1]
  const paramBinds = filter(binding.replace(/^&.+?\b\s*/, '').split(' '))
  const params = map(paramBinds, parse)

  return { binding, value, params }
}

function parseKeymap (keymap) {
  return Object.assign({}, keymap, {
    layers: keymap.layers.map(layer => {
      return layer.map(binding => {
        return parseKeyBinding(binding, this.sources)
      })
    })
  })
}

const { renderTable } = require('./layout')

const header = `
/*
 * Copyright (c) 2020 The ZMK Contributors
 *
 * SPDX-License-Identifier: MIT
 */


/* THIS FILE WAS GENERATED!
 *
 * This file was generated automatically. You may or may not want to
 * edit it directly.
 */

#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
#include <dt-bindings/zmk/outputs.h>

`

function generateKeymap (layout, keymap) {
  return {
    code: generateKeymapCode(layout, keymap),
    json: generateKeymapJSON(layout, keymap)
  }
}

function generateKeymapCode (layout, keymap) {
  const { layer_names: names = [] } = keymap
  const layers = keymap.layers.map((layer, i) => {
    const name = i === 0 ? 'default_layer' : `layer_${names[i] || i}`
    const rendered = renderTable(layout, layer, {
      linePrefix: '',
      columnSeparator: ' '
    })

    return `
        ${name} {
            bindings = <
${rendered}
            >;
        };
`
  })

  const keymapOut = `${header}
/ {
    keymap {
        compatible = "zmk,keymap";

${layers.join('')}
    };
};
`

  return keymapOut
}

function generateKeymapJSON (layout, keymap) {
  const base = JSON.stringify(Object.assign({}, keymap, { layers: null }), null, 2)
  const layers = keymap.layers.map(layer => {
    const rendered = renderTable(layout, layer, {
      useQuotes: true,
      linePrefix: '      '
    })

    return `[\n${rendered}\n    ]`
  })

  return base.replace('"layers": null', `"layers": [\n    ${layers.join(', ')}\n  ]`)
}

module.exports = {
  parseKeymap,
  generateKeymap
}