summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components/shared/multiline-editor.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/components/shared/multiline-editor.tsx')
-rw-r--r--packages/cli/src/ui/components/shared/multiline-editor.tsx98
1 files changed, 21 insertions, 77 deletions
diff --git a/packages/cli/src/ui/components/shared/multiline-editor.tsx b/packages/cli/src/ui/components/shared/multiline-editor.tsx
index c388064a..bd49efcb 100644
--- a/packages/cli/src/ui/components/shared/multiline-editor.tsx
+++ b/packages/cli/src/ui/components/shared/multiline-editor.tsx
@@ -4,10 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { TextBuffer } from './text-buffer.js';
+import { useTextBuffer } from './text-buffer.js';
import chalk from 'chalk';
import { Box, Text, useInput, useStdin, Key } from 'ink';
-import React, { useState, useCallback } from 'react';
+import React from 'react';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { Colors } from '../../colors.js';
@@ -68,10 +68,6 @@ export const MultilineTextEditor = ({
navigateDown,
inputPreprocessor,
}: MultilineTextEditorProps): React.ReactElement => {
- const [buffer, setBuffer] = useState(
- () => new TextBuffer(initialText, initialCursorOffset),
- );
-
const terminalSize = useTerminalSize();
const effectiveWidth = Math.max(
20,
@@ -81,35 +77,14 @@ export const MultilineTextEditor = ({
const { stdin, setRawMode } = useStdin();
- // TODO(jacobr): make TextBuffer immutable rather than this hack to act
- // like it is immutable.
- const updateBufferState = useCallback(
- (mutator: (currentBuffer: TextBuffer) => void) => {
- setBuffer((currentBuffer) => {
- mutator(currentBuffer);
- // Create a new instance from the mutated buffer to trigger re-render
- return TextBuffer.fromBuffer(currentBuffer);
- });
- },
- [],
- );
-
- const openExternalEditor = useCallback(async () => {
- const wasRaw = stdin?.isRaw ?? false;
- try {
- setRawMode?.(false);
- // openInExternalEditor mutates the buffer instance
- await buffer.openInExternalEditor();
- } catch (err) {
- console.error('[MultilineTextEditor] external editor error', err);
- } finally {
- if (wasRaw) {
- setRawMode?.(true);
- }
- // Update state with the mutated buffer to trigger re-render
- setBuffer(TextBuffer.fromBuffer(buffer));
- }
- }, [buffer, stdin, setRawMode, setBuffer]);
+ const buffer = useTextBuffer({
+ initialText,
+ initialCursorOffset,
+ viewport: { height, width: effectiveWidth },
+ stdin,
+ setRawMode,
+ onChange, // Pass onChange to the hook
+ });
useInput(
(input, key) => {
@@ -131,7 +106,7 @@ export const MultilineTextEditor = ({
input.length === 1 &&
input.charCodeAt(0) === 5);
if (isCtrlX || isCtrlE) {
- openExternalEditor();
+ buffer.openInExternalEditor();
return;
}
@@ -142,8 +117,6 @@ export const MultilineTextEditor = ({
console.log('[MultilineTextEditor] event', { input, key });
}
- let bufferMutated = false;
-
if (input.startsWith('[') && input.endsWith('u')) {
const m = input.match(/^\[([0-9]+);([0-9]+)u$/);
if (m && m[1] === '13') {
@@ -151,14 +124,10 @@ export const MultilineTextEditor = ({
const hasCtrl = Math.floor(mod / 4) % 2 === 1;
if (hasCtrl) {
if (onSubmit) {
- onSubmit(buffer.getText());
+ onSubmit(buffer.text);
}
} else {
buffer.newline();
- bufferMutated = true;
- }
- if (bufferMutated) {
- updateBufferState((_) => {}); // Trigger re-render if mutated
}
return;
}
@@ -171,14 +140,10 @@ export const MultilineTextEditor = ({
const hasCtrl = Math.floor(mod / 4) % 2 === 1;
if (hasCtrl) {
if (onSubmit) {
- onSubmit(buffer.getText());
+ onSubmit(buffer.text);
}
} else {
buffer.newline();
- bufferMutated = true;
- }
- if (bufferMutated) {
- updateBufferState((_) => {}); // Trigger re-render if mutated
}
return;
}
@@ -186,63 +151,42 @@ export const MultilineTextEditor = ({
if (input === '\n') {
buffer.newline();
- updateBufferState((_) => {});
return;
}
if (input === '\r') {
if (onSubmit) {
- onSubmit(buffer.getText());
+ onSubmit(buffer.text);
}
return;
}
if (key.upArrow) {
- if (buffer.getCursor()[0] === 0 && navigateUp) {
+ if (buffer.cursor[0] === 0 && navigateUp) {
navigateUp();
return;
}
}
if (key.downArrow) {
- if (
- buffer.getCursor()[0] === buffer.getText().split('\n').length - 1 &&
- navigateDown
- ) {
+ if (buffer.cursor[0] === buffer.lines.length - 1 && navigateDown) {
navigateDown();
return;
}
}
- const modifiedByHandleInput = buffer.handleInput(
- input,
- key as Record<string, boolean>,
- { height, width: effectiveWidth },
- );
-
- if (modifiedByHandleInput) {
- updateBufferState((_) => {});
- }
-
- const newText = buffer.getText();
- if (onChange) {
- onChange(newText);
- }
+ buffer.handleInput(input, key as Record<string, boolean>);
},
{ isActive: focus },
);
- const visibleLines = buffer.getVisibleLines({
- height,
- width: effectiveWidth,
- });
- const [cursorRow, cursorCol] = buffer.getCursor();
- const scrollRow = buffer.getScrollRow();
- const scrollCol = buffer.getScrollCol();
+ const visibleLines = buffer.visibleLines;
+ const [cursorRow, cursorCol] = buffer.cursor;
+ const [scrollRow, scrollCol] = buffer.scroll;
return (
<Box flexDirection="column">
- {buffer.getText().length === 0 && placeholder ? (
+ {buffer.text.length === 0 && placeholder ? (
<Text color={Colors.SubtleComment}>{placeholder}</Text>
) : (
visibleLines.map((lineText, idx) => {