add command palette widget + layout keybindings

ClidePalette renders as a floating overlay with fuzzy-filtered
command list. Ctrl+Shift+P toggles it. Ctrl+B toggles sidebar,
Ctrl+J toggles context panel. All wired through CommandRegistry
via the default layout extension.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-04-22 17:30:21 +02:00
co-authored by Claude
parent eda3b30382
commit 6592a88695
2 changed files with 220 additions and 10 deletions
@@ -22,14 +22,33 @@ class DefaultLayoutExtension extends ClideExtension {
title: 'Layout: Reset to Classic',
run: _reset,
),
CommandContribution(
id: 'palette.toggle',
command: 'palette.toggle',
title: 'Command Palette',
defaultBinding: 'ctrl+shift+p',
run: _togglePalette,
),
CommandContribution(
id: 'sidebar.toggle',
command: 'sidebar.toggle',
title: 'Toggle Sidebar',
defaultBinding: 'ctrl+b',
run: _toggleSidebar,
),
CommandContribution(
id: 'context.toggle',
command: 'context.toggle',
title: 'Toggle Context Panel',
defaultBinding: 'ctrl+j',
run: _toggleContext,
),
];
@override
Future<void> activate(ClideExtensionContext ctx) async {
_ctx = ctx;
_preset = classicPreset();
// Register the preset's slots into the panel registry and apply
// the arrangement so every SlotHost has something to render.
ctx.arrangement.registerSlotsInto(ctx.panels, _preset!);
ctx.arrangement.applyPreset(_preset!);
}
@@ -38,16 +57,41 @@ class DefaultLayoutExtension extends ClideExtension {
final preset = _preset;
final ctx = _ctx;
if (preset == null || ctx == null) {
return IpcResponse.err(
id: '',
error: IpcError(
code: IpcExitCode.toolError,
kind: IpcErrorKind.toolError,
message: 'default-layout not activated',
),
);
return _notActivated();
}
ctx.arrangement.applyPreset(preset);
return IpcResponse.ok(id: '', data: {'preset': preset.id});
}
Future<IpcResponse> _togglePalette(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();
ctx.palette.toggle();
return IpcResponse.ok(id: '', data: {'open': ctx.palette.isOpen});
}
Future<IpcResponse> _toggleSidebar(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();
final visible = ctx.arrangement.isVisible(Slots.sidebar);
ctx.arrangement.setVisible(Slots.sidebar, !visible);
return IpcResponse.ok(id: '', data: {'visible': !visible});
}
Future<IpcResponse> _toggleContext(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();
final visible = ctx.arrangement.isVisible(Slots.contextPanel);
ctx.arrangement.setVisible(Slots.contextPanel, !visible);
return IpcResponse.ok(id: '', data: {'visible': !visible});
}
static IpcResponse _notActivated() => IpcResponse.err(
id: '',
error: IpcError(
code: IpcExitCode.toolError,
kind: IpcErrorKind.toolError,
message: 'not activated',
),
);
}