MCPcopy Index your code
hub / github.com/codeaashu/claude-code / shiftSelectionForFollow

Function shiftSelectionForFollow

src/ink/selection.ts:625–674  ·  view source on GitHub ↗
(
  s: SelectionState,
  dRow: number,
  minRow: number,
  maxRow: number,
)

Source from the content-addressed store, hash-verified

623 * notifySelectionChange (recursion), must fire listeners directly.
624 */
625export function shiftSelectionForFollow(
626 s: SelectionState,
627 dRow: number,
628 minRow: number,
629 maxRow: number,
630): boolean {
631 if (!s.anchor) return false
632 // Mirror shiftSelection: compute raw (unclamped) positions from virtual
633 // if set, else current. This handles BOTH the update path (virtual already
634 // set from a prior keyboard scroll) AND the initialize path (first clamp
635 // happens HERE via follow-scroll, no prior keyboard scroll). Without the
636 // initialize path, follow-scroll-first leaves virtual undefined even
637 // though the clamp below occurred → a later PgUp computes debt from the
638 // clamped row instead of the true pre-clamp row and never pops the
639 // accumulator — getSelectedText double-counts the off-screen rows.
640 const rawAnchor = (s.virtualAnchorRow ?? s.anchor.row) + dRow
641 const rawFocus = s.focus
642 ? (s.virtualFocusRow ?? s.focus.row) + dRow
643 : undefined
644 if (rawAnchor < minRow && rawFocus !== undefined && rawFocus < minRow) {
645 clearSelection(s)
646 return true
647 }
648 // Clamp from raw, not p.row+dRow — so a virtual position coming back
649 // in-bounds lands at the TRUE position, not the stale clamped one.
650 s.anchor = { col: s.anchor.col, row: clamp(rawAnchor, minRow, maxRow) }
651 if (s.focus && rawFocus !== undefined) {
652 s.focus = { col: s.focus.col, row: clamp(rawFocus, minRow, maxRow) }
653 }
654 s.virtualAnchorRow =
655 rawAnchor < minRow || rawAnchor > maxRow ? rawAnchor : undefined
656 s.virtualFocusRow =
657 rawFocus !== undefined && (rawFocus < minRow || rawFocus > maxRow)
658 ? rawFocus
659 : undefined
660 // anchorSpan not virtual-tracked (word/line extend, irrelevant to
661 // keyboard-scroll round-trip) — plain clamp from current row.
662 if (s.anchorSpan) {
663 const shift = (p: Point): Point => ({
664 col: p.col,
665 row: clamp(p.row + dRow, minRow, maxRow),
666 })
667 s.anchorSpan = {
668 lo: shift(s.anchorSpan.lo),
669 hi: shift(s.anchorSpan.hi),
670 kind: s.anchorSpan.kind,
671 }
672 }
673 return false
674}
675
676export function hasSelection(s: SelectionState): boolean {
677 return s.anchor !== null && s.focus !== null

Callers 1

onRenderMethod · 0.85

Calls 3

clearSelectionFunction · 0.85
clampFunction · 0.85
shiftFunction · 0.85

Tested by

no test coverage detected