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

Function wordBoundsAt

src/ink/selection.ts:162–224  ·  view source on GitHub ↗

* Find the bounds of the same-class character run at (col, row). Returns * null if the click is out of bounds or lands on a noSelect cell. Used by * selectWordAt (initial double-click) and extendWordSelection (drag).

(
  screen: Screen,
  col: number,
  row: number,
)

Source from the content-addressed store, hash-verified

160 * selectWordAt (initial double-click) and extendWordSelection (drag).
161 */
162function wordBoundsAt(
163 screen: Screen,
164 col: number,
165 row: number,
166): { lo: number; hi: number } | null {
167 if (row < 0 || row >= screen.height) return null
168 const width = screen.width
169 const noSelect = screen.noSelect
170 const rowOff = row * width
171
172 // If the click landed on the spacer tail of a wide char, step back to
173 // the head so the class check sees the actual grapheme.
174 let c = col
175 if (c > 0) {
176 const cell = cellAt(screen, c, row)
177 if (cell && cell.width === CellWidth.SpacerTail) c -= 1
178 }
179 if (c < 0 || c >= width || noSelect[rowOff + c] === 1) return null
180
181 const startCell = cellAt(screen, c, row)
182 if (!startCell) return null
183 const cls = charClass(startCell.char)
184
185 // Expand left: include cells of the same class, stop at noSelect or
186 // class change. SpacerTail cells are stepped over (the wide-char head
187 // at the preceding column determines the class).
188 let lo = c
189 while (lo > 0) {
190 const prev = lo - 1
191 if (noSelect[rowOff + prev] === 1) break
192 const pc = cellAt(screen, prev, row)
193 if (!pc) break
194 if (pc.width === CellWidth.SpacerTail) {
195 // Step over the spacer to the wide-char head
196 if (prev === 0 || noSelect[rowOff + prev - 1] === 1) break
197 const head = cellAt(screen, prev - 1, row)
198 if (!head || charClass(head.char) !== cls) break
199 lo = prev - 1
200 continue
201 }
202 if (charClass(pc.char) !== cls) break
203 lo = prev
204 }
205
206 // Expand right: same logic, skipping spacer tails.
207 let hi = c
208 while (hi < width - 1) {
209 const next = hi + 1
210 if (noSelect[rowOff + next] === 1) break
211 const nc = cellAt(screen, next, row)
212 if (!nc) break
213 if (nc.width === CellWidth.SpacerTail) {
214 // Include the spacer tail in the selection range (it belongs to
215 // the wide char at hi) and continue past it.
216 hi = next
217 continue
218 }
219 if (charClass(nc.char) !== cls) break

Callers 2

selectWordAtFunction · 0.85
extendSelectionFunction · 0.85

Calls 2

cellAtFunction · 0.85
charClassFunction · 0.85

Tested by

no test coverage detected