(count: number, ctx: OperatorContext)
| 220 | * Execute toggle case (~ command). |
| 221 | */ |
| 222 | export function executeToggleCase(count: number, ctx: OperatorContext): void { |
| 223 | const startOffset = ctx.cursor.offset |
| 224 | |
| 225 | if (startOffset >= ctx.text.length) return |
| 226 | |
| 227 | let newText = ctx.text |
| 228 | let offset = startOffset |
| 229 | let toggled = 0 |
| 230 | |
| 231 | while (offset < newText.length && toggled < count) { |
| 232 | const grapheme = firstGrapheme(newText.slice(offset)) |
| 233 | const graphemeLen = grapheme.length |
| 234 | |
| 235 | const toggledGrapheme = |
| 236 | grapheme === grapheme.toUpperCase() |
| 237 | ? grapheme.toLowerCase() |
| 238 | : grapheme.toUpperCase() |
| 239 | |
| 240 | newText = |
| 241 | newText.slice(0, offset) + |
| 242 | toggledGrapheme + |
| 243 | newText.slice(offset + graphemeLen) |
| 244 | offset += toggledGrapheme.length |
| 245 | toggled++ |
| 246 | } |
| 247 | |
| 248 | ctx.setText(newText) |
| 249 | // Cursor moves to position after the last toggled character |
| 250 | // At end of line, cursor can be at the "end" position |
| 251 | ctx.setOffset(offset) |
| 252 | ctx.recordChange({ type: 'toggleCase', count }) |
| 253 | } |
| 254 | |
| 255 | /** |
| 256 | * Execute join lines (J command). |
no test coverage detected