(line: string, col: number)
| 153 | |
| 154 | // Find word end within a line |
| 155 | export const findWordEndInLine = (line: string, col: number): number | null => { |
| 156 | const chars = toCodePoints(line); |
| 157 | let i = col; |
| 158 | |
| 159 | // If we're already at the end of a word (including punctuation sequences), advance to next word |
| 160 | // This includes both regular word endings and script boundaries |
| 161 | const atEndOfWordChar = |
| 162 | i < chars.length && |
| 163 | isWordCharWithCombining(chars[i]) && |
| 164 | (i + 1 >= chars.length || |
| 165 | !isWordCharWithCombining(chars[i + 1]) || |
| 166 | (isWordCharStrict(chars[i]) && |
| 167 | i + 1 < chars.length && |
| 168 | isWordCharStrict(chars[i + 1]) && |
| 169 | isDifferentScript(chars[i], chars[i + 1]))); |
| 170 | |
| 171 | const atEndOfPunctuation = |
| 172 | i < chars.length && |
| 173 | !isWordCharWithCombining(chars[i]) && |
| 174 | !isWhitespace(chars[i]) && |
| 175 | (i + 1 >= chars.length || |
| 176 | isWhitespace(chars[i + 1]) || |
| 177 | isWordCharWithCombining(chars[i + 1])); |
| 178 | |
| 179 | if (atEndOfWordChar || atEndOfPunctuation) { |
| 180 | // We're at the end of a word or punctuation sequence, move forward to find next word |
| 181 | i++; |
| 182 | // Skip whitespace to find next word or punctuation |
| 183 | while (i < chars.length && isWhitespace(chars[i])) { |
| 184 | i++; |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | // If we're not on a word character, find the next word or punctuation sequence |
| 189 | if (i < chars.length && !isWordCharWithCombining(chars[i])) { |
| 190 | // Skip whitespace to find next word or punctuation |
| 191 | while (i < chars.length && isWhitespace(chars[i])) { |
| 192 | i++; |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | // Move to end of current word (including combining marks, but stop at script boundaries) |
| 197 | let foundWord = false; |
| 198 | let lastBaseCharPos = -1; |
| 199 | |
| 200 | if (i < chars.length && isWordCharWithCombining(chars[i])) { |
| 201 | // Handle word characters |
| 202 | while (i < chars.length && isWordCharWithCombining(chars[i])) { |
| 203 | foundWord = true; |
| 204 | |
| 205 | // Track the position of the last base character (not combining mark) |
| 206 | if (isWordCharStrict(chars[i])) { |
| 207 | lastBaseCharPos = i; |
| 208 | } |
| 209 | |
| 210 | // Check if next character is from a different script (word boundary) |
| 211 | if ( |
| 212 | i + 1 < chars.length && |
no test coverage detected