(screen: VirtualScreen, targetX: number, targetY: number)
| 691 | } |
| 692 | |
| 693 | function moveCursorTo(screen: VirtualScreen, targetX: number, targetY: number) { |
| 694 | screen.txn(prev => { |
| 695 | const dx = targetX - prev.x |
| 696 | const dy = targetY - prev.y |
| 697 | const inPendingWrap = prev.x >= screen.viewportWidth |
| 698 | |
| 699 | // If we're in pending wrap state (cursor.x >= width), use CR |
| 700 | // to reset to column 0 on the current line without advancing |
| 701 | // to the next line, then issue the cursor movement. |
| 702 | if (inPendingWrap) { |
| 703 | return [ |
| 704 | [CARRIAGE_RETURN, { type: 'cursorMove', x: targetX, y: dy }], |
| 705 | { dx, dy }, |
| 706 | ] |
| 707 | } |
| 708 | |
| 709 | // When moving to a different line, use carriage return (\r) to reset to |
| 710 | // column 0 first, then cursor move. |
| 711 | if (dy !== 0) { |
| 712 | return [ |
| 713 | [CARRIAGE_RETURN, { type: 'cursorMove', x: targetX, y: dy }], |
| 714 | { dx, dy }, |
| 715 | ] |
| 716 | } |
| 717 | |
| 718 | // Standard same-line cursor move |
| 719 | return [[{ type: 'cursorMove', x: dx, y: dy }], { dx, dy }] |
| 720 | }) |
| 721 | } |
| 722 | |
| 723 | /** |
| 724 | * Identify emoji where the terminal's wcwidth may disagree with Unicode. |
no test coverage detected