( state: TextBufferState, action: TextBufferAction, )
| 984 | | { type: 'vim_escape_insert_mode' }; |
| 985 | |
| 986 | export function textBufferReducer( |
| 987 | state: TextBufferState, |
| 988 | action: TextBufferAction, |
| 989 | ): TextBufferState { |
| 990 | const pushUndoLocal = pushUndo; |
| 991 | |
| 992 | const currentLine = (r: number): string => state.lines[r] ?? ''; |
| 993 | const currentLineLen = (r: number): number => cpLen(currentLine(r)); |
| 994 | |
| 995 | switch (action.type) { |
| 996 | case 'set_text': { |
| 997 | let nextState = state; |
| 998 | if (action.pushToUndo !== false) { |
| 999 | nextState = pushUndoLocal(state); |
| 1000 | } |
| 1001 | const newContentLines = action.payload |
| 1002 | .replace(/\r\n?/g, '\n') |
| 1003 | .split('\n'); |
| 1004 | const lines = newContentLines.length === 0 ? [''] : newContentLines; |
| 1005 | const lastNewLineIndex = lines.length - 1; |
| 1006 | return { |
| 1007 | ...nextState, |
| 1008 | lines, |
| 1009 | cursorRow: lastNewLineIndex, |
| 1010 | cursorCol: cpLen(lines[lastNewLineIndex] ?? ''), |
| 1011 | preferredCol: null, |
| 1012 | }; |
| 1013 | } |
| 1014 | |
| 1015 | case 'insert': { |
| 1016 | const nextState = pushUndoLocal(state); |
| 1017 | const newLines = [...nextState.lines]; |
| 1018 | let newCursorRow = nextState.cursorRow; |
| 1019 | let newCursorCol = nextState.cursorCol; |
| 1020 | |
| 1021 | const currentLine = (r: number) => newLines[r] ?? ''; |
| 1022 | |
| 1023 | const str = stripUnsafeCharacters( |
| 1024 | action.payload.replace(/\r\n/g, '\n').replace(/\r/g, '\n'), |
| 1025 | ); |
| 1026 | const parts = str.split('\n'); |
| 1027 | const lineContent = currentLine(newCursorRow); |
| 1028 | const before = cpSlice(lineContent, 0, newCursorCol); |
| 1029 | const after = cpSlice(lineContent, newCursorCol); |
| 1030 | |
| 1031 | if (parts.length > 1) { |
| 1032 | newLines[newCursorRow] = before + parts[0]; |
| 1033 | const remainingParts = parts.slice(1); |
| 1034 | const lastPartOriginal = remainingParts.pop() ?? ''; |
| 1035 | newLines.splice(newCursorRow + 1, 0, ...remainingParts); |
| 1036 | newLines.splice( |
| 1037 | newCursorRow + parts.length - 1, |
| 1038 | 0, |
| 1039 | lastPartOriginal + after, |
| 1040 | ); |
| 1041 | newCursorRow = newCursorRow + parts.length - 1; |
| 1042 | newCursorCol = cpLen(lastPartOriginal); |
| 1043 | } else { |
no test coverage detected