import { Cursor } from '../Cursor'; import { Operations } from '../Operations'; import { TextArea } from '../TextArea'; export class Intent { public readonly textArea: TextArea; public readonly operations: Operations; public readonly size: number; public readonly str: string; private intentReg: RegExp; constructor(size: number, textArea: TextArea, operations: Operations) { this.textArea = textArea; this.operations = operations; this.size = size; this.intentReg = /^\s*/; this.str = ''; for (let i = 0; i < size; i += 1) this.str += ' '; } private lineIntent(cursor: Cursor): string { const lines = this.textArea.cursorLines(cursor); const selection = this.textArea.selection(lines); const match = selection.match(this.intentReg); if (!match) return ''; return match[0]; } public moveForward(cursor: Cursor): Cursor { const linesCursor = this.textArea.cursorLines(cursor); const selection = this.textArea.selection(linesCursor); const lines = selection.split('\n'); const intentLines = lines.map((line) => `${this.str}${line}`); this.operations.insert(linesCursor, intentLines.join('\n')); const addedIntentLength = lines.length * this.str.length; return new Cursor( cursor.start === linesCursor.start ? cursor.start : cursor.start + this.str.length, cursor.end + addedIntentLength, cursor.direction ); } public moveBackward(cursor: Cursor): Cursor { const linesCursor = this.textArea.cursorLines(cursor); const selection = this.textArea.selection(linesCursor); const lines = selection.split('\n'); const intentLines = lines.map((line) => { if (line.startsWith(this.str)) return line.substring(this.str.length); return line.replace(this.intentReg, ''); }); const intentCursor = this.operations.insert(linesCursor, intentLines.join('\n')); const firstLineTrimLength = lines[0].length - intentLines[0].length; const lastLine = this.textArea.cursorLines( new Cursor(intentCursor.end, intentCursor.end, 'none') ); const start = Math.max(cursor.start - firstLineTrimLength, linesCursor.start); const trimmedContentLength = linesCursor.length - intentCursor.length; const end = Math.max(lastLine.start, cursor.end - trimmedContentLength); return new Cursor(start, end, cursor.direction); } public addNewLine(cursor: Cursor): Cursor { const lineIntent = this.lineIntent(cursor); const line = `\n${lineIntent}`; const insertCursor = this.operations.insert(cursor, line); return new Cursor(insertCursor.end, insertCursor.end, 'none'); } public addNextLine(cursor: Cursor): Cursor { const lineIntent = this.lineIntent(cursor); const line = `\n${lineIntent}`; const currentLine = this.textArea.cursorLines(cursor); const lineCursor = new Cursor(currentLine.end, currentLine.end, 'none'); const insertCursor = this.operations.insert(lineCursor, line); return new Cursor(insertCursor.end, insertCursor.end, 'none'); } public addPreviousLine(cursor: Cursor): Cursor { const lineIntent = this.lineIntent(cursor); const line = `\n${lineIntent}`; const prevLine = this.textArea.prevLine(cursor); const insertIndex = prevLine?.end ?? 0; const lineCursor = new Cursor(insertIndex, insertIndex, 'none'); const insertCursor = this.operations.insert(lineCursor, line); return new Cursor(insertCursor.end, insertCursor.end, 'none'); } }