* Bracket `fn()` with modifier press/release. `pressed` tracks which presses * actually landed, so a mid-press throw only releases what was pressed — no * stuck modifiers. The finally covers both press-phase and fn() throws. * * Caller must already be inside drainRunLoop() — key() dispatches to
( input: Input, mods: string[], fn: () => Promise<T>, )
| 148 | * main queue and needs the pump to resolve. |
| 149 | */ |
| 150 | async function withModifiers<T>( |
| 151 | input: Input, |
| 152 | mods: string[], |
| 153 | fn: () => Promise<T>, |
| 154 | ): Promise<T> { |
| 155 | const pressed: string[] = [] |
| 156 | try { |
| 157 | for (const m of mods) { |
| 158 | await input.key(m, 'press') |
| 159 | pressed.push(m) |
| 160 | } |
| 161 | return await fn() |
| 162 | } finally { |
| 163 | await releasePressed(input, pressed) |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | /** |
| 168 | * Port of Cowork's `typeViaClipboard`. Sequence: |
no test coverage detected