ccmanager 3.5.2 → 3.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -9,10 +9,5 @@ interface TextInputWrapperProps {
|
|
|
9
9
|
showCursor?: boolean;
|
|
10
10
|
highlightPastedText?: boolean;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Custom text input component that handles rapid input correctly.
|
|
14
|
-
* This is a replacement for ink-text-input that uses refs for immediate
|
|
15
|
-
* state updates, which is necessary for text expansion tools like Espanso.
|
|
16
|
-
*/
|
|
17
12
|
declare const TextInputWrapper: React.FC<TextInputWrapperProps>;
|
|
18
13
|
export default TextInputWrapper;
|
|
@@ -1,142 +1,15 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import
|
|
3
|
-
import { Text, useInput } from 'ink';
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import TextInput from 'ink-text-input';
|
|
4
3
|
import stripAnsi from 'strip-ansi';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const valueRef = useRef(value);
|
|
14
|
-
const cursorRef = useRef(value.length);
|
|
15
|
-
// State for triggering re-renders
|
|
16
|
-
const [, forceUpdate] = useState({});
|
|
17
|
-
// Sync refs when value prop changes from parent
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
valueRef.current = value;
|
|
20
|
-
// Adjust cursor if it's beyond the new value length
|
|
21
|
-
if (cursorRef.current > value.length) {
|
|
22
|
-
cursorRef.current = value.length;
|
|
23
|
-
}
|
|
24
|
-
}, [value]);
|
|
25
|
-
const cleanValue = (val) => {
|
|
26
|
-
let cleaned = stripAnsi(val);
|
|
27
|
-
cleaned = cleaned.replace(/\[200~/g, '').replace(/\[201~/g, '');
|
|
28
|
-
return cleaned;
|
|
4
|
+
const TextInputWrapper = ({ value, onChange, ...props }) => {
|
|
5
|
+
const handleChange = (newValue) => {
|
|
6
|
+
// First strip all ANSI escape sequences
|
|
7
|
+
let cleanedValue = stripAnsi(newValue);
|
|
8
|
+
// Then specifically remove bracketed paste mode markers that might remain
|
|
9
|
+
// These sometimes appear as literal text after ANSI stripping
|
|
10
|
+
cleanedValue = cleanedValue.replace(/\[200~/g, '').replace(/\[201~/g, '');
|
|
11
|
+
onChange(cleanedValue);
|
|
29
12
|
};
|
|
30
|
-
|
|
31
|
-
// This handles cases where text expansion tools send backspaces as characters
|
|
32
|
-
const processBackspaces = (input, currentValue, cursor) => {
|
|
33
|
-
let newValue = currentValue;
|
|
34
|
-
let newCursor = cursor;
|
|
35
|
-
let remaining = '';
|
|
36
|
-
for (let i = 0; i < input.length; i++) {
|
|
37
|
-
const char = input[i];
|
|
38
|
-
const charCode = char?.charCodeAt(0);
|
|
39
|
-
// Check for backspace characters (ASCII 8 or 127)
|
|
40
|
-
if (charCode === 8 || charCode === 127) {
|
|
41
|
-
if (newCursor > 0) {
|
|
42
|
-
newValue =
|
|
43
|
-
newValue.slice(0, newCursor - 1) + newValue.slice(newCursor);
|
|
44
|
-
newCursor--;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// Regular character - add to remaining
|
|
49
|
-
remaining += char;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return { value: newValue, cursor: newCursor, remainingInput: remaining };
|
|
53
|
-
};
|
|
54
|
-
useInput((input, key) => {
|
|
55
|
-
// Ignore certain keys
|
|
56
|
-
if (key.upArrow ||
|
|
57
|
-
key.downArrow ||
|
|
58
|
-
(key.ctrl && input === 'c') ||
|
|
59
|
-
key.tab ||
|
|
60
|
-
(key.shift && key.tab)) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
// Handle Enter/Return
|
|
64
|
-
if (key.return) {
|
|
65
|
-
if (onSubmit) {
|
|
66
|
-
onSubmit(valueRef.current);
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
let currentValue = valueRef.current;
|
|
71
|
-
let cursor = cursorRef.current;
|
|
72
|
-
if (key.leftArrow) {
|
|
73
|
-
if (showCursor && cursor > 0) {
|
|
74
|
-
cursorRef.current = cursor - 1;
|
|
75
|
-
forceUpdate({});
|
|
76
|
-
}
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (key.rightArrow) {
|
|
80
|
-
if (showCursor && cursor < currentValue.length) {
|
|
81
|
-
cursorRef.current = cursor + 1;
|
|
82
|
-
forceUpdate({});
|
|
83
|
-
}
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (key.backspace || key.delete) {
|
|
87
|
-
if (cursor > 0) {
|
|
88
|
-
const nextValue = currentValue.slice(0, cursor - 1) + currentValue.slice(cursor);
|
|
89
|
-
valueRef.current = nextValue;
|
|
90
|
-
cursorRef.current = cursor - 1;
|
|
91
|
-
onChange(nextValue);
|
|
92
|
-
forceUpdate({});
|
|
93
|
-
}
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
// Process input that might contain embedded backspace characters
|
|
97
|
-
// (some text expansion tools send backspaces as part of the input string)
|
|
98
|
-
const { value: processedValue, cursor: processedCursor, remainingInput, } = processBackspaces(input, currentValue, cursor);
|
|
99
|
-
currentValue = processedValue;
|
|
100
|
-
cursor = processedCursor;
|
|
101
|
-
// Add remaining characters (non-backspace)
|
|
102
|
-
if (remainingInput) {
|
|
103
|
-
const cleanedInput = cleanValue(remainingInput);
|
|
104
|
-
if (cleanedInput) {
|
|
105
|
-
currentValue =
|
|
106
|
-
currentValue.slice(0, cursor) +
|
|
107
|
-
cleanedInput +
|
|
108
|
-
currentValue.slice(cursor);
|
|
109
|
-
cursor = cursor + cleanedInput.length;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Update refs immediately (synchronously)
|
|
113
|
-
valueRef.current = currentValue;
|
|
114
|
-
cursorRef.current = cursor;
|
|
115
|
-
// Notify parent of value change
|
|
116
|
-
onChange(currentValue);
|
|
117
|
-
// Force re-render to update display
|
|
118
|
-
forceUpdate({});
|
|
119
|
-
}, { isActive: focus });
|
|
120
|
-
// Render the text with cursor
|
|
121
|
-
const displayValue = mask
|
|
122
|
-
? mask.repeat(valueRef.current.length)
|
|
123
|
-
: valueRef.current;
|
|
124
|
-
const cursor = cursorRef.current;
|
|
125
|
-
if (!showCursor || !focus) {
|
|
126
|
-
return (_jsx(Text, { children: displayValue.length > 0 ? (displayValue) : placeholder ? (_jsx(Text, { dimColor: true, children: placeholder })) : null }));
|
|
127
|
-
}
|
|
128
|
-
// Show cursor
|
|
129
|
-
if (displayValue.length === 0) {
|
|
130
|
-
// Show placeholder with cursor on first char
|
|
131
|
-
if (placeholder) {
|
|
132
|
-
return (_jsxs(Text, { children: [_jsx(Text, { inverse: true, children: placeholder[0] || ' ' }), _jsx(Text, { dimColor: true, children: placeholder.slice(1) })] }));
|
|
133
|
-
}
|
|
134
|
-
return _jsx(Text, { inverse: true, children: " " });
|
|
135
|
-
}
|
|
136
|
-
// Render value with cursor
|
|
137
|
-
const beforeCursor = displayValue.slice(0, cursor);
|
|
138
|
-
const atCursor = displayValue[cursor] || ' ';
|
|
139
|
-
const afterCursor = displayValue.slice(cursor + 1);
|
|
140
|
-
return (_jsxs(Text, { children: [beforeCursor, _jsx(Text, { inverse: true, children: atCursor }), afterCursor] }));
|
|
13
|
+
return _jsx(TextInput, { value: value, onChange: handleChange, ...props });
|
|
141
14
|
};
|
|
142
15
|
export default TextInputWrapper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccmanager",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.3",
|
|
4
4
|
"description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kodai Kabasawa",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"build:binary:native": "bun run scripts/build-binaries.ts --target=native",
|
|
27
27
|
"build:binary:all": "bun run scripts/build-binaries.ts --target=all",
|
|
28
28
|
"dev": "bun run tsc --watch",
|
|
29
|
-
"start": "bun dist/cli.js",
|
|
29
|
+
"start": "bun --no-env-file dist/cli.js",
|
|
30
30
|
"test": "vitest --run",
|
|
31
31
|
"lint": "bun run eslint src",
|
|
32
32
|
"lint:fix": "bun run eslint src --fix",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"bin"
|
|
42
42
|
],
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@kodaikabasawa/ccmanager-darwin-arm64": "3.5.
|
|
45
|
-
"@kodaikabasawa/ccmanager-darwin-x64": "3.5.
|
|
46
|
-
"@kodaikabasawa/ccmanager-linux-arm64": "3.5.
|
|
47
|
-
"@kodaikabasawa/ccmanager-linux-x64": "3.5.
|
|
48
|
-
"@kodaikabasawa/ccmanager-win32-x64": "3.5.
|
|
44
|
+
"@kodaikabasawa/ccmanager-darwin-arm64": "3.5.3",
|
|
45
|
+
"@kodaikabasawa/ccmanager-darwin-x64": "3.5.3",
|
|
46
|
+
"@kodaikabasawa/ccmanager-linux-arm64": "3.5.3",
|
|
47
|
+
"@kodaikabasawa/ccmanager-linux-x64": "3.5.3",
|
|
48
|
+
"@kodaikabasawa/ccmanager-win32-x64": "3.5.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@eslint/js": "^9.28.0",
|