( text: string, offset: number, scope: 'i' | 'a', obj: string )
| 1294 | * and `i(`/`a(` etc. (brackets) around `offset`. `to` is exclusive. Returns |
| 1295 | * null if the object isn't found (e.g. unbalanced brackets). */ |
| 1296 | export function textObjectRange( |
| 1297 | text: string, |
| 1298 | offset: number, |
| 1299 | scope: 'i' | 'a', |
| 1300 | obj: string |
| 1301 | ): { from: number; to: number } | null { |
| 1302 | const n = text.length |
| 1303 | if (n === 0) return null |
| 1304 | const off = Math.max(0, Math.min(offset, n - 1)) |
| 1305 | |
| 1306 | if (obj === 'w') { |
| 1307 | const cls = charClass(text[off]) |
| 1308 | let from = off |
| 1309 | let to = off + 1 |
| 1310 | while (from > 0 && charClass(text[from - 1]) === cls) from-- |
| 1311 | while (to < n && charClass(text[to]) === cls) to++ |
| 1312 | if (scope === 'a') { |
| 1313 | const afterEnd = to |
| 1314 | while (to < n && charClass(text[to]) === 0) to++ |
| 1315 | if (to === afterEnd) while (from > 0 && charClass(text[from - 1]) === 0) from-- |
| 1316 | } |
| 1317 | return { from, to } |
| 1318 | } |
| 1319 | |
| 1320 | if (obj === '"' || obj === "'" || obj === '`') { |
| 1321 | let open = -1 |
| 1322 | for (let i = off; i >= 0; i--) { |
| 1323 | if (text[i] === obj) { |
| 1324 | open = i |
| 1325 | break |
| 1326 | } |
| 1327 | } |
| 1328 | if (open === -1) { |
| 1329 | for (let i = off; i < n; i++) { |
| 1330 | if (text[i] === obj) { |
| 1331 | open = i |
| 1332 | break |
| 1333 | } |
| 1334 | } |
| 1335 | } |
| 1336 | if (open === -1) return null |
| 1337 | let close = -1 |
| 1338 | for (let i = open + 1; i < n; i++) { |
| 1339 | if (text[i] === obj) { |
| 1340 | close = i |
| 1341 | break |
| 1342 | } |
| 1343 | } |
| 1344 | if (close === -1) return null |
| 1345 | return scope === 'i' ? { from: open + 1, to: close } : { from: open, to: close + 1 } |
| 1346 | } |
| 1347 | |
| 1348 | const OPENERS: Record<string, string> = { '(': ')', '[': ']', '{': '}' } |
| 1349 | const CLOSERS: Record<string, string> = { ')': '(', ']': '[', '}': '{' } |
| 1350 | let openCh: string |
| 1351 | let closeCh: string |
| 1352 | if (OPENERS[obj]) { |
| 1353 | openCh = obj |
no test coverage detected