Skip to content

Commit 9fe1873

Browse files
authored
Merge pull request #116 from jeddict/feature
Shortcuts ctrl+quote for chat window
2 parents 749cd4b + e7d7088 commit 9fe1873

4 files changed

Lines changed: 134 additions & 159 deletions

File tree

src/main/java/io/github/jeddict/ai/actions/AIAssistantPopupAction.java

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,26 @@
1515
*/
1616
package io.github.jeddict.ai.actions;
1717

18+
import io.github.jeddict.ai.hints.LearnFix;
1819
import static javax.swing.Action.NAME;
1920
import org.openide.util.NbBundle;
2021
import java.awt.event.ActionEvent;
2122
import java.awt.event.ActionListener;
22-
import java.util.List;
2323
import javax.swing.AbstractAction;
24-
import javax.swing.Action;
25-
import javax.swing.JMenu;
26-
import javax.swing.JMenuItem;
24+
import javax.swing.text.BadLocationException;
25+
import javax.swing.text.JTextComponent;
26+
import javax.swing.text.StyledDocument;
27+
import org.netbeans.api.editor.EditorRegistry;
28+
import org.netbeans.modules.editor.NbEditorUtilities;
29+
import org.netbeans.modules.editor.indent.api.Reformat;
2730
import org.openide.awt.ActionID;
2831
import org.openide.awt.ActionReference;
32+
import org.openide.awt.ActionReferences;
2933
import org.openide.awt.ActionRegistration;
30-
import org.openide.util.Utilities;
31-
import org.openide.util.actions.Presenter;
34+
import org.openide.filesystems.FileObject;
35+
import org.openide.loaders.DataObject;
36+
import org.openide.text.NbDocument;
37+
import org.openide.util.Exceptions;
3238

3339
@ActionID(
3440
category = "Edit/Chat",
@@ -37,28 +43,101 @@
3743
@ActionRegistration(
3844
displayName = "#CTL_AIAssistantPopupAction", lazy = false
3945
)
40-
@ActionReference(path = "Editors/Popup", position = 101)
46+
@ActionReferences({
47+
@ActionReference(path = "Editors/Popup", position = 101),
48+
@ActionReference(path = "Shortcuts", name = "C-QUOTE")
49+
})
4150
@NbBundle.Messages("CTL_AIAssistantPopupAction=AI Assistant")
42-
public final class AIAssistantPopupAction extends AbstractAction implements ActionListener, Presenter.Popup {
51+
public final class AIAssistantPopupAction extends AbstractAction implements ActionListener {
4352

4453
public AIAssistantPopupAction() {
4554
putValue(NAME, Bundle.CTL_AIAssistantPopupAction());
4655
setEnabled(true);
4756
}
4857

58+
4959
@Override
5060
public void actionPerformed(ActionEvent e) {
51-
}
5261

53-
@Override
54-
public JMenuItem getPopupPresenter() {
55-
setEnabled(true);
56-
JMenu main = new JMenu(this);
57-
List<? extends Action> actionsForPath = Utilities.actionsForPath("Actions/Chat/SubActions");
58-
actionsForPath.forEach((action) -> {
59-
main.add(action);
62+
LearnFix learnFix;
63+
JTextComponent editor = EditorRegistry.lastFocusedComponent();
64+
String selectedText = editor.getSelectedText();
65+
final StyledDocument document = (StyledDocument) editor.getDocument();
66+
67+
FileObject file = getFileObject(document);
68+
int selectionStartPosition = editor.getSelectionStart();
69+
if (selectedText == null || selectedText.isEmpty()) {
70+
selectionStartPosition = -1;
71+
selectedText = "";
72+
learnFix = new LearnFix(io.github.jeddict.ai.completion.Action.QUERY, file);
73+
} else {
74+
learnFix = new LearnFix(io.github.jeddict.ai.completion.Action.QUERY);
75+
}
76+
final String text = selectedText;
77+
final int startLocation = selectionStartPosition;
78+
learnFix.openChat(null, selectedText, file.getName(), "Chat with AI", content -> {
79+
NbDocument.runAtomic(document, () -> {
80+
if (!text.isEmpty()) {
81+
insertAndReformat(document, content, startLocation, text.length());
82+
} else {
83+
JTextComponent currenteditor = EditorRegistry.lastFocusedComponent();
84+
String currentSelectedText = currenteditor.getSelectedText();
85+
final StyledDocument currentDocument = (StyledDocument) currenteditor.getDocument();
86+
int currentSelectionStartPosition = currenteditor.getSelectionStart();
87+
DataObject currentDO = NbEditorUtilities.getDataObject(currentDocument);
88+
if (currentDO != null) {
89+
FileObject currentfile = currentDO.getPrimaryFile();
90+
if (currentfile != null) {
91+
if (currentSelectedText == null || currentSelectedText.isEmpty()) {
92+
insertAndReformat(currentDocument, content, currentSelectionStartPosition, 0);
93+
} else {
94+
insertAndReformat(currentDocument, content, currentSelectionStartPosition, currentSelectedText.length());
95+
}
96+
}
97+
} else {
98+
javax.swing.JOptionPane.showMessageDialog(null, "Please select text in the original editor before updating.");
99+
}
100+
}
101+
});
60102
});
61-
return main;
103+
}
104+
105+
private void insertAndReformat(StyledDocument document, String content, int startPosition, int lengthToRemove) {
106+
try {
107+
if (lengthToRemove > 0) {
108+
document.remove(startPosition, lengthToRemove);
109+
}
110+
document.insertString(startPosition, content, null);
111+
Reformat reformat = Reformat.get(document);
112+
reformat.lock();
113+
try {
114+
reformat.reformat(startPosition, startPosition + content.length());
115+
} finally {
116+
reformat.unlock();
117+
}
118+
} catch (BadLocationException ex) {
119+
Exceptions.printStackTrace(ex);
120+
}
121+
}
122+
123+
/**
124+
* Retrieves the FileObject associated with the given JTextComponent.
125+
*
126+
* @param editor The JTextComponent from which to derive the FileObject.
127+
* @return The FileObject associated with the document, or null if not
128+
* found.
129+
*/
130+
private FileObject getFileObject(StyledDocument document) {
131+
try {
132+
// Retrieve the DataObject directly from the document's stream property
133+
DataObject dataObject = NbEditorUtilities.getDataObject(document);
134+
if (dataObject != null) {
135+
return dataObject.getPrimaryFile();
136+
}
137+
} catch (Exception ex) {
138+
Exceptions.printStackTrace(ex);
139+
}
140+
return null;
62141
}
63142

64143
}

src/main/java/io/github/jeddict/ai/actions/OpenChatAction.java

Lines changed: 0 additions & 132 deletions
This file was deleted.

src/main/java/io/github/jeddict/ai/hints/LearnFix.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import io.github.jeddict.ai.components.ContextDialog;
8282
import io.github.jeddict.ai.lang.JeddictStreamHandler;
8383
import io.github.jeddict.ai.util.EditorUtil;
84+
import java.awt.EventQueue;
8485
import java.awt.Toolkit;
8586
import java.awt.datatransfer.Clipboard;
8687
import java.awt.datatransfer.DataFlavor;
@@ -116,6 +117,7 @@ public class LearnFix extends JavaFix {
116117
private SQLCompletion sqlCompletion;
117118
private JButton prevButton, nextButton, copyButton, saveButton, openInBrowserButton;
118119
private AssistantTopComponent topComponent;
120+
private JEditorPane questionPane;
119121
private final List<String> responseHistory = new ArrayList<>();
120122
private int currentResponseIndex = -1;
121123
private String sourceCode = null;
@@ -173,7 +175,7 @@ public LearnFix(Action action, FileObject selectedFileObject) {
173175
this.selectedFileObjects = new ArrayList<>();
174176
this.selectedFileObjects.add(selectedFileObject);
175177
}
176-
178+
177179
@Override
178180
protected String getText() {
179181
if (action == Action.LEARN) {
@@ -402,16 +404,16 @@ public void openChat(String type, final String query, String fileName, String ti
402404

403405
private void initialMessage() {
404406
topComponent.createHtmlPane(
405-
"<div style='margin:20px; padding:20px; border-radius:10px;'>"
406-
+ "<div style='text-align:center;'>"
407-
+ "👋 <strong>Welcome!</strong><br><br>"
408-
+ "I'm here to assist you with any questions you have.<br>"
409-
+ "Feel free to ask anything!<br>"
410-
+ "</div>"
411-
+ "</div>"
412-
);
407+
"<div style='margin:20px; padding:20px; border-radius:10px;'>"
408+
+ "<div style='text-align:center;'>"
409+
+ "👋 <strong>Welcome!</strong><br><br>"
410+
+ "I'm here to assist you with any questions you have.<br>"
411+
+ "Feel free to ask anything!<br>"
412+
+ "</div>"
413+
+ "</div>"
414+
);
415+
EventQueue.invokeLater(() -> questionPane.requestFocusInWindow());
413416
}
414-
private JEditorPane questionPane;
415417

416418
private JPanel createBottomPanel(String type, String fileName, String title, Consumer<String> action) {
417419
// Create a panel for the text field and buttons

src/main/java/io/github/jeddict/ai/settings/AIAssistancePanel.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,42 +1222,68 @@ void store() {
12221222

12231223
if (!temperature.getText().isEmpty()) {
12241224
preferencesManager.setTemperature(Double.parseDouble(temperature.getText()));
1225+
} else {
1226+
preferencesManager.setTemperature(Double.MIN_VALUE);
12251227
}
12261228
if (!maxTokens.getText().isEmpty()) {
12271229
preferencesManager.setMaxTokens(Integer.parseInt(maxTokens.getText()));
1230+
} else {
1231+
preferencesManager.setMaxTokens(Integer.MIN_VALUE);
12281232
}
12291233
if (!topP.getText().isEmpty()) {
12301234
preferencesManager.setTopP(Double.parseDouble(topP.getText()));
1235+
} else {
1236+
preferencesManager.setTopP(Double.MIN_VALUE);
12311237
}
12321238
if (!presencePenalty.getText().isEmpty()) {
12331239
preferencesManager.setPresencePenalty(Double.parseDouble(presencePenalty.getText()));
1240+
} else {
1241+
preferencesManager.setPresencePenalty(Double.MIN_VALUE);
12341242
}
12351243
if (!frequencyPenalty.getText().isEmpty()) {
12361244
preferencesManager.setFrequencyPenalty(Double.parseDouble(frequencyPenalty.getText()));
1245+
} else {
1246+
preferencesManager.setFrequencyPenalty(Double.MIN_VALUE);
12371247
}
12381248
if (!repeatPenalty.getText().isEmpty()) {
12391249
preferencesManager.setRepeatPenalty(Double.parseDouble(repeatPenalty.getText()));
1250+
} else {
1251+
preferencesManager.setRepeatPenalty(Double.MIN_VALUE);
12401252
}
12411253
if (!seed.getText().isEmpty()) {
12421254
preferencesManager.setSeed(Integer.parseInt(seed.getText()));
1255+
} else {
1256+
preferencesManager.setSeed(Integer.MIN_VALUE);
12431257
}
12441258
if (!topK.getText().isEmpty()) {
12451259
preferencesManager.setTopK(Integer.parseInt(topK.getText()));
1260+
} else {
1261+
preferencesManager.setTopK(Integer.MIN_VALUE);
12461262
}
12471263
if (!maxCompletionTokens.getText().isEmpty()) {
12481264
preferencesManager.setMaxCompletionTokens(Integer.parseInt(maxCompletionTokens.getText()));
1265+
} else {
1266+
preferencesManager.setMaxCompletionTokens(Integer.MIN_VALUE);
12491267
}
12501268
if (!maxOutputTokens.getText().isEmpty()) {
12511269
preferencesManager.setMaxOutputTokens(Integer.parseInt(maxOutputTokens.getText()));
1270+
} else {
1271+
preferencesManager.setMaxOutputTokens(Integer.MIN_VALUE);
12521272
}
12531273
if (!maxRetries.getText().isEmpty()) {
12541274
preferencesManager.setMaxRetries(Integer.parseInt(maxRetries.getText()));
1275+
} else {
1276+
preferencesManager.setMaxRetries(Integer.MIN_VALUE);
12551277
}
12561278
if (!organizationId.getText().isEmpty()) {
12571279
preferencesManager.setOrganizationId(organizationId.getText());
1280+
} else {
1281+
preferencesManager.setOrganizationId("");
12581282
}
12591283
if (!timeout.getText().isEmpty()) {
12601284
preferencesManager.setTimeout(Integer.parseInt(timeout.getText()));
1285+
} else {
1286+
preferencesManager.setTimeout(Integer.MIN_VALUE);
12611287
}
12621288
preferencesManager.setAllowCodeExecution(allowCodeExecution.isSelected());
12631289
preferencesManager.setIncludeCodeExecutionOutput(includeCodeExecutionOutput.isSelected());

0 commit comments

Comments
 (0)