@google/gemini-cli 0.25.0-nightly.20260112.15891721a → 0.25.0-preview.0
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.
- package/dist/package.json +2 -2
- package/dist/src/commands/extensions/examples/mcp-server/example.d.ts +6 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js +22 -36
- package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.test.d.ts +6 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.test.js +111 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.test.js.map +1 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.test.ts +135 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.ts +60 -0
- package/dist/src/commands/extensions/examples/mcp-server/gemini-extension.json +1 -1
- package/dist/src/commands/extensions/examples/mcp-server/package.json +7 -0
- package/dist/src/commands/extensions/examples/mcp-server/tsconfig.json +13 -0
- package/dist/src/commands/extensions/utils.d.ts +1 -1
- package/dist/src/commands/skills/disable.js +1 -1
- package/dist/src/commands/skills/disable.js.map +1 -1
- package/dist/src/commands/skills/disable.test.js +1 -1
- package/dist/src/commands/skills/disable.test.js.map +1 -1
- package/dist/src/commands/skills/install.d.ts +14 -0
- package/dist/src/commands/skills/install.js +61 -0
- package/dist/src/commands/skills/install.js.map +1 -0
- package/dist/src/commands/skills/install.test.d.ts +6 -0
- package/dist/src/commands/skills/install.test.js +57 -0
- package/dist/src/commands/skills/install.test.js.map +1 -0
- package/dist/src/commands/skills/list.js +1 -1
- package/dist/src/commands/skills/list.js.map +1 -1
- package/dist/src/commands/skills/list.test.js +1 -1
- package/dist/src/commands/skills/list.test.js.map +1 -1
- package/dist/src/commands/skills/uninstall.d.ts +13 -0
- package/dist/src/commands/skills/uninstall.js +56 -0
- package/dist/src/commands/skills/uninstall.js.map +1 -0
- package/dist/src/commands/skills/uninstall.test.d.ts +6 -0
- package/dist/src/commands/skills/uninstall.test.js +61 -0
- package/dist/src/commands/skills/uninstall.test.js.map +1 -0
- package/dist/src/commands/skills.js +4 -0
- package/dist/src/commands/skills.js.map +1 -1
- package/dist/src/config/config.js +5 -0
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/extension-manager-agents.test.d.ts +6 -0
- package/dist/src/config/extension-manager-agents.test.js +115 -0
- package/dist/src/config/extension-manager-agents.test.js.map +1 -0
- package/dist/src/config/extension-manager-scope.test.js +11 -0
- package/dist/src/config/extension-manager-scope.test.js.map +1 -1
- package/dist/src/config/extension-manager-skills.test.js +4 -0
- package/dist/src/config/extension-manager-skills.test.js.map +1 -1
- package/dist/src/config/extension-manager.js +7 -1
- package/dist/src/config/extension-manager.js.map +1 -1
- package/dist/src/config/extension.test.js +10 -1
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +14 -2
- package/dist/src/config/keyBindings.js +85 -10
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/settings.js +8 -9
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +66 -2
- package/dist/src/config/settingsSchema.js +99 -2
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/gemini.js +12 -6
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +18 -1
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/test-utils/render.js +1 -0
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/ui/AppContainer.js +103 -40
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +214 -41
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.d.ts +4 -1
- package/dist/src/ui/auth/AuthDialog.js +8 -2
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js +17 -0
- package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.d.ts +10 -0
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.js +27 -0
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.js.map +1 -0
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.js +68 -0
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.js.map +1 -0
- package/dist/src/ui/commands/aboutCommand.js +1 -1
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.test.js +4 -4
- package/dist/src/ui/commands/aboutCommand.test.js.map +1 -1
- package/dist/src/ui/commands/agentsCommand.js +5 -1
- package/dist/src/ui/commands/agentsCommand.js.map +1 -1
- package/dist/src/ui/commands/agentsCommand.test.js +1 -1
- package/dist/src/ui/commands/agentsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.js +1 -1
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.test.js +1 -1
- package/dist/src/ui/commands/chatCommand.test.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +9 -9
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.test.js +9 -9
- package/dist/src/ui/commands/directoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.js +36 -36
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.js +36 -36
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/helpCommand.js +1 -1
- package/dist/src/ui/commands/helpCommand.js.map +1 -1
- package/dist/src/ui/commands/helpCommand.test.js +1 -1
- package/dist/src/ui/commands/helpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/hooksCommand.js +1 -1
- package/dist/src/ui/commands/hooksCommand.js.map +1 -1
- package/dist/src/ui/commands/hooksCommand.test.js +4 -4
- package/dist/src/ui/commands/hooksCommand.test.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +6 -6
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.js +3 -3
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +18 -43
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.js +85 -15
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/skillsCommand.js +23 -8
- package/dist/src/ui/commands/skillsCommand.js.map +1 -1
- package/dist/src/ui/commands/skillsCommand.test.js +33 -12
- package/dist/src/ui/commands/skillsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/statsCommand.js +4 -4
- package/dist/src/ui/commands/statsCommand.js.map +1 -1
- package/dist/src/ui/commands/statsCommand.test.js +4 -4
- package/dist/src/ui/commands/statsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/toolsCommand.js +2 -2
- package/dist/src/ui/commands/toolsCommand.js.map +1 -1
- package/dist/src/ui/commands/toolsCommand.test.js +2 -2
- package/dist/src/ui/commands/toolsCommand.test.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +1 -1
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/Help.js +1 -1
- package/dist/src/ui/components/Help.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +18 -7
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +64 -1
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.js +6 -9
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/MainContent.test.js +19 -9
- package/dist/src/ui/components/MainContent.test.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +1 -1
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.d.ts +2 -2
- package/dist/src/ui/components/MultiFolderTrustDialog.js +1 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.js.map +1 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.test.js +2 -2
- package/dist/src/ui/components/MultiFolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +5 -2
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/StickyHeader.d.ts +2 -0
- package/dist/src/ui/components/StickyHeader.js +1 -1
- package/dist/src/ui/components/StickyHeader.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.js +5 -13
- package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +26 -17
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/ShellToolMessage.js +8 -5
- package/dist/src/ui/components/messages/ShellToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -5
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js +6 -2
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplay.js +22 -16
- package/dist/src/ui/components/messages/ToolResultDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplay.test.js +36 -18
- package/dist/src/ui/components/messages/ToolResultDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js +134 -0
- package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js.map +1 -0
- package/dist/src/ui/components/shared/MaxSizedBox.d.ts +2 -38
- package/dist/src/ui/components/shared/MaxSizedBox.js +34 -419
- package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +48 -133
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.d.ts +4 -4
- package/dist/src/ui/components/shared/text-buffer.js +35 -38
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/views/AgentsStatus.js +3 -3
- package/dist/src/ui/components/views/AgentsStatus.js.map +1 -1
- package/dist/src/ui/constants/tips.js +1 -1
- package/dist/src/ui/constants/tips.js.map +1 -1
- package/dist/src/ui/constants.d.ts +1 -0
- package/dist/src/ui/constants.js +1 -0
- package/dist/src/ui/constants.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.js +28 -0
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +31 -1
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +3 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.d.ts +2 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +5 -4
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -0
- package/dist/src/ui/hooks/useCommandCompletion.js +1 -0
- package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +7 -2
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +11 -2
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.d.ts +2 -1
- package/dist/src/ui/hooks/useGeminiStream.js +34 -14
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +87 -10
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.d.ts +1 -1
- package/dist/src/ui/hooks/useHistoryManager.js +1 -1
- package/dist/src/ui/hooks/useHistoryManager.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js +16 -0
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.js +2 -2
- package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +2 -2
- package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.d.ts +2 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +7 -3
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +14 -4
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +2 -2
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +79 -53
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/types.d.ts +2 -1
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +2 -2
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/commandUtils.js +1 -3
- package/dist/src/ui/utils/commandUtils.js.map +1 -1
- package/dist/src/ui/utils/commandUtils.test.js +15 -2
- package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
- package/dist/src/utils/sessionCleanup.js +12 -0
- package/dist/src/utils/sessionCleanup.js.map +1 -1
- package/dist/src/utils/skillUtils.d.ts +13 -0
- package/dist/src/utils/skillUtils.js +93 -0
- package/dist/src/utils/skillUtils.js.map +1 -1
- package/dist/src/utils/skillUtils.test.d.ts +6 -0
- package/dist/src/utils/skillUtils.test.js +57 -0
- package/dist/src/utils/skillUtils.test.js.map +1 -0
- package/dist/src/utils/windowTitle.d.ts +13 -4
- package/dist/src/utils/windowTitle.js +65 -7
- package/dist/src/utils/windowTitle.js.map +1 -1
- package/dist/src/utils/windowTitle.test.js +183 -40
- package/dist/src/utils/windowTitle.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/dist/google-gemini-cli-0.25.0-nightly.20260107.59a18e710.tgz +0 -0
- package/dist/src/commands/extensions/examples/hooks/gemini-extension.json +0 -4
- package/dist/src/commands/extensions/examples/hooks/hooks/hooks.json +0 -14
- package/dist/src/commands/extensions/examples/hooks/scripts/on-start.js +0 -8
- package/dist/src/commands/extensions/examples/mcp-server/README.md +0 -35
- package/dist/src/commands/extensions/examples/skills/gemini-extension.json +0 -4
- package/dist/src/commands/extensions/examples/skills/skills/greeter/SKILL.md +0 -7
|
@@ -5,170 +5,85 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
5
5
|
* SPDX-License-Identifier: Apache-2.0
|
|
6
6
|
*/
|
|
7
7
|
import { render } from '../../../test-utils/render.js';
|
|
8
|
+
import { waitFor } from '../../../test-utils/async.js';
|
|
8
9
|
import { OverflowProvider } from '../../contexts/OverflowContext.js';
|
|
9
|
-
import { MaxSizedBox
|
|
10
|
+
import { MaxSizedBox } from './MaxSizedBox.js';
|
|
10
11
|
import { Box, Text } from 'ink';
|
|
11
12
|
import { describe, it, expect } from 'vitest';
|
|
12
13
|
describe('<MaxSizedBox />', () => {
|
|
13
|
-
|
|
14
|
-
// This is useful for debugging issues with the component.
|
|
15
|
-
// It should be set to false in production for performance and to avoid
|
|
16
|
-
// cluttering the console if there are ignorable issues.
|
|
17
|
-
setMaxSizedBoxDebugging(true);
|
|
18
|
-
it('renders children without truncation when they fit', () => {
|
|
14
|
+
it('renders children without truncation when they fit', async () => {
|
|
19
15
|
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: _jsx(Box, { children: _jsx(Text, { children: "Hello, World!" }) }) }) }));
|
|
20
|
-
expect(lastFrame()).
|
|
16
|
+
await waitFor(() => expect(lastFrame()).toContain('Hello, World!'));
|
|
17
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
21
18
|
unmount();
|
|
22
19
|
});
|
|
23
|
-
it('hides lines when content exceeds maxHeight', () => {
|
|
24
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
25
|
-
expect(lastFrame()).
|
|
26
|
-
|
|
20
|
+
it('hides lines when content exceeds maxHeight', async () => {
|
|
21
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Line 1" }), _jsx(Text, { children: "Line 2" }), _jsx(Text, { children: "Line 3" })] }) }) }));
|
|
22
|
+
await waitFor(() => expect(lastFrame()).toContain('... first 2 lines hidden ...'));
|
|
23
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
27
24
|
unmount();
|
|
28
25
|
});
|
|
29
|
-
it('hides lines at the end when content exceeds maxHeight and overflowDirection is bottom', () => {
|
|
30
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
31
|
-
expect(lastFrame()).
|
|
32
|
-
|
|
26
|
+
it('hides lines at the end when content exceeds maxHeight and overflowDirection is bottom', async () => {
|
|
27
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 2, overflowDirection: "bottom", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Line 1" }), _jsx(Text, { children: "Line 2" }), _jsx(Text, { children: "Line 3" })] }) }) }));
|
|
28
|
+
await waitFor(() => expect(lastFrame()).toContain('... last 2 lines hidden ...'));
|
|
29
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
33
30
|
unmount();
|
|
34
31
|
});
|
|
35
|
-
it('
|
|
36
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth:
|
|
37
|
-
expect(lastFrame()).
|
|
38
|
-
|
|
39
|
-
of text`);
|
|
40
|
-
unmount();
|
|
41
|
-
});
|
|
42
|
-
it('handles mixed wrapping and non-wrapping segments', () => {
|
|
43
|
-
const multilineText = `This part will wrap around.
|
|
44
|
-
And has a line break.
|
|
45
|
-
Leading spaces preserved.`;
|
|
46
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 20, maxHeight: 20, children: [_jsx(Box, { children: _jsx(Text, { children: "Example" }) }), _jsxs(Box, { children: [_jsx(Text, { children: "No Wrap: " }), _jsx(Text, { wrap: "wrap", children: multilineText })] }), _jsxs(Box, { children: [_jsx(Text, { children: "Longer No Wrap: " }), _jsx(Text, { wrap: "wrap", children: "This part will wrap around." })] })] }) }));
|
|
47
|
-
expect(lastFrame()).equals(`Example
|
|
48
|
-
No Wrap: This part
|
|
49
|
-
will wrap
|
|
50
|
-
around.
|
|
51
|
-
And has a
|
|
52
|
-
line break.
|
|
53
|
-
Leading
|
|
54
|
-
spaces
|
|
55
|
-
preserved.
|
|
56
|
-
Longer No Wrap: This
|
|
57
|
-
part
|
|
58
|
-
will
|
|
59
|
-
wrap
|
|
60
|
-
arou
|
|
61
|
-
nd.`);
|
|
32
|
+
it('shows plural "lines" when more than one line is hidden', async () => {
|
|
33
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Line 1" }), _jsx(Text, { children: "Line 2" }), _jsx(Text, { children: "Line 3" })] }) }) }));
|
|
34
|
+
await waitFor(() => expect(lastFrame()).toContain('... first 2 lines hidden ...'));
|
|
35
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
62
36
|
unmount();
|
|
63
37
|
});
|
|
64
|
-
it('
|
|
65
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth:
|
|
66
|
-
expect(lastFrame()).
|
|
67
|
-
|
|
68
|
-
expia
|
|
69
|
-
lidoc
|
|
70
|
-
ious`);
|
|
38
|
+
it('shows singular "line" when exactly one line is hidden', async () => {
|
|
39
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 2, additionalHiddenLinesCount: 1, children: _jsx(Box, { flexDirection: "column", children: _jsx(Text, { children: "Line 1" }) }) }) }));
|
|
40
|
+
await waitFor(() => expect(lastFrame()).toContain('... first 1 line hidden ...'));
|
|
41
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
71
42
|
unmount();
|
|
72
43
|
});
|
|
73
|
-
it('
|
|
74
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
75
|
-
expect(lastFrame()).
|
|
76
|
-
|
|
44
|
+
it('accounts for additionalHiddenLinesCount', async () => {
|
|
45
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 2, additionalHiddenLinesCount: 5, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Line 1" }), _jsx(Text, { children: "Line 2" }), _jsx(Text, { children: "Line 3" })] }) }) }));
|
|
46
|
+
await waitFor(() => expect(lastFrame()).toContain('... first 7 lines hidden ...'));
|
|
47
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
77
48
|
unmount();
|
|
78
49
|
});
|
|
79
|
-
it('
|
|
80
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
81
|
-
expect(lastFrame()).
|
|
82
|
-
|
|
50
|
+
it('wraps text that exceeds maxWidth', async () => {
|
|
51
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 10, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "This is a long line of text" }) }) }) }));
|
|
52
|
+
await waitFor(() => expect(lastFrame()).toContain('This is a'));
|
|
53
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
83
54
|
unmount();
|
|
84
55
|
});
|
|
85
|
-
it('
|
|
86
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
87
|
-
expect(lastFrame()).
|
|
88
|
-
|
|
56
|
+
it('does not truncate when maxHeight is undefined', async () => {
|
|
57
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: undefined, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Line 1" }), _jsx(Text, { children: "Line 2" })] }) }) }));
|
|
58
|
+
await waitFor(() => expect(lastFrame()).toContain('Line 1'));
|
|
59
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
89
60
|
unmount();
|
|
90
61
|
});
|
|
91
|
-
it('renders an empty box for empty children', () => {
|
|
62
|
+
it('renders an empty box for empty children', async () => {
|
|
92
63
|
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10 }) }));
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
expect(lastFrame()).equals('');
|
|
96
|
-
unmount();
|
|
97
|
-
});
|
|
98
|
-
it('wraps text with multi-byte unicode characters correctly', () => {
|
|
99
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 5, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "\u4F60\u597D\u4E16\u754C" }) }) }) }));
|
|
100
|
-
// "你好" has a visual width of 4. "世界" has a visual width of 4.
|
|
101
|
-
// With maxWidth=5, it should wrap after the second character.
|
|
102
|
-
expect(lastFrame()).equals(`你好
|
|
103
|
-
世界`);
|
|
104
|
-
unmount();
|
|
105
|
-
});
|
|
106
|
-
it('wraps text with multi-byte emoji characters correctly', () => {
|
|
107
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 5, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36" }) }) }) }));
|
|
108
|
-
// Each "🐶" has a visual width of 2.
|
|
109
|
-
// With maxWidth=5, it should wrap every 2 emojis.
|
|
110
|
-
expect(lastFrame()).equals(`🐶🐶
|
|
111
|
-
🐶🐶
|
|
112
|
-
🐶`);
|
|
113
|
-
unmount();
|
|
114
|
-
});
|
|
115
|
-
it('falls back to an ellipsis when width is extremely small', () => {
|
|
116
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 2, maxHeight: 2, children: _jsxs(Box, { children: [_jsx(Text, { children: "No" }), _jsx(Text, { wrap: "wrap", children: "wrap" })] }) }) }));
|
|
117
|
-
expect(lastFrame()).equals('N…');
|
|
118
|
-
unmount();
|
|
119
|
-
});
|
|
120
|
-
it('truncates long non-wrapping text with ellipsis', () => {
|
|
121
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 3, maxHeight: 2, children: _jsxs(Box, { children: [_jsx(Text, { children: "ABCDE" }), _jsx(Text, { wrap: "wrap", children: "wrap" })] }) }) }));
|
|
122
|
-
expect(lastFrame()).equals('AB…');
|
|
123
|
-
unmount();
|
|
124
|
-
});
|
|
125
|
-
it('truncates non-wrapping text containing line breaks', () => {
|
|
126
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 3, maxHeight: 2, children: _jsxs(Box, { children: [_jsx(Text, { children: 'A\nBCDE' }), _jsx(Text, { wrap: "wrap", children: "wrap" })] }) }) }));
|
|
127
|
-
expect(lastFrame()).equals(`A\n…`);
|
|
128
|
-
unmount();
|
|
129
|
-
});
|
|
130
|
-
it('truncates emoji characters correctly with ellipsis', () => {
|
|
131
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 3, maxHeight: 2, children: _jsxs(Box, { children: [_jsx(Text, { children: "\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36" }), _jsx(Text, { wrap: "wrap", children: "wrap" })] }) }) }));
|
|
132
|
-
expect(lastFrame()).equals(`🐶…`);
|
|
133
|
-
unmount();
|
|
134
|
-
});
|
|
135
|
-
it('shows ellipsis for multiple rows with long non-wrapping text', () => {
|
|
136
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 3, maxHeight: 3, children: [_jsxs(Box, { children: [_jsx(Text, { children: "AAA" }), _jsx(Text, { wrap: "wrap", children: "first" })] }), _jsxs(Box, { children: [_jsx(Text, { children: "BBB" }), _jsx(Text, { wrap: "wrap", children: "second" })] }), _jsxs(Box, { children: [_jsx(Text, { children: "CCC" }), _jsx(Text, { wrap: "wrap", children: "third" })] })] }) }));
|
|
137
|
-
expect(lastFrame()).equals(`AA…\nBB…\nCC…`);
|
|
138
|
-
unmount();
|
|
139
|
-
});
|
|
140
|
-
it('accounts for additionalHiddenLinesCount', () => {
|
|
141
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, additionalHiddenLinesCount: 5, children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
142
|
-
// 1 line is hidden by overflow, 5 are additionally hidden.
|
|
143
|
-
expect(lastFrame()).equals(`... first 7 lines hidden ...
|
|
144
|
-
Line 3`);
|
|
64
|
+
// Use waitFor to ensure ResizeObserver has a chance to run
|
|
65
|
+
await waitFor(() => expect(lastFrame()).toBeDefined());
|
|
66
|
+
expect(lastFrame()?.trim()).equals('');
|
|
145
67
|
unmount();
|
|
146
68
|
});
|
|
147
|
-
it('handles React.Fragment as a child', () => {
|
|
148
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children:
|
|
149
|
-
expect(lastFrame()).
|
|
150
|
-
|
|
151
|
-
Line 3 direct child`);
|
|
69
|
+
it('handles React.Fragment as a child', async () => {
|
|
70
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: _jsxs(Box, { flexDirection: "column", children: [_jsxs(_Fragment, { children: [_jsx(Text, { children: "Line 1 from Fragment" }), _jsx(Text, { children: "Line 2 from Fragment" })] }), _jsx(Text, { children: "Line 3 direct child" })] }) }) }));
|
|
71
|
+
await waitFor(() => expect(lastFrame()).toContain('Line 1 from Fragment'));
|
|
72
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
152
73
|
unmount();
|
|
153
74
|
});
|
|
154
|
-
it('clips a long single text child from the top', () => {
|
|
75
|
+
it('clips a long single text child from the top', async () => {
|
|
155
76
|
const THIRTY_LINES = Array.from({ length: 30 }, (_, i) => `Line ${i + 1}`).join('\n');
|
|
156
|
-
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: _jsx(Box, { children: _jsx(Text, { children: THIRTY_LINES }) }) }) }));
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
...Array.from({ length: 9 }, (_, i) => `Line ${22 + i}`),
|
|
160
|
-
].join('\n');
|
|
161
|
-
expect(lastFrame()).equals(expected);
|
|
77
|
+
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, overflowDirection: "top", children: _jsx(Box, { children: _jsx(Text, { children: THIRTY_LINES }) }) }) }));
|
|
78
|
+
await waitFor(() => expect(lastFrame()).toContain('... first 21 lines hidden ...'));
|
|
79
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
162
80
|
unmount();
|
|
163
81
|
});
|
|
164
|
-
it('clips a long single text child from the bottom', () => {
|
|
82
|
+
it('clips a long single text child from the bottom', async () => {
|
|
165
83
|
const THIRTY_LINES = Array.from({ length: 30 }, (_, i) => `Line ${i + 1}`).join('\n');
|
|
166
84
|
const { lastFrame, unmount } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, overflowDirection: "bottom", children: _jsx(Box, { children: _jsx(Text, { children: THIRTY_LINES }) }) }) }));
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
'... last 21 lines hidden ...',
|
|
170
|
-
].join('\n');
|
|
171
|
-
expect(lastFrame()).equals(expected);
|
|
85
|
+
await waitFor(() => expect(lastFrame()).toContain('... last 21 lines hidden ...'));
|
|
86
|
+
expect(lastFrame()).toMatchSnapshot();
|
|
172
87
|
unmount();
|
|
173
88
|
});
|
|
174
89
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaxSizedBox.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/shared/MaxSizedBox.test.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"MaxSizedBox.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/shared/MaxSizedBox.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
import { type EditorType } from '@google/gemini-cli-core';
|
|
6
7
|
import type { Key } from '../../contexts/KeypressContext.js';
|
|
7
8
|
export type Direction = 'left' | 'right' | 'up' | 'down' | 'wordLeft' | 'wordRight' | 'home' | 'end';
|
|
8
9
|
export declare const isWordCharStrict: (char: string) => boolean;
|
|
@@ -48,6 +49,7 @@ interface UseTextBufferProps {
|
|
|
48
49
|
shellModeActive?: boolean;
|
|
49
50
|
inputFilter?: (text: string) => string;
|
|
50
51
|
singleLine?: boolean;
|
|
52
|
+
getPreferredEditor?: () => EditorType | undefined;
|
|
51
53
|
}
|
|
52
54
|
interface UndoHistoryEntry {
|
|
53
55
|
lines: string[];
|
|
@@ -285,7 +287,7 @@ export interface TextBufferOptions {
|
|
|
285
287
|
singleLine?: boolean;
|
|
286
288
|
}
|
|
287
289
|
export declare function textBufferReducer(state: TextBufferState, action: TextBufferAction, options?: TextBufferOptions): TextBufferState;
|
|
288
|
-
export declare function useTextBuffer({ initialText, initialCursorOffset, viewport, stdin, setRawMode, onChange, isValidPath, shellModeActive, inputFilter, singleLine, }: UseTextBufferProps): TextBuffer;
|
|
290
|
+
export declare function useTextBuffer({ initialText, initialCursorOffset, viewport, stdin, setRawMode, onChange, isValidPath, shellModeActive, inputFilter, singleLine, getPreferredEditor, }: UseTextBufferProps): TextBuffer;
|
|
289
291
|
export interface TextBuffer {
|
|
290
292
|
lines: string[];
|
|
291
293
|
text: string;
|
|
@@ -389,9 +391,7 @@ export interface TextBuffer {
|
|
|
389
391
|
* continuing. This mirrors Git's behaviour and simplifies downstream
|
|
390
392
|
* control‑flow (callers can simply `await` the Promise).
|
|
391
393
|
*/
|
|
392
|
-
openInExternalEditor: (
|
|
393
|
-
editor?: string;
|
|
394
|
-
}) => Promise<void>;
|
|
394
|
+
openInExternalEditor: () => Promise<void>;
|
|
395
395
|
replaceRangeByOffset: (startOffset: number, endOffset: number, replacementText: string) => void;
|
|
396
396
|
getOffset: () => number;
|
|
397
397
|
moveToOffset(offset: number): void;
|
|
@@ -9,9 +9,10 @@ import os from 'node:os';
|
|
|
9
9
|
import pathMod from 'node:path';
|
|
10
10
|
import * as path from 'node:path';
|
|
11
11
|
import { useState, useCallback, useEffect, useMemo, useReducer } from 'react';
|
|
12
|
-
import { coreEvents, CoreEvent, debugLogger, unescapePath, } from '@google/gemini-cli-core';
|
|
12
|
+
import { coreEvents, CoreEvent, debugLogger, unescapePath, getEditorCommand, isGuiEditor, } from '@google/gemini-cli-core';
|
|
13
13
|
import { toCodePoints, cpLen, cpSlice, stripUnsafeCharacters, getCachedStringWidth, } from '../../utils/textUtils.js';
|
|
14
14
|
import { parsePastedPaths } from '../../utils/clipboardUtils.js';
|
|
15
|
+
import { keyMatchers, Command } from '../../keyMatchers.js';
|
|
15
16
|
import { handleVimAction } from './vim-buffer-actions.js';
|
|
16
17
|
// Helper functions for line-based word navigation
|
|
17
18
|
export const isWordCharStrict = (char) => /[\w\p{L}\p{N}]/u.test(char); // Matches a single character that is any Unicode letter, any Unicode number, or an underscore
|
|
@@ -1294,7 +1295,7 @@ export function textBufferReducer(state, action, options = {}) {
|
|
|
1294
1295
|
return newState;
|
|
1295
1296
|
}
|
|
1296
1297
|
// --- End of reducer logic ---
|
|
1297
|
-
export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewport, stdin, setRawMode, onChange, isValidPath, shellModeActive = false, inputFilter, singleLine = false, }) {
|
|
1298
|
+
export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewport, stdin, setRawMode, onChange, isValidPath, shellModeActive = false, inputFilter, singleLine = false, getPreferredEditor, }) {
|
|
1298
1299
|
const initialState = useMemo(() => {
|
|
1299
1300
|
const lines = initialText.split('\n');
|
|
1300
1301
|
const [initialCursorRow, initialCursorCol] = calculateInitialCursorPosition(lines.length === 0 ? [''] : lines, initialCursorOffset);
|
|
@@ -1522,19 +1523,32 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
|
|
|
1522
1523
|
const vimEscapeInsertMode = useCallback(() => {
|
|
1523
1524
|
dispatch({ type: 'vim_escape_insert_mode' });
|
|
1524
1525
|
}, []);
|
|
1525
|
-
const openInExternalEditor = useCallback(async (
|
|
1526
|
-
const editor = opts.editor ??
|
|
1527
|
-
process.env['VISUAL'] ??
|
|
1528
|
-
process.env['EDITOR'] ??
|
|
1529
|
-
(process.platform === 'win32' ? 'notepad' : 'vi');
|
|
1526
|
+
const openInExternalEditor = useCallback(async () => {
|
|
1530
1527
|
const tmpDir = fs.mkdtempSync(pathMod.join(os.tmpdir(), 'gemini-edit-'));
|
|
1531
1528
|
const filePath = pathMod.join(tmpDir, 'buffer.txt');
|
|
1532
1529
|
fs.writeFileSync(filePath, text, 'utf8');
|
|
1530
|
+
let command = undefined;
|
|
1531
|
+
const args = [filePath];
|
|
1532
|
+
const preferredEditorType = getPreferredEditor?.();
|
|
1533
|
+
if (!command && preferredEditorType) {
|
|
1534
|
+
command = getEditorCommand(preferredEditorType);
|
|
1535
|
+
if (isGuiEditor(preferredEditorType)) {
|
|
1536
|
+
args.unshift('--wait');
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
if (!command) {
|
|
1540
|
+
command =
|
|
1541
|
+
(process.env['VISUAL'] ??
|
|
1542
|
+
process.env['EDITOR'] ??
|
|
1543
|
+
process.platform === 'win32')
|
|
1544
|
+
? 'notepad'
|
|
1545
|
+
: 'vi';
|
|
1546
|
+
}
|
|
1533
1547
|
dispatch({ type: 'create_undo_snapshot' });
|
|
1534
1548
|
const wasRaw = stdin?.isRaw ?? false;
|
|
1535
1549
|
try {
|
|
1536
1550
|
setRawMode?.(false);
|
|
1537
|
-
const { status, error } = spawnSync(
|
|
1551
|
+
const { status, error } = spawnSync(command, args, {
|
|
1538
1552
|
stdio: 'inherit',
|
|
1539
1553
|
});
|
|
1540
1554
|
if (error)
|
|
@@ -1565,7 +1579,7 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
|
|
|
1565
1579
|
/* ignore */
|
|
1566
1580
|
}
|
|
1567
1581
|
}
|
|
1568
|
-
}, [text, stdin, setRawMode]);
|
|
1582
|
+
}, [text, stdin, setRawMode, getPreferredEditor]);
|
|
1569
1583
|
const handleInput = useCallback((key) => {
|
|
1570
1584
|
const { sequence: input } = key;
|
|
1571
1585
|
if (key.paste) {
|
|
@@ -1581,50 +1595,33 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
|
|
|
1581
1595
|
input === '\\r') // VSCode terminal represents shift + enter this way
|
|
1582
1596
|
)
|
|
1583
1597
|
newline();
|
|
1584
|
-
else if (
|
|
1598
|
+
else if (keyMatchers[Command.MOVE_LEFT](key))
|
|
1585
1599
|
move('left');
|
|
1586
|
-
else if (
|
|
1587
|
-
move('left');
|
|
1588
|
-
else if (key.name === 'right' && !key.meta && !key.ctrl)
|
|
1589
|
-
move('right');
|
|
1590
|
-
else if (key.ctrl && key.name === 'f')
|
|
1600
|
+
else if (keyMatchers[Command.MOVE_RIGHT](key))
|
|
1591
1601
|
move('right');
|
|
1592
1602
|
else if (key.name === 'up')
|
|
1593
1603
|
move('up');
|
|
1594
1604
|
else if (key.name === 'down')
|
|
1595
1605
|
move('down');
|
|
1596
|
-
else if ((key
|
|
1606
|
+
else if (keyMatchers[Command.MOVE_WORD_LEFT](key))
|
|
1597
1607
|
move('wordLeft');
|
|
1598
|
-
else if (
|
|
1599
|
-
move('wordLeft');
|
|
1600
|
-
else if ((key.ctrl || key.meta) && key.name === 'right')
|
|
1601
|
-
move('wordRight');
|
|
1602
|
-
else if (key.meta && key.name === 'f')
|
|
1608
|
+
else if (keyMatchers[Command.MOVE_WORD_RIGHT](key))
|
|
1603
1609
|
move('wordRight');
|
|
1604
|
-
else if (key
|
|
1605
|
-
move('home');
|
|
1606
|
-
else if (key.ctrl && key.name === 'a')
|
|
1610
|
+
else if (keyMatchers[Command.HOME](key))
|
|
1607
1611
|
move('home');
|
|
1608
|
-
else if (key
|
|
1612
|
+
else if (keyMatchers[Command.END](key))
|
|
1609
1613
|
move('end');
|
|
1610
|
-
else if (
|
|
1611
|
-
move('end');
|
|
1612
|
-
else if (key.ctrl && key.name === 'w')
|
|
1613
|
-
deleteWordLeft();
|
|
1614
|
-
else if ((key.meta || key.ctrl) &&
|
|
1615
|
-
(key.name === 'backspace' || input === '\x7f'))
|
|
1614
|
+
else if (keyMatchers[Command.DELETE_WORD_BACKWARD](key))
|
|
1616
1615
|
deleteWordLeft();
|
|
1617
|
-
else if ((key
|
|
1616
|
+
else if (keyMatchers[Command.DELETE_WORD_FORWARD](key))
|
|
1618
1617
|
deleteWordRight();
|
|
1619
|
-
else if (key
|
|
1620
|
-
input === '\x7f' ||
|
|
1621
|
-
(key.ctrl && key.name === 'h'))
|
|
1618
|
+
else if (keyMatchers[Command.DELETE_CHAR_LEFT](key))
|
|
1622
1619
|
backspace();
|
|
1623
|
-
else if (
|
|
1620
|
+
else if (keyMatchers[Command.DELETE_CHAR_RIGHT](key))
|
|
1624
1621
|
del();
|
|
1625
|
-
else if (
|
|
1622
|
+
else if (keyMatchers[Command.UNDO](key))
|
|
1626
1623
|
undo();
|
|
1627
|
-
else if (
|
|
1624
|
+
else if (keyMatchers[Command.REDO](key))
|
|
1628
1625
|
redo();
|
|
1629
1626
|
else if (key.insertable) {
|
|
1630
1627
|
insert(input, { paste: key.paste });
|