diff --git a/src/patches/index.ts b/src/patches/index.ts index 9df6c879..671386ae 100644 --- a/src/patches/index.ts +++ b/src/patches/index.ts @@ -72,6 +72,7 @@ import { writeScrollEscapeSequenceFilter } from './scrollEscapeSequenceFilter'; import { writeWorktreeMode } from './worktreeMode'; import { writeAllowCustomAgentModels } from './allowCustomAgentModels'; import { writeVoiceMode } from './voiceMode'; +import { writeKeybindingImmediateCommands } from './keybindingImmediateCommands'; import { restoreNativeBinaryFromBackup, restoreClijsFromBackup, @@ -173,6 +174,13 @@ const PATCH_DEFINITIONS = [ group: PatchGroup.ALWAYS_APPLIED, description: `Statusline updates will be properly throttled instead of queued (or debounced)`, }, + { + id: 'fix-keybinding-immediate-commands', + name: 'Fix keybinding immediate commands', + group: PatchGroup.ALWAYS_APPLIED, + description: + 'Keybinding-triggered local slash commands (command:copy etc.) execute instantly instead of going through the model', + }, // Misc Configurable { id: 'model-customizations', @@ -655,6 +663,9 @@ export const applyCustomization = async ( ), condition: config.settings.misc?.statuslineThrottleMs != null, }, + 'fix-keybinding-immediate-commands': { + fn: c => writeKeybindingImmediateCommands(c), + }, // Misc Configurable 'patches-applied-indication': { fn: c => diff --git a/src/patches/keybindingImmediateCommands.ts b/src/patches/keybindingImmediateCommands.ts new file mode 100644 index 00000000..c6671cbf --- /dev/null +++ b/src/patches/keybindingImmediateCommands.ts @@ -0,0 +1,37 @@ +import { showDiff } from './index'; +import { debug } from '../utils'; + +export const writeKeybindingImmediateCommands = ( + oldFile: string +): string | null => { + const pattern = + /([,;{}])([$\w]+)=([$\w]+)\.isActive&&\(([$\w]+)\?\.immediate\|\|([$\w]+)\?\.fromKeybinding\)/; + + const alreadyPatchedPattern = + /[,;{}][$\w]+=[$\w]+\?\.immediate\|\|[$\w]+\?\.fromKeybinding/; + + const match = oldFile.match(pattern); + if (!match || match.index === undefined) { + if (alreadyPatchedPattern.test(oldFile)) { + return oldFile; + } + debug( + 'patch: keybindingImmediateCommands: failed to find queryGuard.isActive && immediate/fromKeybinding pattern' + ); + return null; + } + + const [fullMatch, delimiter, resultVar, , commandVar, optionsVar] = match; + + const replacement = `${delimiter}${resultVar}=${commandVar}?.immediate||${optionsVar}?.fromKeybinding`; + + const startIndex = match.index; + const endIndex = startIndex + fullMatch.length; + + const newFile = + oldFile.slice(0, startIndex) + replacement + oldFile.slice(endIndex); + + showDiff(oldFile, newFile, replacement, startIndex, endIndex); + + return newFile; +};