aboutsummaryrefslogtreecommitdiff
path: root/src/shared/utils/keys.js
blob: 8a86dfbbaba336f08f91e2f0e5c6f2d62e733b56 (plain) (blame)
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
const modifierdKeyName = (name) => {
  if (name.length === 1) {
    return name;
  } else if (name === 'Escape') {
    return 'Esc';
  }
  return name;
};

const fromKeyboardEvent = (e) => {
  let key = modifierdKeyName(e.key);
  let shift = e.shiftKey;
  if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) {
    // make shift false for symbols to enable key bindings by symbold keys.
    // But this limits key bindings by symbol keys with Shift (such as Shift+$>.
    shift = false;
  }

  return {
    key: modifierdKeyName(e.key),
    repeat: e.repeat,
    shiftKey: shift,
    ctrlKey: e.ctrlKey,
    altKey: e.altKey,
    metaKey: e.metaKey,
  };
};

const fromMapKey = (key) => {
  if (key.startsWith('<') && key.endsWith('>')) {
    let inner = key.slice(1, -1);
    let shift = inner.includes('S-');
    let base = inner.slice(inner.lastIndexOf('-') + 1);
    if (shift && base.length === 1) {
      base = base.toUpperCase();
    } else if (!shift && base.length === 1) {
      base = base.toLowerCase();
    }
    return {
      key: base,
      shiftKey: inner.includes('S-'),
      ctrlKey: inner.includes('C-'),
      altKey: inner.includes('A-'),
      metaKey: inner.includes('M-'),
    };
  }
  return {
    key: key,
    shiftKey: key.toLowerCase() !== key,
    ctrlKey: false,
    altKey: false,
    metaKey: false,
  };
};

const fromMapKeys = (keys) => {
  const fromMapKeysRecursive = (remainings, mappedKeys) => {
    if (remainings.length === 0) {
      return mappedKeys;
    }

    let nextPos = 1;
    if (remainings.startsWith('<')) {
      let ltPos = remainings.indexOf('>');
      if (ltPos > 0) {
        nextPos = ltPos + 1;
      }
    }

    return fromMapKeysRecursive(
      remainings.slice(nextPos),
      mappedKeys.concat([fromMapKey(remainings.slice(0, nextPos))])
    );
  };

  return fromMapKeysRecursive(keys, []);
};

const equals = (e1, e2) => {
  return e1.key === e2.key &&
    e1.ctrlKey === e2.ctrlKey &&
    e1.metaKey === e2.metaKey &&
    e1.altKey === e2.altKey &&
    e1.shiftKey === e2.shiftKey;
};

export { fromKeyboardEvent, fromMapKey, fromMapKeys, equals };