Skip to content

Commit 028f4f3

Browse files
authored
feat(amazonq): add keybinding shortcut for stop/reject/run shell commands (#7655)
## Problem Currently, users need to manually click buttons or use the command palette to execute common shell commands (reject/run/stop) in the IDE. This creates friction in the developer workflow, especially for power users who prefer keyboard shortcuts. ## Solution Reopen [Na's PR](#7178) that added keyboard shortcuts for reject/run/stop shell commands Update to align with new requirements. Add VS Code feature flag (shortcut) ## Screenshots https://github.com/user-attachments/assets/8a87d38f-e696-4d78-be27-ce9a710e85dd --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent bccb5a1 commit 028f4f3

File tree

6 files changed

+69
-2
lines changed

6 files changed

+69
-2
lines changed

docs/lsp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ sequenceDiagram
2525
```
2626

2727
## Language Server Debugging
28+
2829
If you want to connect a local version of language-servers to aws-toolkit-vscode, follow these steps:
2930

3031
1. Clone https://github.com/aws/language-servers.git and set it up in the same workspace as this project by cmd+shift+p and "add folder to workspace" and selecting the language-servers folder that you just cloned. Your VS code folder structure should look like below.
@@ -57,13 +58,16 @@ If you want to connect a local version of language-servers to aws-toolkit-vscode
5758
6. (Optional): Enable `"amazonq.trace.server": "on"` or `"amazonq.trace.server": "verbose"` in your VSCode settings to view detailed log messages sent to/from the language server. These log messages will show up in the "Amazon Q Language Server" output channel
5859
5960
### Breakpoints Work-Around
61+
6062
If the breakpoints in your language-servers project remain greyed out and do not trigger when you run `Launch LSP with Debugging`, your debugger may be attaching to the language server before it has launched. You can follow the work-around below to avoid this problem. If anyone fixes this issue, please remove this section.
63+
6164
1. Set your breakpoints and click `Launch LSP with Debugging`
6265
2. Once the debugging session has started, click `Launch LSP with Debugging` again, then `Cancel` on any pop-ups that appear
6366
3. On the debug panel, click `Attach to Language Server (amazonq)` next to the red stop button
6467
4. Click `Launch LSP with Debugging` again, then `Cancel` on any pop-ups that appear
6568
6669
## Language Server Runtimes Debugging
70+
6771
If you want to connect a local version of language-server-runtimes to aws-toolkit-vscode, follow these steps:
6872
6973
1. Clone https://github.com/aws/language-server-runtimes.git and set it up in the same workspace as this project by cmd+shift+p and "add folder to workspace" and selecting the language-server-runtimes folder that you just cloned. Your VS code folder structure should look like below.
@@ -75,6 +79,7 @@ If you want to connect a local version of language-server-runtimes to aws-toolki
7579
/amazonq
7680
/language-server-runtimes
7781
```
82+
7883
2. Inside of the language-server-runtimes project run:
7984
```
8085
npm install

packages/amazonq/package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,21 @@
554554
]
555555
},
556556
"commands": [
557+
{
558+
"command": "aws.amazonq.stopCmdExecution",
559+
"title": "Stop Amazon Q Command Execution",
560+
"category": "%AWS.amazonq.title%"
561+
},
562+
{
563+
"command": "aws.amazonq.runCmdExecution",
564+
"title": "Run Amazon Q Command Execution",
565+
"category": "%AWS.amazonq.title%"
566+
},
567+
{
568+
"command": "aws.amazonq.rejectCmdExecution",
569+
"title": "Reject Amazon Q Command Execution",
570+
"category": "%AWS.amazonq.title%"
571+
},
557572
{
558573
"command": "_aws.amazonq.notifications.dismiss",
559574
"title": "%AWS.generic.dismiss%",
@@ -843,6 +858,24 @@
843858
}
844859
],
845860
"keybindings": [
861+
{
862+
"command": "aws.amazonq.stopCmdExecution",
863+
"key": "ctrl+shift+backspace",
864+
"mac": "cmd+shift+backspace",
865+
"when": "aws.amazonq.amazonqChatLSP.isRunning"
866+
},
867+
{
868+
"command": "aws.amazonq.runCmdExecution",
869+
"key": "ctrl+shift+enter",
870+
"mac": "cmd+shift+enter",
871+
"when": "aws.amazonq.amazonqChatLSP.isRunning"
872+
},
873+
{
874+
"command": "aws.amazonq.rejectCmdExecution",
875+
"key": "ctrl+shift+r",
876+
"mac": "cmd+shift+r",
877+
"when": "aws.amazonq.amazonqChatLSP.isRunning"
878+
},
846879
{
847880
"command": "_aws.amazonq.focusChat.keybinding",
848881
"win": "win+alt+i",

packages/amazonq/src/lsp/chat/commands.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ export function registerCommands(provider: AmazonQChatViewProvider) {
7878
params: {},
7979
})
8080
})
81-
})
81+
}),
82+
registerShellCommandShortCut('aws.amazonq.runCmdExecution', 'run-shell-command', provider),
83+
registerShellCommandShortCut('aws.amazonq.rejectCmdExecution', 'reject-shell-command', provider),
84+
registerShellCommandShortCut('aws.amazonq.stopCmdExecution', 'stop-shell-command', provider)
8285
)
8386
}
8487

@@ -123,3 +126,14 @@ export async function focusAmazonQPanel() {
123126
await Commands.tryExecute('aws.amazonq.AmazonQChatView.focus')
124127
await Commands.tryExecute('aws.amazonq.AmazonCommonAuth.focus')
125128
}
129+
130+
function registerShellCommandShortCut(commandName: string, buttonId: string, provider: AmazonQChatViewProvider) {
131+
return Commands.register(commandName, async () => {
132+
void focusAmazonQPanel().then(() => {
133+
void provider.webview?.postMessage({
134+
command: 'aws/chat/executeShellCommandShortCut',
135+
params: { id: buttonId },
136+
})
137+
})
138+
})
139+
}

packages/amazonq/src/lsp/chat/webviewProvider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Webview,
1414
} from 'vscode'
1515
import * as path from 'path'
16+
import * as os from 'os'
1617
import {
1718
globals,
1819
isSageMaker,
@@ -149,7 +150,7 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
149150
const vscodeApi = acquireVsCodeApi()
150151
const hybridChatConnector = new HybridChatAdapter(${(await AuthUtil.instance.getChatAuthState()).amazonQ === 'connected'},${featureConfigData},${welcomeCount},${disclaimerAcknowledged},${regionProfileString},${disabledCommands},${isSMUS},${isSM},vscodeApi.postMessage)
151152
const commands = [hybridChatConnector.initialQuickActions[0]]
152-
qChat = amazonQChat.createChat(vscodeApi, {disclaimerAcknowledged: ${disclaimerAcknowledged}, pairProgrammingAcknowledged: ${pairProgrammingAcknowledged}, agenticMode: true, quickActionCommands: commands, modelSelectionEnabled: ${modelSelectionEnabled}}, hybridChatConnector, ${JSON.stringify(featureConfigData)});
153+
qChat = amazonQChat.createChat(vscodeApi, {os: "${os.platform()}", disclaimerAcknowledged: ${disclaimerAcknowledged}, pairProgrammingAcknowledged: ${pairProgrammingAcknowledged}, agenticMode: true, quickActionCommands: commands, modelSelectionEnabled: ${modelSelectionEnabled}}, hybridChatConnector, ${JSON.stringify(featureConfigData)});
153154
}
154155
window.addEventListener('message', (event) => {
155156
/**

packages/amazonq/src/lsp/client.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
getClientId,
3939
extensionVersion,
4040
isSageMaker,
41+
setContext,
4142
} from 'aws-core-vscode/shared'
4243
import { processUtils } from 'aws-core-vscode/shared'
4344
import { activate } from './chat/activation'
@@ -164,6 +165,7 @@ export async function startLanguageServer(
164165
pinnedContextEnabled: true,
165166
imageContextEnabled: true,
166167
mcp: true,
168+
shortcut: true,
167169
reroute: true,
168170
modelSelection: true,
169171
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,
@@ -247,6 +249,17 @@ async function onLanguageServerReady(
247249

248250
if (Experiments.instance.get('amazonqChatLSP', true)) {
249251
await activate(client, encryptionKey, resourcePaths.ui)
252+
253+
await setContext('aws.amazonq.amazonqChatLSP.isRunning', true)
254+
getLogger().info('Amazon Q Chat LSP context flag set on client activated')
255+
256+
// Add a disposable to reset the context flag when the client stops
257+
toDispose.push({
258+
dispose: async () => {
259+
await setContext('aws.amazonq.amazonqChatLSP.isRunning', false)
260+
getLogger().info('Amazon Q Chat LSP context flag reset on client disposal')
261+
},
262+
})
250263
}
251264

252265
const refreshInterval = auth.startTokenRefreshInterval(10 * oneSecond)

packages/core/src/shared/vscode/setContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export type contextKey =
4040
| 'gumby.wasQCodeTransformationUsed'
4141
| 'amazonq.inline.codelensShortcutEnabled'
4242
| 'aws.toolkit.lambda.walkthroughSelected'
43+
| 'aws.amazonq.amazonqChatLSP.isRunning'
4344

4445
const contextMap: Partial<Record<contextKey, any>> = {}
4546

0 commit comments

Comments
 (0)