The definition of a bug is that its behaviour is not as designed. I’m telling you that it’s a bug as a warning that it is likely to get fixed, so that it does work as designed in the future. The one-shot key is designed to stay in effect until the event that triggers its release is done being processed by Kaleidoscope, so if it was behaving as designed, it would not be (virtually) released until after the macro had finished playing.
That’s not the behaviour that you want, and that’s fair. I encourage you to submit an issue to the Kaleidoscope GitHub repository requesting the change, so that it can be discussed by other interested parties. Unsurprisingly, I disagree with you about what it should do (I’m the one who most recently redesigned both the Macros and OneShot plugins), but this is a matter of what is most sensible, not a matter of “right” and “wrong”. Macros can be used for other purposes than just typing, so it really isn’t that clear whether OneShot should apply to keys or characters. One downside to the latter is that is substantially complicates the code.
I have now looked into the cause, and can reproduce the bug (or would-be feature, if you will) in the interaction between DynamicMacros and OneShot. While I still haven’t found the cause, I can tell that OneShot is releasing the one-shot modifier key, curiously, after the release event of the first virtual key in the macro sequence. If OneShot was simply treating this as a “normal” key tap, it would release the modifier after the press event, not the release. It’s clear that this bug in plugin-order dependent (there’s no actual salient difference between the two Macros plugins; whether or not it happens depends on whether OneShot comes before or after them in KALEIDOSCOPE_INIT_PLUGINS()
). For right now, you can just move OneShot after Macros, and you’ll get what you’re looking for. However, I do have a fix for the bug, and once I’ve determined the cause, I’ll be submitting it as a PR, which will cause it to stop working the way you want.
However, it has occurred to me that you do not need to employ a custom ShiftBlocker plugin to get what you want. While OneShot doesn’t know about Macros, or vice versa, your sketch knows about both, so you can write your macros like this:
const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) {
if (keyToggledOn(event.state)) {
switch (macro_id) {
case MACRO_QU:
Macros.tap(Key_Q);
OneShot.cancel();
event.key = Key_U;
return MACRO_NONE;
case MACRO_TABLE:
Macros.tap(Key_T);
OneShot.cancel();
return MACRO(T(A), T(B), T(L), T(E));
default:
break;
}
}
return MACRO_NONE;
}
This should do exactly what you want, even after the bug gets fixed, and should have been the first thing I suggested.