mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-09 02:51:09 +00:00
Ability to create new files from codegpt toolwindow editor (#219)
This commit is contained in:
parent
6490a2c8d5
commit
e417ac8a03
1 changed files with 130 additions and 41 deletions
|
|
@ -3,6 +3,8 @@ package ee.carlrobert.codegpt.toolwindow.chat;
|
|||
import static ee.carlrobert.codegpt.util.FileUtils.findFileNameExtensionMapping;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.icons.AllIcons.Actions;
|
||||
import com.intellij.ide.util.EditorHelper;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
|
|
@ -16,16 +18,25 @@ import com.intellij.openapi.editor.EditorKind;
|
|||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.impl.ContextMenuPopupHandler;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.ui.TextBrowseFolderListener;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import ee.carlrobert.codegpt.actions.toolwindow.ReplaceCodeInMainEditorAction;
|
||||
import ee.carlrobert.codegpt.toolwindow.IconActionButton;
|
||||
import ee.carlrobert.codegpt.util.EditorUtils;
|
||||
import ee.carlrobert.codegpt.util.FileUtils;
|
||||
import ee.carlrobert.codegpt.util.OverlayUtils;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.FlowLayout;
|
||||
|
|
@ -43,28 +54,45 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
public class ChatToolWindowTabPanelEditor implements Disposable {
|
||||
|
||||
private final Project project;
|
||||
private final Editor editor;
|
||||
private final Map.Entry<String, String> fileNameExtensionMapping;
|
||||
|
||||
public ChatToolWindowTabPanelEditor(Project project, String code, String language, Disposable disposableParent) {
|
||||
public ChatToolWindowTabPanelEditor(
|
||||
Project project,
|
||||
String code,
|
||||
String language,
|
||||
Disposable disposableParent) {
|
||||
this.project = project;
|
||||
this.fileNameExtensionMapping = findFileNameExtensionMapping(language);
|
||||
|
||||
var fileName = "temp_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()) + fileNameExtensionMapping.getValue();
|
||||
var lightVirtualFile = new LightVirtualFile(String.format("%s/%s", PathManager.getTempPath(), fileName), code);
|
||||
var timestamp = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
|
||||
var fileName = "temp_" + timestamp + fileNameExtensionMapping.getValue();
|
||||
var lightVirtualFile = new LightVirtualFile(
|
||||
String.format("%s/%s", PathManager.getTempPath(), fileName), code);
|
||||
var document = FileDocumentManager.getInstance().getDocument(lightVirtualFile);
|
||||
if (document == null) {
|
||||
document = EditorFactory.getInstance().createDocument(code);
|
||||
}
|
||||
EditorUtils.disableHighlighting(project, document);
|
||||
editor = EditorFactory.getInstance().createEditor(document, project, lightVirtualFile, true, EditorKind.UNTYPED);
|
||||
String originalGroupId = ((EditorEx) editor).getContextMenuGroupId();
|
||||
AnAction originalGroup = originalGroupId == null ? null : ActionManager.getInstance().getAction(originalGroupId);
|
||||
editor = EditorFactory.getInstance().createEditor(
|
||||
document,
|
||||
project,
|
||||
lightVirtualFile,
|
||||
true,
|
||||
EditorKind.UNTYPED);
|
||||
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
if (originalGroup instanceof ActionGroup) {
|
||||
group.addAll(((ActionGroup) originalGroup).getChildren(null));
|
||||
}
|
||||
group.add(new ReplaceCodeInMainEditorAction());
|
||||
|
||||
String originalGroupId = ((EditorEx) editor).getContextMenuGroupId();
|
||||
if (originalGroupId != null) {
|
||||
AnAction originalGroup = ActionManager.getInstance().getAction(originalGroupId);
|
||||
if (originalGroup instanceof ActionGroup) {
|
||||
group.addAll(((ActionGroup) originalGroup).getChildren(null));
|
||||
}
|
||||
}
|
||||
|
||||
var editorEx = ((EditorEx) editor);
|
||||
editorEx.installPopupHandler(new ContextMenuPopupHandler.Simple(group));
|
||||
editorEx.setColorsScheme(EditorColorsManager.getInstance().getSchemeForCurrentUITheme());
|
||||
|
|
@ -102,44 +130,105 @@ public class ChatToolWindowTabPanelEditor implements Disposable {
|
|||
|
||||
private JPanel createHeaderActions() {
|
||||
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||
wrapper.add(new IconActionButton("Copy", AllIcons.Actions.Copy, new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
StringSelection stringSelection = new StringSelection(editor.getDocument().getText());
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(stringSelection, null);
|
||||
|
||||
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
|
||||
locationOnScreen.y = locationOnScreen.y - 16;
|
||||
|
||||
OverlayUtils.showInfoBalloon("Code copied!", locationOnScreen);
|
||||
}
|
||||
}));
|
||||
wrapper.add(new IconActionButton("New File", Actions.AddFile, new NewFileAction()));
|
||||
wrapper.add(Box.createHorizontalStrut(8));
|
||||
wrapper.add(new IconActionButton("Replace in Main Editor", AllIcons.Actions.Replace, new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
var project = event.getProject();
|
||||
if (project != null) {
|
||||
if (EditorUtils.isMainEditorTextSelected(project)) {
|
||||
EditorUtils.replaceMainEditorSelection(project, editor.getDocument().getText());
|
||||
} else {
|
||||
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
|
||||
locationOnScreen.y = locationOnScreen.y - 16;
|
||||
|
||||
OverlayUtils.showWarningBalloon(
|
||||
EditorUtils.getSelectedEditor(project) == null ? "Unable to locate a selected editor" : "Please select a target code before proceeding",
|
||||
locationOnScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
wrapper.add(new IconActionButton("Copy", AllIcons.Actions.Copy, new CopyAction()));
|
||||
wrapper.add(Box.createHorizontalStrut(8));
|
||||
wrapper.add(new IconActionButton(
|
||||
"Replace in Main Editor",
|
||||
AllIcons.Actions.Replace,
|
||||
new ReplaceInMainEditorAction()));
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
EditorFactory.getInstance().releaseEditor(editor);
|
||||
}
|
||||
|
||||
class NewFileAction extends AnAction {
|
||||
|
||||
private final TextFieldWithBrowseButton textFieldWithBrowseButton;
|
||||
private final JBTextField fileNameTextField;
|
||||
|
||||
NewFileAction() {
|
||||
var fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
fileChooserDescriptor.setForcedToUseIdeaFileChooser(true);
|
||||
|
||||
textFieldWithBrowseButton = new TextFieldWithBrowseButton();
|
||||
textFieldWithBrowseButton.addBrowseFolderListener(
|
||||
new TextBrowseFolderListener(fileChooserDescriptor, project));
|
||||
fileNameTextField = new JBTextField("Untitled" + fileNameExtensionMapping.getValue());
|
||||
fileNameTextField.setColumns(30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
if (getDialogBuilder().show() == 0) {
|
||||
var file = FileUtils.createFile(
|
||||
textFieldWithBrowseButton.getText(),
|
||||
fileNameTextField.getText(),
|
||||
editor.getDocument().getText());
|
||||
var virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
|
||||
if (virtualFile == null) {
|
||||
throw new RuntimeException("Couldn't find the saved virtual file");
|
||||
}
|
||||
var psiFile = PsiManager.getInstance(project).findFile(virtualFile);
|
||||
if (psiFile == null) {
|
||||
throw new RuntimeException("Couldn't find the saved psi file");
|
||||
}
|
||||
|
||||
EditorHelper.openInEditor(psiFile);
|
||||
}
|
||||
}
|
||||
|
||||
private DialogBuilder getDialogBuilder() {
|
||||
var dialogBuilder = new DialogBuilder(project);
|
||||
dialogBuilder.setTitle("New File");
|
||||
dialogBuilder.setCenterPanel(FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent("File name:", fileNameTextField)
|
||||
.addLabeledComponent("Destination:", textFieldWithBrowseButton)
|
||||
.getPanel());
|
||||
dialogBuilder.addOkAction();
|
||||
dialogBuilder.addCancelAction();
|
||||
return dialogBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
class CopyAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
StringSelection stringSelection = new StringSelection(editor.getDocument().getText());
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(stringSelection, null);
|
||||
|
||||
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
|
||||
locationOnScreen.y = locationOnScreen.y - 16;
|
||||
|
||||
OverlayUtils.showInfoBalloon("Code copied!", locationOnScreen);
|
||||
}
|
||||
}
|
||||
|
||||
class ReplaceInMainEditorAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
var project = event.getProject();
|
||||
if (project != null) {
|
||||
if (EditorUtils.isMainEditorTextSelected(project)) {
|
||||
EditorUtils.replaceMainEditorSelection(project, editor.getDocument().getText());
|
||||
} else {
|
||||
var locationOnScreen = ((MouseEvent) event.getInputEvent()).getLocationOnScreen();
|
||||
locationOnScreen.y = locationOnScreen.y - 16;
|
||||
|
||||
OverlayUtils.showWarningBalloon(
|
||||
EditorUtils.getSelectedEditor(project) == null
|
||||
? "Unable to locate a selected editor"
|
||||
: "Please select a target code before proceeding",
|
||||
locationOnScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue