diff --git a/src/main/kotlin/ee/carlrobert/codegpt/actions/InlayActionPromoter.kt b/src/main/kotlin/ee/carlrobert/codegpt/actions/InlayActionPromoter.kt index ce000818..4405cbcb 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/actions/InlayActionPromoter.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/actions/InlayActionPromoter.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.actionSystem.DataContext import ee.carlrobert.codegpt.codecompletions.AcceptNextLineInlayAction import ee.carlrobert.codegpt.codecompletions.AcceptNextWordInlayAction +import ee.carlrobert.codegpt.predictions.OpenPredictionAction import ee.carlrobert.codegpt.predictions.TriggerCustomPredictionAction class InlayActionPromoter : ActionPromoter { @@ -14,6 +15,7 @@ class InlayActionPromoter : ActionPromoter { val editor = CommonDataKeys.EDITOR.getData(context) ?: return emptyList() actions.filterIsInstance().takeIf { it.isNotEmpty() }?.let { return it } + actions.filterIsInstance().takeIf { it.isNotEmpty() }?.let { return it } if (InlineCompletionContext.getOrNull(editor) == null) { return emptyList() diff --git a/src/main/kotlin/ee/carlrobert/codegpt/predictions/CodeSuggestionDiffViewer.kt b/src/main/kotlin/ee/carlrobert/codegpt/predictions/CodeSuggestionDiffViewer.kt index 87fb0b7b..41970fda 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/predictions/CodeSuggestionDiffViewer.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/predictions/CodeSuggestionDiffViewer.kt @@ -13,6 +13,7 @@ import com.intellij.diff.util.DiffUtil import com.intellij.ide.plugins.newui.TagComponent import com.intellij.openapi.Disposable import com.intellij.openapi.actionSystem.ActionManager +import com.intellij.openapi.components.service import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.LogicalPosition @@ -30,11 +31,14 @@ import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.UserDataHolder import com.intellij.openapi.util.UserDataHolderBase import com.intellij.testFramework.LightVirtualFile +import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBScrollPane import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.ui.JBUI import com.intellij.util.ui.components.BorderLayoutPanel +import ee.carlrobert.codegpt.CodeGPTBundle import ee.carlrobert.codegpt.CodeGPTKeys +import java.awt.BorderLayout import java.awt.Dimension import java.awt.FlowLayout import java.awt.Point @@ -157,17 +161,24 @@ class CodeSuggestionDiffViewer( } private fun getTagPanel(): JComponent { - val tagPanel = JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)) - if (!isManuallyOpened) { - tagPanel.add( - TagComponent( - "Trigger manually: ${getShortcutText(TriggerCustomPredictionAction.ID)}" - ).apply { - font = JBUI.Fonts.smallFont() - } - ) - tagPanel.add(Box.createHorizontalStrut(6)) + val tagPanel = JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)).apply { + isOpaque = false } + tagPanel.add( + TagComponent( + "Open: ${getShortcutText(OpenPredictionAction.ID)}" + ).apply { + setListener({ _, _ -> + service().openDirectPrediction( + mainEditor, + content2.document.text + ) + popup.dispose() + }, component) + font = JBUI.Fonts.smallFont() + } + ) + tagPanel.add(Box.createHorizontalStrut(6)) tagPanel.add(TagComponent("Accept: ${getShortcutText(AcceptNextPredictionRevisionAction.ID)}").apply { setListener({ _, _ -> applyChanges() @@ -183,6 +194,25 @@ class CodeSuggestionDiffViewer( .andTransparent() .withBorder(JBUI.Borders.empty(4)) .addToRight(getTagPanel()) + + val footerText = if (isManuallyOpened) { + CodeGPTBundle.get("shared.escToCancel") + } else { + "Trigger manually: ${getShortcutText(OpenPredictionAction.ID)} ยท ${CodeGPTBundle.get("shared.escToCancel")}" + } + + myEditor.component.add( + BorderLayoutPanel() + .addToRight(JBLabel(footerText) + .apply { + font = JBUI.Fonts.miniFont() + }) + .apply { + background = editor.backgroundColor + border = JBUI.Borders.empty(4) + }, + BorderLayout.SOUTH + ) } private fun getVisibleAreaListener(): VisibleAreaListener { diff --git a/src/main/kotlin/ee/carlrobert/codegpt/predictions/OpenPredictionAction.kt b/src/main/kotlin/ee/carlrobert/codegpt/predictions/OpenPredictionAction.kt new file mode 100644 index 00000000..252bf125 --- /dev/null +++ b/src/main/kotlin/ee/carlrobert/codegpt/predictions/OpenPredictionAction.kt @@ -0,0 +1,30 @@ +package ee.carlrobert.codegpt.predictions + +import com.intellij.codeInsight.hint.HintManagerImpl +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.application.runInEdt +import com.intellij.openapi.components.service +import com.intellij.openapi.editor.Caret +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.actionSystem.EditorAction +import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler +import ee.carlrobert.codegpt.CodeGPTKeys.EDITOR_PREDICTION_DIFF_VIEWER + +class OpenPredictionAction : EditorAction(Handler()), HintManagerImpl.ActionToIgnore { + + companion object { + const val ID = "codegpt.openPrediction" + } + + private class Handler : EditorWriteActionHandler() { + + override fun doExecute(editor: Editor, caret: Caret?, dataContext: DataContext?) { + val diffViewer = EDITOR_PREDICTION_DIFF_VIEWER.get(editor) ?: return + val nextRevision = diffViewer.content2.document.text + runInEdt { + diffViewer.dispose() + } + service().openDirectPrediction(editor, nextRevision) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/predictions/PredictionService.kt b/src/main/kotlin/ee/carlrobert/codegpt/predictions/PredictionService.kt index 79cfec71..f5acdcfe 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/predictions/PredictionService.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/predictions/PredictionService.kt @@ -1,6 +1,7 @@ package ee.carlrobert.codegpt.predictions import com.intellij.codeInsight.lookup.LookupEvent +import com.intellij.diff.DiffManager import com.intellij.notification.NotificationListener import com.intellij.notification.NotificationType import com.intellij.openapi.application.runInEdt @@ -8,6 +9,8 @@ import com.intellij.openapi.application.runReadAction import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.testFramework.LightVirtualFile import ee.carlrobert.codegpt.CodeGPTKeys import ee.carlrobert.codegpt.CodeGPTKeys.IS_FETCHING_COMPLETION import ee.carlrobert.codegpt.CodeGPTKeys.PENDING_PREDICTION_CALL @@ -18,6 +21,7 @@ import ee.carlrobert.codegpt.settings.prompts.PromptsSettings import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceSettings import ee.carlrobert.codegpt.ui.OverlayUtil import ee.carlrobert.codegpt.ui.OverlayUtil.getDefaultNotification +import ee.carlrobert.codegpt.util.EditorDiffUtil.createDiffRequest import ee.carlrobert.codegpt.util.EditorUtil import ee.carlrobert.codegpt.util.GitUtil import ee.carlrobert.llm.client.codegpt.request.prediction.AutocompletionPredictionRequest @@ -35,7 +39,7 @@ class PredictionService { fun displayDirectPrediction(editor: Editor) { val request = CompletionClientProvider.getCodeGPTClient() .buildDirectPredictionRequest(createDirectPredictionRequest(editor)) - displayInlineDiff(editor, request) + displayInlineDiff(editor, request, true) } fun displayAutocompletePrediction(editor: Editor, textToInsert: String, beforeApply: String) { @@ -78,11 +82,19 @@ class PredictionService { } } - private fun displayInlineDiff(editor: Editor, request: Request) { + private fun displayInlineDiff( + editor: Editor, + request: Request, + isManuallyOpened: Boolean = false + ) { val prediction = getPrediction(editor, request) if (prediction != null && !prediction.nextRevision.isNullOrEmpty()) { runInEdt { - CodeSuggestionDiffViewer.displayInlineDiff(editor, prediction.nextRevision) + CodeSuggestionDiffViewer.displayInlineDiff( + editor, + prediction.nextRevision, + isManuallyOpened + ) } } } @@ -169,4 +181,13 @@ class PredictionService { conversationMessages = messages.toList() } } + + fun openDirectPrediction(editor: Editor, nextRevision: String) { + val project: Project = editor.project ?: return + val tempDiffFile = LightVirtualFile(editor.virtualFile.name, nextRevision) + val diffRequest = createDiffRequest(project, tempDiffFile, editor) + runInEdt { + service().showDiff(project, diffRequest) + } + } } \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 683262f0..005ca1d1 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -108,6 +108,13 @@ + + + +