Skip to content

Commit

Permalink
feat: new 'Insert at Caret' toolwindow editor action
Browse files Browse the repository at this point in the history
  • Loading branch information
carlrobertoh committed Sep 4, 2024
1 parent dc02fd3 commit c417cca
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 9 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- 'Direct Apply' and 'Compare with Original' tool window editor actions for generated code
- Multiple tool window editor actions for generated code:
- Direct apply: Directly replaces the highlighted code in the main editor with the generated code
- Compare with Original: Opens a diff view to compare the generated code with the highlighted code
- Insert at Caret: Inserts the generated code at the exact location of the caret in the main editor
- Vision support for Azure models
- General improvements to code completions, including:
- Proper streaming support
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/ee/carlrobert/codegpt/Icons.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ public final class Icons {
public static final Icon Upload = IconLoader.getIcon("/icons/upload.svg", Icons.class);
public static final Icon GreenCheckmark =
IconLoader.getIcon("/icons/greenCheckmark.svg", Icons.class);
public static final Icon SendToTheLeft =
IconLoader.getIcon("/icons/sendToTheLeft.svg", Icons.class);
public static final Icon StatusBarCompletionInProgress = new AnimatedIcon.Default();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum ActionType {
CREATE_NEW_FILE,
COPY_CODE,
REPLACE_IN_MAIN_EDITOR,
INSERT_AT_CARET,
RELOAD_MESSAGE,
CHANGE_PROVIDER
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public class ReplaceCodeInMainEditorAction extends AnAction {

public ReplaceCodeInMainEditorAction() {
super("Replace in Main Editor", "Replace code in main editor", AllIcons.Actions.Replace);
super("Replace Selection", "Replace selected code in main editor", AllIcons.Actions.Replace);
EditorActionsUtil.registerAction(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.DiffAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.EditAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.InsertAtCaretAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.NewFileAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.ReplaceSelectionAction;
import ee.carlrobert.codegpt.ui.IconActionButton;
Expand Down Expand Up @@ -82,9 +83,9 @@ public ResponseEditorPanel(

if (highlightedText != null && !highlightedText.isEmpty()) {
directLinksPanel.setVisible(false);
directLinksPanel.setBorder(JBUI.Borders.emptyTop(4));
directLinksPanel.setBorder(JBUI.Borders.emptyTop(8));
directLinksPanel.add(new CompareWithOriginalActionLink(project, editor, highlightedText));
directLinksPanel.add(Box.createHorizontalStrut(8));
directLinksPanel.add(Box.createHorizontalStrut(12));
directLinksPanel.add(new DirectApplyActionLink(project, editor, highlightedText));
add(directLinksPanel, BorderLayout.SOUTH);
}
Expand Down Expand Up @@ -179,6 +180,7 @@ private ActionToolbar createHeaderActions(String extension, EditorEx editorEx) {
var actionGroup = new DefaultCompactActionGroup("EDITOR_TOOLBAR_ACTION_GROUP", false);
actionGroup.add(new CopyAction(editor));
actionGroup.add(new ReplaceSelectionAction(editor));
actionGroup.add(new InsertAtCaretAction(editor));
actionGroup.addSeparator();

var wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@

public class DiffAction extends AbstractAction {

private final EditorEx toolwindowEditor;
private final EditorEx editor;
private final Point locationOnScreen;

public DiffAction(EditorEx toolwindowEditor, @Nullable Point locationOnScreen) {
public DiffAction(EditorEx editor, @Nullable Point locationOnScreen) {
super("Diff", Actions.DiffWithClipboard);
this.toolwindowEditor = toolwindowEditor;
this.editor = editor;
this.locationOnScreen = locationOnScreen;
}

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

EditorDiffUtil.showDiff(
project,
toolwindowEditor,
editor,
mainEditor.getSelectionModel().getSelectedText());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ee.carlrobert.codegpt.toolwindow.chat.editor.actions;

import static com.intellij.openapi.application.ActionsKt.runUndoTransparentWriteAction;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.Icons;
import ee.carlrobert.codegpt.actions.ActionType;
import ee.carlrobert.codegpt.actions.TrackableAction;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import java.awt.Point;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class InsertAtCaretAction extends TrackableAction {

public InsertAtCaretAction(@NotNull Editor editor) {
super(
editor,
CodeGPTBundle.get("toolwindow.chat.editor.action.insertAtCaret.title"),
CodeGPTBundle.get("toolwindow.chat.editor.action.insertAtCaret.description"),
Icons.SendToTheLeft,
ActionType.INSERT_AT_CARET);
}

@Override
public void handleAction(@NotNull AnActionEvent event) {
Point locationOnScreen = getLocationOnScreen(event);
Editor mainEditor = getSelectedTextEditor();

if (mainEditor == null) {
OverlayUtil.showWarningBalloon("Active editor not found", locationOnScreen);
return;
}

insertTextAtCaret(mainEditor, locationOnScreen);
}

@Nullable
private Point getLocationOnScreen(AnActionEvent event) {
return Optional.ofNullable(event.getInputEvent())
.map(inputEvent -> inputEvent.getComponent().getLocationOnScreen())
.orElse(null);
}

@Nullable
private Editor getSelectedTextEditor() {
return Optional.ofNullable(editor.getProject())
.map(FileEditorManager::getInstance)
.map(FileEditorManager::getSelectedTextEditor)
.orElse(null);
}

private void insertTextAtCaret(Editor mainEditor, @Nullable Point locationOnScreen) {
runUndoTransparentWriteAction(() -> {
mainEditor.getDocument().insertString(
mainEditor.getCaretModel().getOffset(),
editor.getDocument().getText());
if (locationOnScreen != null) {
OverlayUtil.showInfoBalloon(
"Text successfully inserted at the current cursor position.",
locationOnScreen);
}
return null;
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.toolwindow.chat

import com.intellij.icons.AllIcons.Actions
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.editor.Editor
Expand All @@ -18,6 +19,10 @@ class CompareWithOriginalActionLink(
highlightedText
) {

init {
setIcon(Actions.Diff)
}

class CompareWithOriginalAction(
private val project: Project,
private val toolwindowEditor: Editor,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.toolwindow.chat

import com.intellij.icons.AllIcons.Actions
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.command.WriteCommandAction
Expand All @@ -20,6 +21,10 @@ class DirectApplyActionLink(
highlightedText
) {

init {
setIcon(Actions.Selectall)
}

class DirectApplyAction(
private val project: Project,
private val toolwindowEditor: Editor,
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/icons/sendToTheLeft.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/main/resources/icons/sendToTheLeft_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/main/resources/messages/codegpt.properties
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ toolwindow.chat.editor.action.newFile.title=New File
toolwindow.chat.editor.action.newFile.description=Create new file from generated code
toolwindow.chat.editor.action.replaceSelection.title=Replace Selection
toolwindow.chat.editor.action.replaceSelection.description=Replace main editor selected code
toolwindow.chat.editor.action.insertAtCaret.title=Insert at Caret
toolwindow.chat.editor.action.insertAtCaret.description=Insert generated code after main editor caret position
toolwindow.chat.editor.action.expand=Show More (+%s rows)
toolwindow.chat.editor.action.collapse=Show Less
toolwindow.chat.response.action.reloadResponse.text=Reload Response
Expand Down

0 comments on commit c417cca

Please sign in to comment.