diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml b/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml index f1df792e004..8b7e5614ddb 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml +++ b/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml @@ -81,9 +81,31 @@ + text="Invoke Amazon Q Inline Suggestions"> + + + + + + + + + + + + + + , context: DataContext): MutableList { val results = actions.toMutableList() + if (!CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive()) return results + results.sortWith { a, b -> - if (isCodeWhispererPopupAction(a)) { + if (isCodeWhispererForceAction(a)) { + return@sortWith -1 + } else if (isCodeWhispererForceAction(b)) { + return@sortWith 1 + } + + if (a is ChooseItemAction) { return@sortWith -1 - } else if (isCodeWhispererPopupAction(b)) { + } else if (b is ChooseItemAction) { return@sortWith 1 - } else { - 0 } + + if (isCodeWhispererAcceptAction(a)) { + return@sortWith -1 + } else if (isCodeWhispererAcceptAction(b)) { + return@sortWith 1 + } + + 0 } return results } private fun isCodeWhispererAcceptAction(action: AnAction): Boolean = - action is EditorAction && action.handler is CodeWhispererPopupTabHandler + action is CodeWhispererAcceptAction + + private fun isCodeWhispererForceAcceptAction(action: AnAction): Boolean = + action is CodeWhispererForceAcceptAction private fun isCodeWhispererNavigateAction(action: AnAction): Boolean = - action is EditorAction && ( - action.handler is CodeWhispererPopupRightArrowHandler || - action.handler is CodeWhispererPopupLeftArrowHandler - ) + action is CodeWhispererNavigateNextAction || action is CodeWhispererNavigatePrevAction - private fun isCodeWhispererPopupAction(action: AnAction): Boolean = - isCodeWhispererAcceptAction(action) || isCodeWhispererNavigateAction(action) + private fun isCodeWhispererForceAction(action: AnAction): Boolean = + isCodeWhispererForceAcceptAction(action) || isCodeWhispererNavigateAction(action) } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigateNextAction.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigateNextAction.kt new file mode 100644 index 00000000000..ed02c8803a4 --- /dev/null +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigateNextAction.kt @@ -0,0 +1,33 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.codewhisperer.actions + +import com.intellij.openapi.actionSystem.ActionUpdateThread +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.DumbAware +import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService +import software.aws.toolkits.resources.message + +class CodeWhispererNavigateNextAction : AnAction(message("codewhisperer.inline.navigate.next")), DumbAware { + override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT + + override fun update(e: AnActionEvent) { + e.presentation.isEnabled = e.project != null && + e.getData(CommonDataKeys.EDITOR) != null && + CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive() + } + + override fun actionPerformed(e: AnActionEvent) { + val sessionContext = e.project?.getUserData(CodeWhispererService.KEY_SESSION_CONTEXT) ?: return + if (!CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive()) return + ApplicationManager.getApplication().messageBus.syncPublisher( + CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED + ).navigateNext(sessionContext) + } +} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigatePrevAction.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigatePrevAction.kt new file mode 100644 index 00000000000..118f7738213 --- /dev/null +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/CodeWhispererNavigatePrevAction.kt @@ -0,0 +1,33 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.codewhisperer.actions + +import com.intellij.openapi.actionSystem.ActionUpdateThread +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.DumbAware +import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService +import software.aws.toolkits.resources.message + +class CodeWhispererNavigatePrevAction : AnAction(message("codewhisperer.inline.navigate.previous")), DumbAware { + override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT + + override fun update(e: AnActionEvent) { + e.presentation.isEnabled = e.project != null && + e.getData(CommonDataKeys.EDITOR) != null && + CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive() + } + + override fun actionPerformed(e: AnActionEvent) { + val sessionContext = e.project?.getUserData(CodeWhispererService.KEY_SESSION_CONTEXT) ?: return + if (!CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive()) return + ApplicationManager.getApplication().messageBus.syncPublisher( + CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED + ).navigatePrevious(sessionContext) + } +} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/ConnectWithAwsToContinueActionWarn.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/ConnectWithAwsToContinueActionWarn.kt deleted file mode 100644 index 0c19cfcff97..00000000000 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/ConnectWithAwsToContinueActionWarn.kt +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package software.aws.toolkits.jetbrains.services.codewhisperer.actions - -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.application.runInEdt -import com.intellij.openapi.project.DumbAwareAction -import software.aws.toolkits.jetbrains.core.gettingstarted.requestCredentialsForCodeWhisperer -import software.aws.toolkits.resources.message - -/** - * Action prompting users to switch to SSO based credential, will nullify accountless credential (delete) - */ -class ConnectWithAwsToContinueActionWarn : DumbAwareAction(message("codewhisperer.notification.accountless.warn.action.connect")) { - override fun actionPerformed(e: AnActionEvent) { - e.project?.let { - runInEdt { - requestCredentialsForCodeWhisperer(it) - } - } - } -} -class ConnectWithAwsToContinueActionError : DumbAwareAction(message("codewhisperer.notification.accountless.error.action.connect")) { - override fun actionPerformed(e: AnActionEvent) { - e.project?.let { - runInEdt { - requestCredentialsForCodeWhisperer(it) - } - } - } -} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupComponents.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupComponents.kt index fcf2279f478..d1ce0c87ff3 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupComponents.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupComponents.kt @@ -6,11 +6,16 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup import com.intellij.icons.AllIcons import com.intellij.ide.BrowserUtil import com.intellij.idea.AppMode +import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.ActionPlaces import com.intellij.openapi.actionSystem.ActionToolbar import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.actionSystem.KeyboardShortcut import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.actionSystem.impl.ActionButton +import com.intellij.openapi.keymap.KeymapUtil +import com.intellij.openapi.keymap.MacKeymapUtil +import com.intellij.openapi.util.SystemInfo import com.intellij.ui.IdeBorderFactory import com.intellij.ui.components.ActionLink import com.intellij.util.ui.UIUtil @@ -43,10 +48,33 @@ import javax.swing.JPanel class CodeWhispererPopupComponents { val prevButton = createNavigationButton( - message("codewhisperer.popup.button.prev", POPUP_DIM_HEX) + message( + "codewhisperer.popup.button.prev", + POPUP_DIM_HEX, + run { + // TODO: Doesn't reflect dynamically if users change but didn't restart IDE + val shortcut = ActionManager.getInstance().getAction("codewhisperer.inline.navigate.previous") + .shortcutSet.shortcuts.first() + val keyStroke = (shortcut as KeyboardShortcut).firstKeyStroke + if (SystemInfo.isMac) { + MacKeymapUtil.getKeyStrokeText(keyStroke, " ", true) + } else { + KeymapUtil.getKeystrokeText(keyStroke) + } + } + ) ) val nextButton = createNavigationButton( - message("codewhisperer.popup.button.next", POPUP_DIM_HEX) + message( + "codewhisperer.popup.button.next", + POPUP_DIM_HEX, + run { + // TODO: Doesn't reflect dynamically if users change but didn't restart IDE + KeymapUtil.getFirstKeyboardShortcutText( + ActionManager.getInstance().getAction("codewhisperer.inline.navigate.next") + ) + } + ) ).apply { preferredSize = prevButton.preferredSize } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt index 1bdd36ee42b..bc5e1a8e06e 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt @@ -6,8 +6,10 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup import com.intellij.codeInsight.hint.ParameterInfoController import com.intellij.codeInsight.lookup.LookupManager import com.intellij.idea.AppMode +import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_BACKSPACE import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ENTER +import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ESCAPE import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_TAB @@ -44,6 +46,10 @@ import software.amazon.awssdk.services.codewhispererruntime.model.Import import software.amazon.awssdk.services.codewhispererruntime.model.Reference import software.aws.toolkits.core.utils.debug import software.aws.toolkits.core.utils.getLogger +import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererAcceptAction +import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererForceAcceptAction +import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererNavigateNextAction +import software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererNavigatePrevAction import software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEditorManager import software.aws.toolkits.jetbrains.services.codewhisperer.layout.CodeWhispererLayoutConfig.addHorizontalGlue import software.aws.toolkits.jetbrains.services.codewhisperer.layout.CodeWhispererLayoutConfig.horizontalPanelConstraints @@ -55,8 +61,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionConte import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererEditorActionHandler import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupBackspaceHandler import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupEnterHandler -import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupLeftArrowHandler -import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupRightArrowHandler +import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupEscHandler import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupTabHandler import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.CodeWhispererPopupTypedHandler import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererAcceptButtonActionListener @@ -66,6 +71,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.Co import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService +import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererColorUtil.POPUP_DIM_HEX import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.POPUP_INFO_TEXT_SIZE @@ -373,41 +379,44 @@ class CodeWhispererPopupManager { ) } - private fun addButtonActionListeners(states: InvocationContext) { - popupComponents.prevButton.addButtonActionListener(CodeWhispererPrevButtonActionListener(states)) - popupComponents.nextButton.addButtonActionListener(CodeWhispererNextButtonActionListener(states)) - popupComponents.acceptButton.addButtonActionListener(CodeWhispererAcceptButtonActionListener(states)) + private fun addButtonActionListeners(sessionContext: SessionContext) { + popupComponents.prevButton.addButtonActionListener(CodeWhispererPrevButtonActionListener(sessionContext), sessionContext) + popupComponents.nextButton.addButtonActionListener(CodeWhispererNextButtonActionListener(sessionContext), sessionContext) + popupComponents.acceptButton.addButtonActionListener(CodeWhispererAcceptButtonActionListener(sessionContext), sessionContext) } - private fun JButton.addButtonActionListener(listener: CodeWhispererActionListener) { + private fun JButton.addButtonActionListener(listener: CodeWhispererActionListener, sessionContext: SessionContext) { this.addActionListener(listener) - Disposer.register(listener.states) { this.removeActionListener(listener) } + Disposer.register(sessionContext) { this.removeActionListener(listener) } } - private fun setPopupActionHandlers(states: InvocationContext) { + private fun setPopupActionHandlers(sessionContext: SessionContext) { val actionManager = EditorActionManager.getInstance() - setPopupTypedHandler(CodeWhispererPopupTypedHandler(TypedAction.getInstance().rawHandler, states)) - setPopupActionHandler(ACTION_EDITOR_TAB, CodeWhispererPopupTabHandler(states)) - setPopupActionHandler(ACTION_EDITOR_MOVE_CARET_LEFT, CodeWhispererPopupLeftArrowHandler(states)) - setPopupActionHandler(ACTION_EDITOR_MOVE_CARET_RIGHT, CodeWhispererPopupRightArrowHandler(states)) + + sessionContext.project.putUserData(CodeWhispererService.KEY_SESSION_CONTEXT, sessionContext) + + setPopupTypedHandler(CodeWhispererPopupTypedHandler(TypedAction.getInstance().rawHandler, sessionContext), sessionContext) + setPopupActionHandler(ACTION_EDITOR_ESCAPE, CodeWhispererPopupEscHandler(sessionContext), sessionContext) setPopupActionHandler( ACTION_EDITOR_ENTER, - CodeWhispererPopupEnterHandler(actionManager.getActionHandler(ACTION_EDITOR_ENTER), states) + CodeWhispererPopupEnterHandler(actionManager.getActionHandler(ACTION_EDITOR_ENTER), sessionContext), + sessionContext ) setPopupActionHandler( ACTION_EDITOR_BACKSPACE, - CodeWhispererPopupBackspaceHandler(actionManager.getActionHandler(ACTION_EDITOR_BACKSPACE), states) + CodeWhispererPopupBackspaceHandler(actionManager.getActionHandler(ACTION_EDITOR_BACKSPACE), sessionContext), + sessionContext ) } - private fun setPopupTypedHandler(newHandler: CodeWhispererPopupTypedHandler) { + private fun setPopupTypedHandler(newHandler: CodeWhispererPopupTypedHandler, sessionContext: SessionContext) { val oldTypedHandler = TypedAction.getInstance().setupRawHandler(newHandler) - Disposer.register(newHandler.states) { TypedAction.getInstance().setupRawHandler(oldTypedHandler) } + Disposer.register(sessionContext) { TypedAction.getInstance().setupRawHandler(oldTypedHandler) } } - private fun setPopupActionHandler(id: String, newHandler: CodeWhispererEditorActionHandler) { + private fun setPopupActionHandler(id: String, newHandler: CodeWhispererEditorActionHandler, sessionContext: SessionContext) { val oldHandler = EditorActionManager.getInstance().setActionHandler(id, newHandler) - Disposer.register(newHandler.states) { EditorActionManager.getInstance().setActionHandler(id, oldHandler) } + Disposer.register(sessionContext) { EditorActionManager.getInstance().setActionHandler(id, oldHandler) } } private fun addComponentListeners(sessionContext: SessionContext) { diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererEditorActionHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererEditorActionHandler.kt index 0e02fb260bf..a2cea3c836f 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererEditorActionHandler.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererEditorActionHandler.kt @@ -4,6 +4,6 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers import com.intellij.openapi.editor.actionSystem.EditorActionHandler -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext -abstract class CodeWhispererEditorActionHandler(val states: InvocationContext) : EditorActionHandler() +abstract class CodeWhispererEditorActionHandler(val sessionContext: SessionContext) : EditorActionHandler() diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupBackspaceHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupBackspaceHandler.kt index ec2b656c6f4..cdd510a31eb 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupBackspaceHandler.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupBackspaceHandler.kt @@ -8,15 +8,16 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.actionSystem.EditorActionHandler -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager class CodeWhispererPopupBackspaceHandler( private val defaultHandler: EditorActionHandler, - states: InvocationContext, -) : CodeWhispererEditorActionHandler(states) { + sessionContext: SessionContext +) : CodeWhispererEditorActionHandler(sessionContext) { override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { val popupManager = CodeWhispererPopupManager.getInstance() + popupManager.dontClosePopupAndRun { val oldOffset = editor.caretModel.offset defaultHandler.execute(editor, caret, dataContext) @@ -24,7 +25,7 @@ class CodeWhispererPopupBackspaceHandler( val newText = "a".repeat(oldOffset - newOffset) ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).backspace(states, newText) + ).backspace(sessionContext, newText) } } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEnterHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEnterHandler.kt index 25dc0a7c6ba..a36177f579e 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEnterHandler.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEnterHandler.kt @@ -1,21 +1,19 @@ // Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 - package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers - import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.actionSystem.EditorActionHandler import com.intellij.openapi.util.TextRange -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager class CodeWhispererPopupEnterHandler( private val defaultHandler: EditorActionHandler, - states: InvocationContext, -) : CodeWhispererEditorActionHandler(states) { + sessionContext: SessionContext +) : CodeWhispererEditorActionHandler(sessionContext) { override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { val popupManager = CodeWhispererPopupManager.getInstance() popupManager.dontClosePopupAndRun { @@ -25,7 +23,7 @@ class CodeWhispererPopupEnterHandler( val newText = editor.document.getText(TextRange.create(oldOffset, newOffset)) ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).enter(states, newText) + ).enter(sessionContext, newText) } } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEscHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEscHandler.kt new file mode 100644 index 00000000000..634f76e885a --- /dev/null +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupEscHandler.kt @@ -0,0 +1,16 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers + +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.editor.Caret +import com.intellij.openapi.editor.Editor +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService + +class CodeWhispererPopupEscHandler(sessionContext: SessionContext) : CodeWhispererEditorActionHandler(sessionContext) { + override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { + CodeWhispererService.getInstance().disposeDisplaySession(false) + } +} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupLeftArrowHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupLeftArrowHandler.kt deleted file mode 100644 index 020e1434808..00000000000 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupLeftArrowHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers - -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.Caret -import com.intellij.openapi.editor.Editor -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext -import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager - -class CodeWhispererPopupLeftArrowHandler(states: InvocationContext) : CodeWhispererEditorActionHandler(states) { - override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { - ApplicationManager.getApplication().messageBus.syncPublisher( - CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).navigatePrevious(states) - } -} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupRightArrowHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupRightArrowHandler.kt deleted file mode 100644 index 9efba65a80b..00000000000 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupRightArrowHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers - -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.Caret -import com.intellij.openapi.editor.Editor -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext -import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager - -class CodeWhispererPopupRightArrowHandler(states: InvocationContext) : CodeWhispererEditorActionHandler(states) { - override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { - ApplicationManager.getApplication().messageBus.syncPublisher( - CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).navigateNext(states) - } -} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTabHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTabHandler.kt deleted file mode 100644 index c92eae91062..00000000000 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTabHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers - -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.Caret -import com.intellij.openapi.editor.Editor -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext -import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager - -class CodeWhispererPopupTabHandler(states: InvocationContext) : CodeWhispererEditorActionHandler(states) { - override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { - ApplicationManager.getApplication().messageBus.syncPublisher( - CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).beforeAccept(states, CodeWhispererPopupManager.getInstance().sessionContext) - } -} diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTypedHandler.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTypedHandler.kt index 7e18feaf3e0..501409dc4ce 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTypedHandler.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/handlers/CodeWhispererPopupTypedHandler.kt @@ -7,19 +7,19 @@ import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.actionSystem.TypedActionHandler -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager class CodeWhispererPopupTypedHandler( private val defaultHandler: TypedActionHandler, - val states: InvocationContext, + val sessionContext: SessionContext ) : TypedActionHandler { override fun execute(editor: Editor, charTyped: Char, dataContext: DataContext) { CodeWhispererPopupManager.getInstance().dontClosePopupAndRun { defaultHandler.execute(editor, charTyped, dataContext) ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).type(states, charTyped.toString()) + ).type(sessionContext, charTyped.toString()) } } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererActionListener.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererActionListener.kt index c04f8cc444c..23f0975e66e 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererActionListener.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererActionListener.kt @@ -3,7 +3,7 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import java.awt.event.ActionListener -abstract class CodeWhispererActionListener(val states: InvocationContext) : ActionListener +abstract class CodeWhispererActionListener(val sessionContext: SessionContext) : ActionListener diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererNextButtonActionListener.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererNextButtonActionListener.kt index ce1d34432ee..d11f219a330 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererNextButtonActionListener.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererNextButtonActionListener.kt @@ -4,14 +4,14 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners import com.intellij.openapi.application.ApplicationManager -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager import java.awt.event.ActionEvent -class CodeWhispererNextButtonActionListener(states: InvocationContext) : CodeWhispererActionListener(states) { +class CodeWhispererNextButtonActionListener(sessionContext: SessionContext) : CodeWhispererActionListener(sessionContext) { override fun actionPerformed(e: ActionEvent?) { ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).navigateNext(states) + ).navigateNext(sessionContext) } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererPrevButtonActionListener.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererPrevButtonActionListener.kt index e77fdf469b5..273a40a8e16 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererPrevButtonActionListener.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererPrevButtonActionListener.kt @@ -4,14 +4,14 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners import com.intellij.openapi.application.ApplicationManager -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager import java.awt.event.ActionEvent -class CodeWhispererPrevButtonActionListener(states: InvocationContext) : CodeWhispererActionListener(states) { +class CodeWhispererPrevButtonActionListener(sessionContext: SessionContext) : CodeWhispererActionListener(sessionContext) { override fun actionPerformed(e: ActionEvent?) { ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_USER_ACTION_PERFORMED - ).navigatePrevious(states) + ).navigatePrevious(sessionContext) } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererScrollListener.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererScrollListener.kt index f1dfab068a8..4ebea981628 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererScrollListener.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/listeners/CodeWhispererScrollListener.kt @@ -6,20 +6,20 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.event.VisibleAreaEvent import com.intellij.openapi.editor.event.VisibleAreaListener -import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext +import software.aws.toolkits.jetbrains.services.codewhisperer.model.SessionContext import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus -class CodeWhispererScrollListener(private val states: InvocationContext) : VisibleAreaListener { +class CodeWhispererScrollListener(private val sessionContext: SessionContext) : VisibleAreaListener { override fun visibleAreaChanged(e: VisibleAreaEvent) { val oldRect = e.oldRectangle val newRect = e.newRectangle - if (CodeWhispererInvocationStatus.getInstance().isPopupActive() && + if (CodeWhispererInvocationStatus.getInstance().isDisplaySessionActive() && (oldRect.x != newRect.x || oldRect.y != newRect.y) ) { ApplicationManager.getApplication().messageBus.syncPublisher( CodeWhispererPopupManager.CODEWHISPERER_POPUP_STATE_CHANGED - ).scrolled(states, CodeWhispererPopupManager.getInstance().sessionContext) + ).scrolled(sessionContext) } } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt index 80d01722c57..857452934f3 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt @@ -17,6 +17,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.VisualPosition import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.Key import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile import com.intellij.util.concurrency.annotations.RequiresEdt @@ -807,7 +808,7 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable { "CodeWhisperer code completion service invoked", CodeWhispererCodeCompletionServiceListener::class.java ) - val DATA_KEY_SESSION = DataKey.create("codewhisperer.session") + val KEY_SESSION_CONTEXT = Key.create("codewhisperer.session") fun getInstance(): CodeWhispererService = service() const val KET_SESSION_ID = "x-amzn-SessionId" diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt index 9db80018184..107f83059b3 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt @@ -4,13 +4,17 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.settings import com.intellij.icons.AllIcons +import com.intellij.ide.DataManager import com.intellij.openapi.options.BoundConfigurable +import com.intellij.openapi.options.Configurable import com.intellij.openapi.options.SearchableConfigurable +import com.intellij.openapi.options.ex.Settings import com.intellij.openapi.project.Project -import com.intellij.ui.dsl.builder.AlignX +import com.intellij.ui.components.ActionLink import com.intellij.ui.dsl.builder.bindIntText import com.intellij.ui.dsl.builder.bindSelected import com.intellij.ui.dsl.builder.panel +import com.intellij.util.concurrency.EdtExecutorService import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManagerListener import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererLoginType @@ -18,6 +22,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhisp import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.isCodeWhispererEnabled import software.aws.toolkits.resources.message import java.awt.Font +import java.util.concurrent.TimeUnit // As the connection is project-level, we need to make this project-level too (we have different config for Sono vs SSO users) class CodeWhispererConfigurable(private val project: Project) : @@ -87,6 +92,21 @@ class CodeWhispererConfigurable(private val project: Project) : bindSelected(codeWhispererSettings::isImportAdderEnabled, codeWhispererSettings::toggleImportAdder) }.comment(message("aws.settings.codewhisperer.automatic_import_adder.tooltip")) } + + row { + link("Configure inline suggestion keybindings") { e -> + // TODO: user needs feedback if these are null + val settings = DataManager.getInstance().getDataContext(e.source as ActionLink).getData(Settings.KEY) ?: return@link + val configurable: Configurable = settings.find("preferences.keymap") ?: return@link + + settings.select(configurable, Q_INLINE_KEYBINDING_SEARCH_TEXT) + + // workaround for certain cases for sometimes the string is not input there + EdtExecutorService.getScheduledExecutorInstance().schedule({ + settings.select(configurable, Q_INLINE_KEYBINDING_SEARCH_TEXT) + }, 500, TimeUnit.MILLISECONDS) + } + } } group(message("aws.settings.codewhisperer.group.q_chat")) { @@ -109,7 +129,7 @@ class CodeWhispererConfigurable(private val project: Project) : intTextField( range = IntRange(0, 50) ).bindIntText(codeWhispererSettings::getProjectContextIndexThreadCount, codeWhispererSettings::setProjectContextIndexThreadCount) - .align(AlignX.FILL).apply { + .apply { connect.subscribe( ToolkitConnectionManagerListener.TOPIC, object : ToolkitConnectionManagerListener { @@ -126,7 +146,7 @@ class CodeWhispererConfigurable(private val project: Project) : intTextField( range = IntRange(1, 250) ).bindIntText(codeWhispererSettings::getProjectContextIndexMaxSize, codeWhispererSettings::setProjectContextIndexMaxSize) - .align(AlignX.FILL).apply { + .apply { connect.subscribe( ToolkitConnectionManagerListener.TOPIC, object : ToolkitConnectionManagerListener { @@ -183,4 +203,8 @@ class CodeWhispererConfigurable(private val project: Project) : } } } + + companion object { + private const val Q_INLINE_KEYBINDING_SEARCH_TEXT = "inline suggestion" + } } diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 50418a9c139..35d5ec3edb9 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -855,6 +855,10 @@ codewhisperer.gettingstarted.panel.learn_more=Learn more codewhisperer.gettingstarted.panel.learn_more.with.q=Learn more about Amazon Q and Codewhisperer codewhisperer.gettingstarted.panel.licence_comment=Already have a license? codewhisperer.gettingstarted.panel.login_button=Use for free, no AWS account required +codewhisperer.inline.accept=Accept Suggestion +codewhisperer.inline.force.accept=Force Accept Suggestion +codewhisperer.inline.navigate.next=Navigate to Next Suggestion +codewhisperer.inline.navigate.previous=Navigate to Previous Suggestion codewhisperer.language.error={0} is currently not supported by Amazon Q codewhisperer.learn_page.banner.dismiss=Dismiss codewhisperer.learn_page.banner.message.new_user=You can always return to this page by clicking "Learn" in the Amazon Q status bar menu.