| 1489 | // --- End of reducer logic --- |
| 1490 | |
| 1491 | export function useTextBuffer({ |
| 1492 | initialText = '', |
| 1493 | initialCursorOffset = 0, |
| 1494 | viewport, |
| 1495 | stdin, |
| 1496 | setRawMode, |
| 1497 | onChange, |
| 1498 | isValidPath, |
| 1499 | shellModeActive = false, |
| 1500 | }: UseTextBufferProps): TextBuffer { |
| 1501 | const initialState = useMemo((): TextBufferState => { |
| 1502 | const lines = initialText.split('\n'); |
| 1503 | const [initialCursorRow, initialCursorCol] = calculateInitialCursorPosition( |
| 1504 | lines.length === 0 ? [''] : lines, |
| 1505 | initialCursorOffset, |
| 1506 | ); |
| 1507 | return { |
| 1508 | lines: lines.length === 0 ? [''] : lines, |
| 1509 | cursorRow: initialCursorRow, |
| 1510 | cursorCol: initialCursorCol, |
| 1511 | preferredCol: null, |
| 1512 | undoStack: [], |
| 1513 | redoStack: [], |
| 1514 | clipboard: null, |
| 1515 | selectionAnchor: null, |
| 1516 | viewportWidth: viewport.width, |
| 1517 | }; |
| 1518 | }, [initialText, initialCursorOffset, viewport.width]); |
| 1519 | |
| 1520 | const [state, dispatch] = useReducer(textBufferReducer, initialState); |
| 1521 | const { lines, cursorRow, cursorCol, preferredCol, selectionAnchor } = state; |
| 1522 | |
| 1523 | const text = useMemo(() => lines.join('\n'), [lines]); |
| 1524 | |
| 1525 | const visualLayout = useMemo( |
| 1526 | () => |
| 1527 | calculateVisualLayout(lines, [cursorRow, cursorCol], state.viewportWidth), |
| 1528 | [lines, cursorRow, cursorCol, state.viewportWidth], |
| 1529 | ); |
| 1530 | |
| 1531 | const { visualLines, visualCursor } = visualLayout; |
| 1532 | |
| 1533 | const [visualScrollRow, setVisualScrollRow] = useState<number>(0); |
| 1534 | |
| 1535 | useEffect(() => { |
| 1536 | if (onChange) { |
| 1537 | onChange(text); |
| 1538 | } |
| 1539 | }, [text, onChange]); |
| 1540 | |
| 1541 | useEffect(() => { |
| 1542 | dispatch({ type: 'set_viewport_width', payload: viewport.width }); |
| 1543 | }, [viewport.width]); |
| 1544 | |
| 1545 | // Update visual scroll (vertical) |
| 1546 | useEffect(() => { |
| 1547 | const { height } = viewport; |
| 1548 | let newVisualScrollRow = visualScrollRow; |