diff --git a/src/config/double-tap.test.ts b/src/config/double-tap.test.ts index 786d486..37a8fdd 100644 --- a/src/config/double-tap.test.ts +++ b/src/config/double-tap.test.ts @@ -11,6 +11,7 @@ describe('mapDoubleTap()', () => { from: { key_code: '1' }, to: [{ key_code: '2' }], conditions: [{ name: 'double-tap-1', type: 'variable_if', value: 1 }], + description: '__support__manipulator', }, { type: 'basic', @@ -56,6 +57,7 @@ describe('mapDoubleTap()', () => { from: { key_code: '1' }, to: [{ key_code: '2' }], conditions: [{ name: 'double-tap-1', type: 'variable_if', value: 1 }], + description: '__support__manipulator', }, { type: 'basic', diff --git a/src/config/double-tap.ts b/src/config/double-tap.ts index 69d8f75..258d50d 100644 --- a/src/config/double-tap.ts +++ b/src/config/double-tap.ts @@ -24,6 +24,7 @@ import { FromOptionalModifierParam } from '../utils/optional-modifiers.ts' import { ifVar } from './condition.ts' import { BasicManipulatorBuilder } from './manipulator.ts' import { FromModifierParam } from './modifier.ts' +import { supportManipulator } from './support-manipulator.ts' import { toSetVar } from './to.ts' export const defaultDoubleTapParameters = { @@ -144,15 +145,15 @@ export class DoubleTapManipulatorBuilder extends BasicManipulatorBuilder { const onCondition = ifVar(varName).build() const offCondition = ifVar(varName).unless().build() - const baseManipulator: BasicManipulator = { + const baseManipulator = supportManipulator({ ...this.manipulator, - conditions: [...(this.manipulator.conditions || []), onCondition], - } + conditions: [onCondition], + }) const toggleManipulator: BasicManipulator = { ...this.manipulator, to: [toSetVar(varName, 1)], - conditions: [offCondition], + conditions: [...(this.manipulator.conditions || []), offCondition], to_delayed_action: { to_if_invoked: [ ...(this.singleTapEvent ? [this.singleTapEvent] : []), diff --git a/src/config/duo-layer.ts b/src/config/duo-layer.ts index fce3901..88607f9 100644 --- a/src/config/duo-layer.ts +++ b/src/config/duo-layer.ts @@ -17,6 +17,7 @@ import { buildCondition, ConditionBuilder, ifVar } from './condition.ts' import { LayerKeyParam } from './layer.ts' import { BasicRuleBuilder } from './rule.ts' import { mapSimultaneous } from './simultaneous.ts' +import { isSupportManipulator } from './support-manipulator.ts' import { toNotificationMessage, toRemoveNotificationMessage, @@ -143,7 +144,10 @@ export class DuoLayerRuleBuilder extends BasicRuleBuilder { if (this.leaderModeOptions) { if (!this.leaderModeOptions.sticky) { rule.manipulators.forEach( - (v) => v.type === 'basic' && (v.to = (v.to || []).concat(deactivate)), + (v) => + v.type === 'basic' && + !isSupportManipulator(v) && + (v.to = (v.to || []).concat(deactivate)), ) } rule.manipulators.push( diff --git a/src/config/layer.test.ts b/src/config/layer.test.ts index a74575b..0469ccb 100644 --- a/src/config/layer.test.ts +++ b/src/config/layer.test.ts @@ -9,6 +9,7 @@ import { import { complexModifications } from './complex-modifications' import { ifVar } from './condition' +import { mapDoubleTap } from './double-tap.ts' import { map } from './from' import { hyperLayer, layer, LayerRuleBuilder } from './layer' import { mouseMotionToScroll } from './mouse-motion-to-scroll' @@ -447,4 +448,40 @@ describe('layer() leader mode', () => { expect(manipulators[3].conditions).toEqual([ifOn]) expect(manipulators[3].to).toEqual([toOff, toLayerVarOff, remove]) }) + + test('leader() and mapDoubleTap()', () => { + const rule = layer('a') + .leaderMode({ sticky: true }) + .notification() + .manipulators([mapDoubleTap(1).to(2).singleTap(toKey(3))]) + .build() + const manipulators = rule.manipulators as BasicManipulator[] + expect(manipulators.length).toBe(5) + + const ifOn = ifVar('layer-a', 1).build() + const toOff = toSetVar('layer-a', 0) + const toLayerVarOff = toSetVar('__layer', 0) + const remove = toRemoveNotificationMessage('layer-layer-a') + + // the second tap + expect(manipulators[1].to).toEqual([{ key_code: '2' }]) + expect(manipulators[1].conditions).toEqual([ + { name: 'double-tap-1', type: 'variable_if', value: 1 }, + ]) + + // the first tap + expect(manipulators[2].to).toEqual([ + { set_variable: { name: 'double-tap-1', value: 1 } }, + ]) + expect(manipulators[2].conditions).toEqual([ + { name: 'double-tap-1', type: 'variable_unless', value: 1 }, + ifOn, + ]) + + // escape keys + expect(manipulators[3].conditions).toEqual([ifOn]) + expect(manipulators[3].to).toEqual([toOff, toLayerVarOff, remove]) + expect(manipulators[4].conditions).toEqual([ifOn]) + expect(manipulators[4].to).toEqual([toOff, toLayerVarOff, remove]) + }) }) diff --git a/src/config/layer.ts b/src/config/layer.ts index 325dfb7..7d17b79 100644 --- a/src/config/layer.ts +++ b/src/config/layer.ts @@ -37,6 +37,7 @@ import { SideModifierAlias, } from './modifier.ts' import { BasicRuleBuilder } from './rule.ts' +import { isSupportManipulator } from './support-manipulator.ts' import { toRemoveNotificationMessage, toSetVar } from './to.ts' export type LayerKeyCode = Exclude< @@ -192,7 +193,10 @@ export class LayerRuleBuilder extends BasicRuleBuilder { } if (!this.leaderModeOptions.sticky) { rule.manipulators.forEach( - (v) => v.type === 'basic' && (v.to = (v.to || []).concat(toOff)), + (v) => + v.type === 'basic' && + !isSupportManipulator(v) && + (v.to = (v.to || []).concat(toOff)), ) } rule.manipulators.push( diff --git a/src/config/rule.ts b/src/config/rule.ts index 76a3ff7..ed64d56 100644 --- a/src/config/rule.ts +++ b/src/config/rule.ts @@ -7,6 +7,7 @@ import { ManipulatorBuilder, ManipulatorMap, } from './manipulator.ts' +import { isSupportManipulator } from './support-manipulator.ts' export function rule( description: string, @@ -69,7 +70,7 @@ export class BasicRuleBuilder implements RuleBuilder { const conditions = this.conditions.map(buildCondition) rule.manipulators = rule.manipulators.map((v) => - v.type === 'basic' + v.type === 'basic' && !isSupportManipulator(v) ? { ...v, conditions: [...(v.conditions || []), ...conditions] } : { ...v }, ) diff --git a/src/config/support-manipulator.ts b/src/config/support-manipulator.ts new file mode 100644 index 0000000..f8784b6 --- /dev/null +++ b/src/config/support-manipulator.ts @@ -0,0 +1,13 @@ +import { BasicManipulator, Manipulator } from '../karabiner/karabiner-config.ts' + +const suffix = '__support__manipulator' + +/** Manipulators only to support normal manipulators. */ +export function supportManipulator(manipulator: BasicManipulator) { + manipulator.description = (manipulator.description || '') + suffix + return manipulator +} + +export function isSupportManipulator(manipulator: Manipulator) { + return (manipulator as BasicManipulator).description?.endsWith(suffix) +}