Skip to content

Commit c417cca

Browse files
committed
feat: new 'Insert at Caret' toolwindow editor action
1 parent dc02fd3 commit c417cca

File tree

12 files changed

+109
-9
lines changed

12 files changed

+109
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Added
1010

11-
- 'Direct Apply' and 'Compare with Original' tool window editor actions for generated code
11+
- Multiple tool window editor actions for generated code:
12+
- Direct apply: Directly replaces the highlighted code in the main editor with the generated code
13+
- Compare with Original: Opens a diff view to compare the generated code with the highlighted code
14+
- Insert at Caret: Inserts the generated code at the exact location of the caret in the main editor
1215
- Vision support for Azure models
1316
- General improvements to code completions, including:
1417
- Proper streaming support

src/main/java/ee/carlrobert/codegpt/Icons.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,7 @@ public final class Icons {
2828
public static final Icon Upload = IconLoader.getIcon("/icons/upload.svg", Icons.class);
2929
public static final Icon GreenCheckmark =
3030
IconLoader.getIcon("/icons/greenCheckmark.svg", Icons.class);
31+
public static final Icon SendToTheLeft =
32+
IconLoader.getIcon("/icons/sendToTheLeft.svg", Icons.class);
3133
public static final Icon StatusBarCompletionInProgress = new AnimatedIcon.Default();
3234
}

src/main/java/ee/carlrobert/codegpt/actions/ActionType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public enum ActionType {
1313
CREATE_NEW_FILE,
1414
COPY_CODE,
1515
REPLACE_IN_MAIN_EDITOR,
16+
INSERT_AT_CARET,
1617
RELOAD_MESSAGE,
1718
CHANGE_PROVIDER
1819
}

src/main/java/ee/carlrobert/codegpt/actions/toolwindow/ReplaceCodeInMainEditorAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
public class ReplaceCodeInMainEditorAction extends AnAction {
1515

1616
public ReplaceCodeInMainEditorAction() {
17-
super("Replace in Main Editor", "Replace code in main editor", AllIcons.Actions.Replace);
17+
super("Replace Selection", "Replace selected code in main editor", AllIcons.Actions.Replace);
1818
EditorActionsUtil.registerAction(this);
1919
}
2020

src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditorPanel.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction;
3434
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.DiffAction;
3535
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.EditAction;
36+
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.InsertAtCaretAction;
3637
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.NewFileAction;
3738
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.ReplaceSelectionAction;
3839
import ee.carlrobert.codegpt.ui.IconActionButton;
@@ -82,9 +83,9 @@ public ResponseEditorPanel(
8283

8384
if (highlightedText != null && !highlightedText.isEmpty()) {
8485
directLinksPanel.setVisible(false);
85-
directLinksPanel.setBorder(JBUI.Borders.emptyTop(4));
86+
directLinksPanel.setBorder(JBUI.Borders.emptyTop(8));
8687
directLinksPanel.add(new CompareWithOriginalActionLink(project, editor, highlightedText));
87-
directLinksPanel.add(Box.createHorizontalStrut(8));
88+
directLinksPanel.add(Box.createHorizontalStrut(12));
8889
directLinksPanel.add(new DirectApplyActionLink(project, editor, highlightedText));
8990
add(directLinksPanel, BorderLayout.SOUTH);
9091
}
@@ -179,6 +180,7 @@ private ActionToolbar createHeaderActions(String extension, EditorEx editorEx) {
179180
var actionGroup = new DefaultCompactActionGroup("EDITOR_TOOLBAR_ACTION_GROUP", false);
180181
actionGroup.add(new CopyAction(editor));
181182
actionGroup.add(new ReplaceSelectionAction(editor));
183+
actionGroup.add(new InsertAtCaretAction(editor));
182184
actionGroup.addSeparator();
183185

184186
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));

src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/DiffAction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@
1515

1616
public class DiffAction extends AbstractAction {
1717

18-
private final EditorEx toolwindowEditor;
18+
private final EditorEx editor;
1919
private final Point locationOnScreen;
2020

21-
public DiffAction(EditorEx toolwindowEditor, @Nullable Point locationOnScreen) {
21+
public DiffAction(EditorEx editor, @Nullable Point locationOnScreen) {
2222
super("Diff", Actions.DiffWithClipboard);
23-
this.toolwindowEditor = toolwindowEditor;
23+
this.editor = editor;
2424
this.locationOnScreen = locationOnScreen;
2525
}
2626

2727
@Override
2828
public void actionPerformed(ActionEvent event) {
29-
var project = requireNonNull(toolwindowEditor.getProject());
29+
var project = requireNonNull(editor.getProject());
3030
var mainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor();
3131
if (mainEditor != null && !EditorUtil.hasSelection(mainEditor) && locationOnScreen != null) {
3232
OverlayUtil.showSelectedEditorSelectionWarning(project, locationOnScreen);
@@ -35,7 +35,7 @@ public void actionPerformed(ActionEvent event) {
3535

3636
EditorDiffUtil.showDiff(
3737
project,
38-
toolwindowEditor,
38+
editor,
3939
mainEditor.getSelectionModel().getSelectedText());
4040
}
4141
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package ee.carlrobert.codegpt.toolwindow.chat.editor.actions;
2+
3+
import static com.intellij.openapi.application.ActionsKt.runUndoTransparentWriteAction;
4+
5+
import com.intellij.openapi.actionSystem.AnActionEvent;
6+
import com.intellij.openapi.editor.Editor;
7+
import com.intellij.openapi.fileEditor.FileEditorManager;
8+
import ee.carlrobert.codegpt.CodeGPTBundle;
9+
import ee.carlrobert.codegpt.Icons;
10+
import ee.carlrobert.codegpt.actions.ActionType;
11+
import ee.carlrobert.codegpt.actions.TrackableAction;
12+
import ee.carlrobert.codegpt.ui.OverlayUtil;
13+
import java.awt.Point;
14+
import java.util.Optional;
15+
import org.jetbrains.annotations.NotNull;
16+
import org.jetbrains.annotations.Nullable;
17+
18+
public class InsertAtCaretAction extends TrackableAction {
19+
20+
public InsertAtCaretAction(@NotNull Editor editor) {
21+
super(
22+
editor,
23+
CodeGPTBundle.get("toolwindow.chat.editor.action.insertAtCaret.title"),
24+
CodeGPTBundle.get("toolwindow.chat.editor.action.insertAtCaret.description"),
25+
Icons.SendToTheLeft,
26+
ActionType.INSERT_AT_CARET);
27+
}
28+
29+
@Override
30+
public void handleAction(@NotNull AnActionEvent event) {
31+
Point locationOnScreen = getLocationOnScreen(event);
32+
Editor mainEditor = getSelectedTextEditor();
33+
34+
if (mainEditor == null) {
35+
OverlayUtil.showWarningBalloon("Active editor not found", locationOnScreen);
36+
return;
37+
}
38+
39+
insertTextAtCaret(mainEditor, locationOnScreen);
40+
}
41+
42+
@Nullable
43+
private Point getLocationOnScreen(AnActionEvent event) {
44+
return Optional.ofNullable(event.getInputEvent())
45+
.map(inputEvent -> inputEvent.getComponent().getLocationOnScreen())
46+
.orElse(null);
47+
}
48+
49+
@Nullable
50+
private Editor getSelectedTextEditor() {
51+
return Optional.ofNullable(editor.getProject())
52+
.map(FileEditorManager::getInstance)
53+
.map(FileEditorManager::getSelectedTextEditor)
54+
.orElse(null);
55+
}
56+
57+
private void insertTextAtCaret(Editor mainEditor, @Nullable Point locationOnScreen) {
58+
runUndoTransparentWriteAction(() -> {
59+
mainEditor.getDocument().insertString(
60+
mainEditor.getCaretModel().getOffset(),
61+
editor.getDocument().getText());
62+
if (locationOnScreen != null) {
63+
OverlayUtil.showInfoBalloon(
64+
"Text successfully inserted at the current cursor position.",
65+
locationOnScreen);
66+
}
67+
return null;
68+
});
69+
}
70+
}

src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/CompareWithOriginalActionLink.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ee.carlrobert.codegpt.toolwindow.chat
22

3+
import com.intellij.icons.AllIcons.Actions
34
import com.intellij.openapi.actionSystem.AnAction
45
import com.intellij.openapi.actionSystem.AnActionEvent
56
import com.intellij.openapi.editor.Editor
@@ -18,6 +19,10 @@ class CompareWithOriginalActionLink(
1819
highlightedText
1920
) {
2021

22+
init {
23+
setIcon(Actions.Diff)
24+
}
25+
2126
class CompareWithOriginalAction(
2227
private val project: Project,
2328
private val toolwindowEditor: Editor,

src/main/kotlin/ee/carlrobert/codegpt/toolwindow/chat/DirectApplyActionLink.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ee.carlrobert.codegpt.toolwindow.chat
22

3+
import com.intellij.icons.AllIcons.Actions
34
import com.intellij.openapi.actionSystem.AnAction
45
import com.intellij.openapi.actionSystem.AnActionEvent
56
import com.intellij.openapi.command.WriteCommandAction
@@ -20,6 +21,10 @@ class DirectApplyActionLink(
2021
highlightedText
2122
) {
2223

24+
init {
25+
setIcon(Actions.Selectall)
26+
}
27+
2328
class DirectApplyAction(
2429
private val project: Project,
2530
private val toolwindowEditor: Editor,
Lines changed: 5 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading

src/main/resources/messages/codegpt.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ toolwindow.chat.editor.action.newFile.title=New File
181181
toolwindow.chat.editor.action.newFile.description=Create new file from generated code
182182
toolwindow.chat.editor.action.replaceSelection.title=Replace Selection
183183
toolwindow.chat.editor.action.replaceSelection.description=Replace main editor selected code
184+
toolwindow.chat.editor.action.insertAtCaret.title=Insert at Caret
185+
toolwindow.chat.editor.action.insertAtCaret.description=Insert generated code after main editor caret position
184186
toolwindow.chat.editor.action.expand=Show More (+%s rows)
185187
toolwindow.chat.editor.action.collapse=Show Less
186188
toolwindow.chat.response.action.reloadResponse.text=Reload Response

0 commit comments

Comments
 (0)