(lines: readonly string[], selection: EditorSelection)
| 99 | * @returns Edit result with updated lines and cursor |
| 100 | */ |
| 101 | export function deleteRange(lines: readonly string[], selection: EditorSelection): EditResult { |
| 102 | const newLines = [...lines]; |
| 103 | |
| 104 | // Normalize selection (anchor before active) |
| 105 | const [start, end] = normalizeSelection(selection); |
| 106 | |
| 107 | // Clamp to valid positions |
| 108 | const startRow = Math.max(0, Math.min(start.line, newLines.length - 1)); |
| 109 | const endRow = Math.max(0, Math.min(end.line, newLines.length - 1)); |
| 110 | |
| 111 | const startLine = newLines[startRow] ?? ""; |
| 112 | const endLine = newLines[endRow] ?? ""; |
| 113 | |
| 114 | const startCol = Math.max(0, Math.min(start.column, startLine.length)); |
| 115 | const endCol = Math.max(0, Math.min(end.column, endLine.length)); |
| 116 | |
| 117 | // Same line |
| 118 | if (startRow === endRow) { |
| 119 | newLines[startRow] = startLine.slice(0, startCol) + startLine.slice(endCol); |
| 120 | return Object.freeze({ |
| 121 | lines: Object.freeze(newLines), |
| 122 | cursor: { line: startRow, column: startCol }, |
| 123 | selection: null, |
| 124 | }); |
| 125 | } |
| 126 | |
| 127 | // Multi-line delete |
| 128 | const newLine = startLine.slice(0, startCol) + endLine.slice(endCol); |
| 129 | newLines.splice(startRow, endRow - startRow + 1, newLine); |
| 130 | |
| 131 | return Object.freeze({ |
| 132 | lines: Object.freeze(newLines), |
| 133 | cursor: { line: startRow, column: startCol }, |
| 134 | selection: null, |
| 135 | }); |
| 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Delete character before cursor (backspace). |
no test coverage detected