feat(ui): add Ctrl/Cmd+L to send selected text to chat

Bind mod+l to append the current selection into the chat composer
(Cursor-style), and move session sidebar toggle to mod+alt+l so desktop
menus stay in sync. Closes #208.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-03 12:04:35 +00:00
co-authored by Serhii Dziupin
parent e0bd787468
commit 3ad3f21024
30 changed files with 362 additions and 5 deletions
@@ -16,6 +16,8 @@ import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
import { isVSCodeRuntime } from '@/lib/desktop';
import { useI18n } from '@/lib/i18n';
import { rangeToMarkdown, trimSelectionValue, wrapMarkdownSelectionForChat } from './selectionMarkdown';
import { formatShortcutForDisplay, getEffectiveShortcutCombo } from '@/lib/shortcuts';
import { focusChatInput } from '@/components/chat/composer/editor/dom';
interface TextSelectionMenuProps {
containerRef: React.RefObject<HTMLElement | null>;
@@ -63,6 +65,11 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
const setPendingInputText = useInputStore((state) => state.setPendingInputText);
const isMobile = useUIStore((state) => state.isMobile);
const shortcutOverrides = useUIStore((state) => state.shortcutOverrides);
const addToChatShortcut = React.useMemo(
() => formatShortcutForDisplay(getEffectiveShortcutCombo('add_selection_to_chat', shortcutOverrides)),
[shortcutOverrides],
);
const projects = useProjectsStore((state) => state.projects);
const availableWorktreesByProject = useSessionUIStore((state) => state.availableWorktreesByProject);
const effectiveDirectory = useEffectiveDirectory();
@@ -309,6 +316,9 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
// Clear selection
window.getSelection()?.removeAllRanges();
queueMicrotask(() => {
focusChatInput();
});
}, [selectedTextMarkdown, setPendingInputText, hideMenu]);
const handleCreateNewSession = React.useCallback(async () => {
@@ -415,7 +425,9 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
'active:opacity-80',
'transition-opacity duration-150'
)}
title={t('chat.textSelection.title.addToCurrentChat')}
title={addToChatShortcut
? `${t('chat.textSelection.title.addToCurrentChat')} (${addToChatShortcut})`
: t('chat.textSelection.title.addToCurrentChat')}
type="button"
>
<Icon name="add" className="h-5 w-5 flex-shrink-0" />
@@ -508,11 +520,16 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
'hover:bg-[var(--interactive-hover)]',
'transition-colors duration-150'
)}
title={t('chat.textSelection.title.addToCurrentChat')}
title={addToChatShortcut
? `${t('chat.textSelection.title.addToCurrentChat')} (${addToChatShortcut})`
: t('chat.textSelection.title.addToCurrentChat')}
type="button"
>
<Icon name="add" className="h-4 w-4" />
<span className="whitespace-nowrap">{t('chat.textSelection.actions.addToChat')}</span>
{addToChatShortcut ? (
<span className="whitespace-nowrap text-xs text-muted-foreground">{addToChatShortcut}</span>
) : null}
</button>
<div className="w-px h-4 bg-[var(--interactive-border)]" />
@@ -65,6 +65,12 @@ export const HelpDialog: React.FC = () => {
icon: "layout-left",
keys: '',
},
{
id: 'add_selection_to_chat',
descriptionKey: "helpDialog.item.addSelectionToChat",
icon: "add",
keys: '',
},
{
id: 'cycle_agent',
keys: '',
@@ -16,6 +16,7 @@ import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { useProjectsStore } from '@/stores/useProjectsStore';
import { getCycledPrimaryAgentName } from '@/components/chat/mobileControlsUtils';
import { focusChatInput } from '@/components/chat/composer/editor/dom';
import { addSelectionToChat } from '@/lib/addSelectionToChat';
import { hasOpenDropdown } from './keyboard-shortcut-dom';
export const useKeyboardShortcuts = () => {
@@ -337,6 +338,12 @@ export const useKeyboardShortcuts = () => {
return;
}
if (eventMatchesShortcut(e, combo('add_selection_to_chat'))) {
e.preventDefault();
addSelectionToChat();
return;
}
if (eventMatchesShortcut(e, combo('toggle_sidebar'))) {
e.preventDefault();
const { isMobile, isSessionSwitcherOpen } = useUIStore.getState();
+6
View File
@@ -10,6 +10,7 @@ import { useThemeSystem } from '@/contexts/useThemeSystem';
import { sessionEvents } from '@/lib/sessionEvents';
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
import { showOpenCodeStatus } from '@/lib/openCodeStatus';
import { addSelectionToChat } from '@/lib/addSelectionToChat';
const getActiveElementSelectedText = (): string => {
if (typeof document === 'undefined') {
@@ -77,6 +78,7 @@ type MenuAction =
| 'toggle-terminal'
| 'toggle-terminal-expanded'
| 'copy'
| 'add-selection-to-chat'
| 'theme-light'
| 'theme-dark'
| 'theme-system'
@@ -278,6 +280,10 @@ export const useMenuActions = (
setThemeMode('system');
break;
case 'add-selection-to-chat':
addSelectionToChat();
break;
case 'toggle-sidebar':
toggleSidebar();
break;
@@ -0,0 +1,137 @@
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
const focusChatInputCalls: number[] = [];
const pendingInputCalls: Array<{ text: string | null; mode?: string }> = [];
const activeMainTabCalls: string[] = [];
const sessionSwitcherCalls: boolean[] = [];
mock.module('@/components/chat/composer/editor/dom', () => ({
focusChatInput: () => {
focusChatInputCalls.push(1);
},
}));
mock.module('@/sync/input-store', () => ({
useInputStore: {
getState: () => ({
setPendingInputText: (text: string | null, mode?: string) => {
pendingInputCalls.push({ text, mode });
},
}),
},
}));
mock.module('@/stores/useUIStore', () => ({
useUIStore: {
getState: () => ({
setActiveMainTab: (tab: string) => {
activeMainTabCalls.push(tab);
},
setSessionSwitcherOpen: (open: boolean) => {
sessionSwitcherCalls.push(open);
},
}),
},
}));
const { addSelectionToChat, captureSelectionMarkdownForChat } = await import('./addSelectionToChat');
const originalDocument = globalThis.document;
const originalWindow = globalThis.window;
const installEmptySelectionEnvironment = (activeElement: Element | null = null) => {
const documentLike = {
activeElement,
querySelector: () => null,
};
const windowLike = {
getSelection: () => null,
};
Object.defineProperty(globalThis, 'document', { value: documentLike, configurable: true });
Object.defineProperty(globalThis, 'window', { value: windowLike, configurable: true });
};
const clearCalls = () => {
focusChatInputCalls.length = 0;
pendingInputCalls.length = 0;
activeMainTabCalls.length = 0;
sessionSwitcherCalls.length = 0;
};
afterEach(() => {
Object.defineProperty(globalThis, 'document', { value: originalDocument, configurable: true });
Object.defineProperty(globalThis, 'window', { value: originalWindow, configurable: true });
});
describe('captureSelectionMarkdownForChat', () => {
beforeEach(() => {
clearCalls();
});
test('returns null when nothing is selected', () => {
installEmptySelectionEnvironment();
expect(captureSelectionMarkdownForChat()).toBeNull();
});
test('captures a textarea selection outside the composer', () => {
const textarea = {
tagName: 'TEXTAREA',
value: 'alpha beta gamma',
selectionStart: 6,
selectionEnd: 10,
closest: () => null,
} as unknown as HTMLTextAreaElement;
installEmptySelectionEnvironment(textarea);
expect(captureSelectionMarkdownForChat()).toBe('```md\nbeta\n```');
});
test('ignores selections inside the chat composer', () => {
const textarea = {
tagName: 'TEXTAREA',
value: 'draft text',
selectionStart: 0,
selectionEnd: 5,
closest: (selector: string) => (selector === '[data-chat-input="true"]' ? textarea : null),
} as unknown as HTMLTextAreaElement;
installEmptySelectionEnvironment(textarea);
expect(captureSelectionMarkdownForChat()).toBeNull();
});
});
describe('addSelectionToChat', () => {
beforeEach(() => {
clearCalls();
});
test('appends captured selection and focuses chat input', async () => {
const textarea = {
tagName: 'TEXTAREA',
value: 'selected',
selectionStart: 0,
selectionEnd: 8,
closest: () => null,
} as unknown as HTMLTextAreaElement;
installEmptySelectionEnvironment(textarea);
expect(addSelectionToChat()).toBe(true);
expect(activeMainTabCalls).toEqual(['chat']);
expect(sessionSwitcherCalls).toEqual([false]);
expect(pendingInputCalls).toEqual([{ text: '```md\nselected\n```', mode: 'append' }]);
await Promise.resolve();
expect(focusChatInputCalls.length).toBe(1);
});
test('focuses chat input when nothing is selected', async () => {
installEmptySelectionEnvironment();
expect(addSelectionToChat()).toBe(false);
expect(pendingInputCalls).toEqual([]);
expect(activeMainTabCalls).toEqual(['chat']);
await Promise.resolve();
expect(focusChatInputCalls.length).toBe(1);
});
});
+153
View File
@@ -0,0 +1,153 @@
import { EditorView } from '@codemirror/view';
import { focusChatInput } from '@/components/chat/composer/editor/dom';
import {
formatCodeSelectionMarkdown,
rangeToMarkdown,
trimSelectionValue,
wrapMarkdownSelectionForChat,
} from '@/components/chat/message/selectionMarkdown';
import { useInputStore } from '@/sync/input-store';
import { useUIStore } from '@/stores/useUIStore';
const CHAT_INPUT_HOST_SELECTOR = '[data-chat-input="true"]';
const isInsideChatComposer = (node: Node | null): boolean => {
if (!node) {
return false;
}
const asElement = node as Element;
const element = typeof asElement.closest === 'function'
? asElement
: (node as Node).parentElement;
return Boolean(element?.closest(CHAT_INPUT_HOST_SELECTOR));
};
const readTextControlSelection = (element: Element): string | null => {
if (isInsideChatComposer(element)) {
return null;
}
const tag = element.tagName?.toLowerCase();
if (tag === 'textarea') {
const control = element as HTMLTextAreaElement;
return trimSelectionValue(
control.value.slice(control.selectionStart ?? 0, control.selectionEnd ?? 0),
) || null;
}
if (tag === 'input') {
const control = element as HTMLInputElement;
const type = control.type?.toLowerCase() ?? 'text';
if (!['text', 'search', 'url', 'tel', 'password'].includes(type)) {
return null;
}
return trimSelectionValue(
control.value.slice(control.selectionStart ?? 0, control.selectionEnd ?? 0),
) || null;
}
return null;
};
const captureActiveElementSelection = (): string | null => {
if (typeof document === 'undefined') {
return null;
}
const activeElement = document.activeElement;
if (!activeElement || typeof (activeElement as Element).tagName !== 'string') {
return null;
}
const text = readTextControlSelection(activeElement as Element);
return text ? wrapMarkdownSelectionForChat(text) : null;
};
const captureCodeMirrorSelection = (): string | null => {
if (typeof document === 'undefined') {
return null;
}
const focusedEditor = document.querySelector<HTMLElement>('.cm-editor.cm-focused');
if (!focusedEditor || isInsideChatComposer(focusedEditor)) {
return null;
}
const view = EditorView.findFromDOM(focusedEditor);
if (!view) {
return null;
}
const { from, to } = view.state.selection.main;
if (from === to) {
return null;
}
const text = trimSelectionValue(view.state.sliceDoc(from, to));
if (!text) {
return null;
}
view.dispatch({
selection: { anchor: to },
});
return formatCodeSelectionMarkdown(text);
};
const captureDomSelection = (): string | null => {
if (typeof window === 'undefined') {
return null;
}
const selection = window.getSelection();
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
return null;
}
const range = selection.getRangeAt(0);
if (isInsideChatComposer(range.commonAncestorContainer)) {
return null;
}
const plainText = trimSelectionValue(selection.toString());
if (!plainText) {
return null;
}
const markdown = rangeToMarkdown(range, plainText);
selection.removeAllRanges();
return wrapMarkdownSelectionForChat(markdown);
};
/**
* Capture the current non-composer selection as chat-ready markdown.
* Returns null when nothing usable is selected.
*/
export const captureSelectionMarkdownForChat = (): string | null => {
return captureCodeMirrorSelection()
?? captureActiveElementSelection()
?? captureDomSelection();
};
/**
* Append the current selection to the chat composer.
* When nothing is selected, focuses the chat input (Cursor-style Ctrl/Cmd+L).
* Returns true when selected text was appended.
*/
export const addSelectionToChat = (): boolean => {
const markdown = captureSelectionMarkdownForChat();
useUIStore.getState().setActiveMainTab('chat');
useUIStore.getState().setSessionSwitcherOpen(false);
if (markdown) {
useInputStore.getState().setPendingInputText(markdown, 'append');
}
queueMicrotask(() => {
focusChatInput();
});
return markdown !== null;
};
@@ -1039,6 +1039,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': 'Einstellungen öffnen',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': 'Terminal-Dock umschalten',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal erweitert umschalten',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Auswahl zum Chat hinzufügen',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Seitenleiste umschalten',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Rechte Seitenleiste umschalten',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git-Tab der rechten Seitenleiste öffnen',
+1
View File
@@ -1531,6 +1531,7 @@ export const dict = {
'helpDialog.item.openCommandPalette': 'Befehlspalette öffnen',
'helpDialog.item.showKeyboardShortcuts': 'Tastaturkürzel anzeigen (dieses Dialogfeld)',
'helpDialog.item.toggleSessionSidebar': 'Sitzungs-Seitenleiste umschalten',
'helpDialog.item.addSelectionToChat': 'Auswahl zum Chat hinzufügen',
'helpDialog.item.cycleAgent': 'Agent wechseln (Chat-Eingabe)',
'helpDialog.item.openModelSelector': 'Modell-Auswahldialog öffnen',
'helpDialog.item.navigateModels': 'Modelle navigieren (in Auswahl)',
@@ -1104,6 +1104,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': 'Open settings',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': 'Toggle terminal dock',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Toggle terminal expanded',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Add selection to chat',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Toggle sidebar',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Toggle context panel',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Open Git surface',
+1
View File
@@ -1678,6 +1678,7 @@ export const dict = {
'helpDialog.item.openCommandPalette': 'Open Command Palette',
'helpDialog.item.showKeyboardShortcuts': 'Show Keyboard Shortcuts (this dialog)',
'helpDialog.item.toggleSessionSidebar': 'Toggle Session Sidebar',
'helpDialog.item.addSelectionToChat': 'Add Selection to Chat',
'helpDialog.item.cycleAgent': 'Cycle Agent (chat input)',
'helpDialog.item.openModelSelector': 'Open Model Selector',
'helpDialog.item.navigateModels': 'Navigate Models (in picker)',
@@ -1071,6 +1071,7 @@ export const settingsDict = {
"settings.openchamber.keyboardShortcuts.action.open_settings.label": "Abrir configuración",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal.label": "Mostrar u ocultar panel de terminal",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir o contraer terminal",
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Agregar selección al chat",
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar u ocultar barra lateral",
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Alternar panel de contexto',
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Abrir superficie de Git',
+1
View File
@@ -1656,6 +1656,7 @@ export const dict: Record<I18nKey, string> = {
"helpDialog.item.openCommandPalette": "Abrir paleta de comandos",
"helpDialog.item.showKeyboardShortcuts": "Mostrar atajos de teclado (este diálogo)",
"helpDialog.item.toggleSessionSidebar": "Mostrar u ocultar barra lateral de sesión",
"helpDialog.item.addSelectionToChat": "Agregar selección al chat",
"helpDialog.item.cycleAgent": "Cambiar agente (entrada de chat)",
"helpDialog.item.openModelSelector": "Abrir selector de modelos",
"helpDialog.item.navigateModels": "Navegar modelos (en selector)",
@@ -992,6 +992,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': 'Ouvrir les paramètres',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': 'Basculer la station d\'accueil du terminal',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal à bascule étendu',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Ajouter la sélection au chat',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Basculer la barre latérale',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Afficher/masquer le panneau de contexte',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Ouvrir la surface Git',
+1
View File
@@ -1491,6 +1491,7 @@ export const dict = {
'helpDialog.item.openCommandPalette': 'Ouvrir la palette de commandes',
'helpDialog.item.showKeyboardShortcuts': 'Afficher les raccourcis clavier (cette boîte de dialogue)',
'helpDialog.item.toggleSessionSidebar': 'Toggle la barre latérale de la session',
'helpDialog.item.addSelectionToChat': 'Ajouter la sélection au chat',
'helpDialog.item.cycleAgent': 'Agent de cycle (entrée de chat)',
'helpDialog.item.openModelSelector': 'Ouvrir le sélecteur de modèle',
'helpDialog.item.navigateModels': 'Naviguer dans les modèles (dans le sélecteur)',
@@ -1104,6 +1104,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': '設定を開く',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': 'ターミナルドックの切替',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'ターミナル拡大の切替',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '選択範囲をチャットに追加',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'サイドバーの切替',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'コンテキストパネルの表示切替',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git サーフェスを開く',
+1
View File
@@ -1674,6 +1674,7 @@ export const dict: Record<I18nKey, string> = {
'helpDialog.item.openCommandPalette': 'コマンドパレットを開く',
'helpDialog.item.showKeyboardShortcuts': 'キーボードショートカットを表示(このダイアログ)',
'helpDialog.item.toggleSessionSidebar': 'セッションサイドバーの切り替え',
'helpDialog.item.addSelectionToChat': '選択範囲をチャットに追加',
'helpDialog.item.cycleAgent': 'エージェント切り替え(チャット入力)',
'helpDialog.item.openModelSelector': 'モデルセレクターを開く',
'helpDialog.item.navigateModels': 'モデルを移動(ピッカー内)',
@@ -1071,6 +1071,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': '설정 열기',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': '터미널 dock 토글',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '터미널 확장 토글',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '선택 내용을 채팅에 추가',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '사이드바 토글',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '컨텍스트 패널 표시 전환',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git 서피스 열기',
+1
View File
@@ -1680,6 +1680,7 @@ export const dict: Record<I18nKey, string> = {
'helpDialog.item.openCommandPalette': '명령 팔레트 열기',
'helpDialog.item.showKeyboardShortcuts': '키보드 단축키 보기(이 대화상자)',
'helpDialog.item.toggleSessionSidebar': '토글 세션 사이드바',
'helpDialog.item.addSelectionToChat': '선택 내용을 채팅에 추가',
'helpDialog.item.cycleAgent': '에이전트 순환(채팅 입력)',
'helpDialog.item.openModelSelector': '모델 선택기 열기',
'helpDialog.item.navigateModels': '모델 이동(선택기)',
@@ -825,6 +825,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': 'Przełącz panel kontekstu planu',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Przełącz panel kontekstu',
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Przełącz menu usług',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Dodaj zaznaczenie do czatu',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Przełącz pasek boczny',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': 'Przełącz dokowanie terminala',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Przełącz rozszerzony terminal',
+1
View File
@@ -2325,6 +2325,7 @@ export const dict: Record<I18nKey, string> = {
'helpDialog.item.toggleRightSidebar': 'Przełącz panel kontekstu',
'helpDialog.item.toggleServicesMenu': 'Przełącz menu usług',
'helpDialog.item.toggleSessionSidebar': 'Przełącz panel sesji',
'helpDialog.item.addSelectionToChat': 'Dodaj zaznaczenie do czatu',
'helpDialog.item.toggleTerminalDock': 'Przełącz dolny terminal',
'helpDialog.item.toggleTerminalExpanded': 'Przełącz rozszerzenie terminala',
'helpDialog.keyCombiner.or': 'lub',
@@ -1071,6 +1071,7 @@ export const settingsDict = {
"settings.openchamber.keyboardShortcuts.action.open_settings.label": "Abrir configurações",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal.label": "Mostrar ou ocultar painel de terminal",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir ou recolher terminal",
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Adicionar seleção ao chat",
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar ou ocultar barra lateral",
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Alternar painel de contexto',
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Abrir superfície do Git',
@@ -1656,6 +1656,7 @@ export const dict: Record<I18nKey, string> = {
"helpDialog.item.openCommandPalette": "Abrir paleta de comandos",
"helpDialog.item.showKeyboardShortcuts": "Mostrar atalhos de teclado (este diálogo)",
"helpDialog.item.toggleSessionSidebar": "Mostrar ou ocultar barra lateral de sessão",
"helpDialog.item.addSelectionToChat": "Adicionar seleção ao chat",
"helpDialog.item.cycleAgent": "Alternar agente (entrada do chat)",
"helpDialog.item.openModelSelector": "Abrir seletor de modelos",
"helpDialog.item.navigateModels": "Navegar por modelos (no seletor)",
@@ -1071,6 +1071,7 @@ export const settingsDict = {
"settings.openchamber.keyboardShortcuts.action.open_settings.label": "Відкрити налаштування",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal.label": "Перемкнути панель терміналу",
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Розгорнути або згорнути термінал",
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Додати виділення в чат",
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Перемкнути бічну панель",
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Перемкнути контекстну панель',
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Відкрити поверхню Git',
+1
View File
@@ -1656,6 +1656,7 @@ export const dict: Record<I18nKey, string> = {
"helpDialog.item.openCommandPalette": "Відкрити палітру команд",
"helpDialog.item.showKeyboardShortcuts": "Показати комбінації клавіш (це діалогове вікно)",
"helpDialog.item.toggleSessionSidebar": "Перемкнути бічну панель сесій",
"helpDialog.item.addSelectionToChat": "Додати виділення в чат",
"helpDialog.item.cycleAgent": "Перемкнути агента (введення в чат)",
"helpDialog.item.openModelSelector": "Відкрити засіб вибору моделі",
"helpDialog.item.navigateModels": "Навігація моделями (у засобі вибору)",
@@ -1071,6 +1071,7 @@ export const settingsDict = {
'settings.openchamber.keyboardShortcuts.action.open_settings.label': '打开设置',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': '切换终端停靠区',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切换终端展开',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '将选中内容添加到聊天',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切换侧边栏',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '切换上下文面板',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': '打开 Git 界面',
@@ -1644,6 +1644,7 @@ export const dict: Record<I18nKey, string> = {
'helpDialog.item.openCommandPalette': '打开命令面板',
'helpDialog.item.showKeyboardShortcuts': '显示键盘快捷键(此对话框)',
'helpDialog.item.toggleSessionSidebar': '切换会话侧边栏',
'helpDialog.item.addSelectionToChat': '将选中内容添加到聊天',
'helpDialog.item.cycleAgent': '循环切换智能体(聊天输入)',
'helpDialog.item.openModelSelector': '打开模型选择器',
'helpDialog.item.navigateModels': '导航模型(选择器中)',
@@ -978,6 +978,7 @@
'settings.openchamber.keyboardShortcuts.action.open_settings.label': '開啟設定',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal.label': '切換終端機停靠區',
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切換終端機展開',
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '將選取內容加入聊天',
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切換側邊欄',
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '切換上下文面板',
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': '開啟 Git 介面',
@@ -1648,6 +1648,7 @@ export const dict: Record<I18nKey, string> = {
'helpDialog.item.openCommandPalette': '開啟命令面板',
'helpDialog.item.showKeyboardShortcuts': '顯示鍵盤快速鍵(此對話方塊)',
'helpDialog.item.toggleSessionSidebar': '切換會話側邊欄',
'helpDialog.item.addSelectionToChat': '將選取內容加入聊天',
'helpDialog.item.cycleAgent': '循環切換 Agent(聊天輸入)',
'helpDialog.item.openModelSelector': '開啟模型選擇器',
'helpDialog.item.navigateModels': '導覽模型(選擇器中)',
+8 -1
View File
@@ -159,8 +159,15 @@ const SHORTCUT_ACTIONS: ReadonlyArray<ShortcutAction> = [
description: 'Toggle the files panel',
},
{
id: 'toggle_sidebar',
id: 'add_selection_to_chat',
defaultCombo: 'mod+l',
label: 'Add selection to chat',
description: 'Add the selected text to the chat input',
customizable: true,
},
{
id: 'toggle_sidebar',
defaultCombo: 'mod+alt+l',
label: 'Toggle sidebar',
description: 'Toggle the session sidebar',
customizable: true,