* Iterate over every line in the block defined by the two positions (Range) passed in. * If no range is given, the primary cursor will be used as the block. * * This is intended for visual block mode.
(
vimState: VimState,
cursor?: Cursor,
options: { reverse?: boolean } = { reverse: false },
)
| 207 | * This is intended for visual block mode. |
| 208 | */ |
| 209 | public static *iterateLinesInBlock( |
| 210 | vimState: VimState, |
| 211 | cursor?: Cursor, |
| 212 | options: { reverse?: boolean } = { reverse: false }, |
| 213 | ): Iterable<{ line: string; start: Position; end: Position }> { |
| 214 | const { reverse } = options; |
| 215 | |
| 216 | cursor ??= vimState.cursors[0]; |
| 217 | |
| 218 | const topLeft = visualBlockGetTopLeftPosition(cursor.start, cursor.stop); |
| 219 | const bottomRight = visualBlockGetBottomRightPosition(cursor.start, cursor.stop); |
| 220 | |
| 221 | const [itrStart, itrEnd] = reverse |
| 222 | ? [bottomRight.line, topLeft.line] |
| 223 | : [topLeft.line, bottomRight.line]; |
| 224 | |
| 225 | const runToLineEnd = vimState.desiredColumn === Number.POSITIVE_INFINITY; |
| 226 | |
| 227 | for ( |
| 228 | let lineIndex = itrStart; |
| 229 | reverse ? lineIndex >= itrEnd : lineIndex <= itrEnd; |
| 230 | reverse ? lineIndex-- : lineIndex++ |
| 231 | ) { |
| 232 | const line = vimState.document.lineAt(lineIndex).text; |
| 233 | const endCharacter = runToLineEnd |
| 234 | ? line.length + 1 |
| 235 | : Math.min(line.length, bottomRight.character + 1); |
| 236 | |
| 237 | yield { |
| 238 | line: line.substring(topLeft.character, endCharacter), |
| 239 | start: new Position(lineIndex, topLeft.character), |
| 240 | end: new Position(lineIndex, endCharacter), |
| 241 | }; |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | /** |
| 246 | * Iterates through words on the same line, starting from the current position. |