(
state: { type: 'g'; count: number },
input: string,
ctx: TransitionContext,
)
| 383 | } |
| 384 | |
| 385 | function fromG( |
| 386 | state: { type: 'g'; count: number }, |
| 387 | input: string, |
| 388 | ctx: TransitionContext, |
| 389 | ): TransitionResult { |
| 390 | if (input === 'j' || input === 'k') { |
| 391 | return { |
| 392 | execute: () => { |
| 393 | const target = resolveMotion(`g${input}`, ctx.cursor, state.count) |
| 394 | ctx.setOffset(target.offset) |
| 395 | }, |
| 396 | } |
| 397 | } |
| 398 | if (input === 'g') { |
| 399 | // If count provided (e.g., 5gg), go to that line. Otherwise go to first line. |
| 400 | if (state.count > 1) { |
| 401 | return { |
| 402 | execute: () => { |
| 403 | const lines = ctx.text.split('\n') |
| 404 | const targetLine = Math.min(state.count - 1, lines.length - 1) |
| 405 | let offset = 0 |
| 406 | for (let i = 0; i < targetLine; i++) { |
| 407 | offset += (lines[i]?.length ?? 0) + 1 // +1 for newline |
| 408 | } |
| 409 | ctx.setOffset(offset) |
| 410 | }, |
| 411 | } |
| 412 | } |
| 413 | return { |
| 414 | execute: () => ctx.setOffset(ctx.cursor.startOfFirstLine().offset), |
| 415 | } |
| 416 | } |
| 417 | return { next: { type: 'idle' } } |
| 418 | } |
| 419 | |
| 420 | function fromOperatorG( |
| 421 | state: { type: 'operatorG'; op: Operator; count: number }, |
no test coverage detected