mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-03 05:59:43 +02:00
fix: COD-153 support terminal-focused command palette shortcuts
This commit is contained in:
committed by
Aamer Akhter
parent
ad25e234f4
commit
c45e456b0e
@@ -482,7 +482,7 @@ Single-digit selection (1-9), color-coded status, token counts, auto-refresh. De
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl/Cmd+W` | Kill active session |
|
||||
| `Ctrl/Cmd+K` | Find open session or start a new one |
|
||||
| `Ctrl/Cmd/Option+K` | Find open session or start a new one |
|
||||
| `Ctrl/Cmd+Tab` | Next session |
|
||||
| `Alt/Option+[` / `Alt/Option+]` | Previous / next session |
|
||||
| `Alt/Option+1`-`Alt/Option+9` | Switch to tab N (physical keys, so macOS Option layouts work) |
|
||||
|
||||
@@ -573,7 +573,7 @@
|
||||
<h4>Session</h4>
|
||||
<div class="shortcuts-grid">
|
||||
<div><kbd>Ctrl</kbd>+<kbd>W</kbd></div><div>Close Session</div>
|
||||
<div><kbd>Ctrl/Cmd</kbd>+<kbd>K</kbd></div><div>Find Open Session</div>
|
||||
<div><kbd>Ctrl/Cmd/Option</kbd>+<kbd>K</kbd></div><div>Find Open Session</div>
|
||||
<div><kbd>Ctrl</kbd>+<kbd>Tab</kbd></div><div>Next Session</div>
|
||||
<div><kbd>Alt/Option</kbd>+<kbd>[</kbd> / <kbd>Alt/Option</kbd>+<kbd>]</kbd></div><div>Previous / Next Session</div>
|
||||
<div><kbd>Alt/Option</kbd>+<kbd>1-9</kbd></div><div>Switch to Tab N</div>
|
||||
|
||||
@@ -257,12 +257,17 @@ Object.assign(CodemanApp.prototype, {
|
||||
|
||||
shouldOpenCommandPaletteFromShortcut(e) {
|
||||
if (!e) return false;
|
||||
if ((e.key || '').toLowerCase() !== 'k') return false;
|
||||
if (!(e.metaKey || e.ctrlKey) || e.altKey) return false;
|
||||
const key = (e.key || '').toLowerCase();
|
||||
if (key !== 'k' && e.code !== 'KeyK') return false;
|
||||
if (!(e.metaKey || e.ctrlKey || e.altKey)) return false;
|
||||
|
||||
const target = e.target;
|
||||
if (!target) return true;
|
||||
const tagName = (target.tagName || '').toUpperCase();
|
||||
const className = typeof target.className === 'string' ? target.className : '';
|
||||
const isXtermHelper =
|
||||
target.classList?.contains?.('xterm-helper-textarea') || className.includes('xterm-helper-textarea');
|
||||
if (isXtermHelper) return true;
|
||||
if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') return false;
|
||||
if (target.isContentEditable) return false;
|
||||
if (typeof target.closest === 'function' && target.closest('[contenteditable="true"]')) return false;
|
||||
|
||||
@@ -120,12 +120,17 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.terminal.attachCustomKeyEventHandler((ev) => {
|
||||
if (ev.isComposing || ev.keyCode === 229) return false;
|
||||
|
||||
// Let the app's Alt/Option session-nav shortcuts reach the document keydown handler
|
||||
// Let the app's Alt/Option session-nav and Command Palette shortcuts reach the document keydown handler
|
||||
// (app.js switches tabs by PHYSICAL e.code) instead of xterm injecting ESC<char> into
|
||||
// the PTY. Mirror app.js's gate exactly — same physical codes + modifier guard — so
|
||||
// macOS Option layouts (Option+1 -> "¡", Option+[ -> "“") are suppressed here too and
|
||||
// macOS Option layouts (Option+1 -> "¡", Option+[ -> "“", Option+K -> "˚") are suppressed here too and
|
||||
// don't leak an escape sequence into the focused terminal on every tab switch.
|
||||
if (ev.altKey && !ev.ctrlKey && !ev.shiftKey && /^(Digit[1-9]|BracketLeft|BracketRight)$/.test(ev.code || '')) {
|
||||
if (
|
||||
ev.altKey &&
|
||||
!ev.ctrlKey &&
|
||||
!ev.shiftKey &&
|
||||
/^(Digit[1-9]|BracketLeft|BracketRight|KeyK)$/.test(ev.code || '')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,40 @@ describe('Command-K session palette', () => {
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('recognizes Ctrl-K from the focused xterm helper textarea', () => {
|
||||
const { app } = loadPaletteHarness();
|
||||
|
||||
expect(
|
||||
app.shouldOpenCommandPaletteFromShortcut({
|
||||
key: 'k',
|
||||
code: 'KeyK',
|
||||
metaKey: false,
|
||||
ctrlKey: true,
|
||||
altKey: false,
|
||||
target: {
|
||||
tagName: 'TEXTAREA',
|
||||
isContentEditable: false,
|
||||
classList: { contains: (name: string) => name === 'xterm-helper-textarea' },
|
||||
},
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('recognizes macOS Option-K by physical key code', () => {
|
||||
const { app } = loadPaletteHarness();
|
||||
|
||||
expect(
|
||||
app.shouldOpenCommandPaletteFromShortcut({
|
||||
key: '˚',
|
||||
code: 'KeyK',
|
||||
metaKey: false,
|
||||
ctrlKey: false,
|
||||
altKey: true,
|
||||
target: null,
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('opens and focuses the palette search box', () => {
|
||||
const { app, elements } = loadPaletteHarness();
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('keyboard shortcuts', () => {
|
||||
// terminal-ui.js must gate its xterm pass-through on the SAME physical e.code set the
|
||||
// app.js handler consumes; otherwise Alt+[ / Alt+] (and Option+digit on remapped macOS
|
||||
// layouts) switch tabs AND inject ESC<char> into the focused terminal. Keep in sync.
|
||||
expect(terminalUiSource).toContain('/^(Digit[1-9]|BracketLeft|BracketRight)$/.test(ev.code');
|
||||
expect(terminalUiSource).toContain('/^(Digit[1-9]|BracketLeft|BracketRight|KeyK)$/.test(ev.code');
|
||||
});
|
||||
|
||||
it('documents the Alt/Option shortcuts in help and README', () => {
|
||||
@@ -37,7 +37,7 @@ describe('keyboard shortcuts', () => {
|
||||
|
||||
it('documents the Command-K open-session palette in help and README', () => {
|
||||
expect(appSource).toContain('this.openCommandPalette()');
|
||||
expect(helpHtml).toContain('<kbd>Ctrl/Cmd</kbd>+<kbd>K</kbd>');
|
||||
expect(readme).toMatch(/\| `Ctrl\/Cmd\+K`\s+\| Find open session or start a new one\s+\|/);
|
||||
expect(helpHtml).toContain('<kbd>Ctrl/Cmd/Option</kbd>+<kbd>K</kbd>');
|
||||
expect(readme).toMatch(/\| `Ctrl\/Cmd\/Option\+K`\s+\| Find open session or start a new one\s+\|/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user