Repository: evan-liu/karabiner.ts
Pull request #70 (2023-05-08 07:34:22)

✨ Add modifiers to simlayer (default to optionalAny)


Patch:
diff --git a/src/config/simlayer.ts b/src/config/simlayer.ts
index 302e238..a0bbd3b 100644
--- a/src/config/simlayer.ts
+++ b/src/config/simlayer.ts
@@ -1,12 +1,18 @@
 import { BasicRuleBuilder } from './rule'
 import { buildCondition, ifVar } from './condition'
-import { Rule, ToVariable } from '../karabiner/karabiner-config'
+import { FromEvent, Rule, ToVariable } from '../karabiner/karabiner-config'
 import { toArray } from '../utils/to-array'
 import { getKeyWithAlias } from '../utils/key-alias'
 import { toSetVar } from './to'
 import { FromKeyCode } from '../karabiner/key-code'
 import { LayerKeyCode, LayerKeyParam, layerToggleManipulator } from './layer'
 import { BuildContext } from '../utils/build-context'
+import {
+  FromModifierOverloadParam,
+  FromOptionalModifierParam,
+  parseFromModifierOverload,
+} from '../utils/from-modifier-overload'
+import { FromModifierParam } from './modifier'
 
 export const defaultSimlayerParameters = {
   'simlayer.threshold_milliseconds': 200,
@@ -27,6 +33,7 @@ export class SimlayerRuleBuilder extends BasicRuleBuilder {
   protected readonly keys: LayerKeyCode[]
   protected readonly layerCondition = ifVar(this.varName, this.onValue)
   protected readonly sharedLayerKeys: LayerKeyCode[] = []
+  protected layerModifiers: FromEvent['modifiers'] = { optional: ['any'] }
 
   constructor(
     key: LayerKeyParam | LayerKeyParam[],
@@ -40,6 +47,24 @@ export class SimlayerRuleBuilder extends BasicRuleBuilder {
     this.condition(this.layerCondition)
   }
 
+  /** Set the simlayer modifiers. Default optionalAny. Set to null to remove. */
+  public modifiers(
+    mandatoryModifiers?: FromModifierOverloadParam,
+    optionalModifiers?: FromModifierParam,
+  ): this
+  /** Set the simlayer modifiers to { optional: [...]} (default optionalAny) */
+  public modifiers(modifiers: FromOptionalModifierParam): this
+  public modifiers(
+    mandatoryModifiers?: FromModifierOverloadParam,
+    optionalModifiers?: FromModifierParam,
+  ): this {
+    this.layerModifiers =
+      mandatoryModifiers || optionalModifiers
+        ? parseFromModifierOverload(mandatoryModifiers, optionalModifiers)
+        : undefined
+    return this
+  }
+
   /** Enable layer with the same variable and manipulators with this simlayer */
   public enableLayer(...key: LayerKeyParam[]): this {
     key
@@ -89,6 +114,13 @@ export class SimlayerRuleBuilder extends BasicRuleBuilder {
         )
       }
 
+      if (this.layerModifiers) {
+        v.from.modifiers = {
+          ...v.from.modifiers,
+          ...this.layerModifiers,
+        }
+      }
+
       for (const layerKey of this.keys) {
         rule.manipulators.push({
           type: 'basic',
@@ -105,6 +137,7 @@ export class SimlayerRuleBuilder extends BasicRuleBuilder {
               key_up_when: 'any',
               to_after_key_up: [setVarOff],
             },
+            modifiers: this.layerModifiers,
           },
           conditions,
         })


Test patch:
diff --git a/src/config/simlayer.test.ts b/src/config/simlayer.test.ts
index 65a1fb7..612d009 100644
--- a/src/config/simlayer.test.ts
+++ b/src/config/simlayer.test.ts
@@ -32,6 +32,7 @@ test('simlayer()', () => {
         key_up_when: 'any',
         to_after_key_up: [toSetVar('b-mode', false)],
       },
+      modifiers: { optional: ['any'] },
     },
   })
 
@@ -39,6 +40,7 @@ test('simlayer()', () => {
   expect(manipulators[0].conditions).toEqual([
     { type: 'variable_if', name: 'b-mode', value: true },
   ])
+  expect(manipulators[0].from.modifiers).toEqual({ optional: ['any'] })
 })
 
 test('simlayer() with multiple key', () => {
@@ -104,3 +106,26 @@ test('simlayer().enableLayer()', () => {
     conditions: [{ type: 'variable_if', name: 'd', value: 1 }],
   })
 })
+
+test('simlayer().modifiers()', () => {
+  expect(
+    simlayer('a', 'b')
+      .modifiers('⌘')
+      .manipulators([map(1).to(2)])
+      .build().manipulators[1].from?.modifiers,
+  ).toEqual({ mandatory: ['command'] })
+
+  expect(
+    simlayer('a', 'b')
+      .modifiers({ optional: '⇪' })
+      .manipulators([map(1).to(2)])
+      .build().manipulators[1].from?.modifiers,
+  ).toEqual({ optional: ['caps_lock'] })
+
+  expect(
+    simlayer('a', 'b')
+      .modifiers(null)
+      .manipulators([map(1).to(2)])
+      .build().manipulators[1].from?.modifiers,
+  ).toBeUndefined()
+})