Skip to content

Commit 3114c73

Browse files
authored
Merge pull request #593 from devoxx/feat-590
Feat #590: You can now also configure the newline shortcut
2 parents 59d9eb0 + afcb3bd commit 3114c73

File tree

8 files changed

+192
-27
lines changed

8 files changed

+192
-27
lines changed

src/main/java/com/devoxx/genie/ui/component/input/CommandAutoCompleteTextField.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,29 @@ public void keyPressed(@NotNull KeyEvent e) {
8888
KeyStroke currentKeyStroke = KeyStroke.getKeyStrokeForEvent(e);
8989
DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance();
9090

91-
String shortcutString;
91+
String submitShortcutString;
92+
String newlineShortcutString;
93+
9294
if (SystemInfo.isMac) {
93-
shortcutString = stateService.getSubmitShortcutMac();
95+
submitShortcutString = stateService.getSubmitShortcutMac();
96+
newlineShortcutString = stateService.getNewlineShortcutMac();
9497
} else if (SystemInfo.isLinux) {
95-
shortcutString = stateService.getSubmitShortcutLinux();
98+
submitShortcutString = stateService.getSubmitShortcutLinux();
99+
newlineShortcutString = stateService.getNewlineShortcutLinux();
96100
} else {
97-
shortcutString = stateService.getSubmitShortcutWindows();
101+
submitShortcutString = stateService.getSubmitShortcutWindows();
102+
newlineShortcutString = stateService.getNewlineShortcutWindows();
98103
}
99104

100-
KeyStroke submitKeyStroke = KeyStroke.getKeyStroke(shortcutString);
105+
KeyStroke submitKeyStroke = KeyStroke.getKeyStroke(submitShortcutString);
106+
KeyStroke newlineKeyStroke = KeyStroke.getKeyStroke(newlineShortcutString);
107+
101108
if (submitKeyStroke != null && submitKeyStroke.equals(currentKeyStroke)) {
102109
sendPrompt();
103110
e.consume();
111+
} else if (newlineKeyStroke != null && newlineKeyStroke.equals(currentKeyStroke)) {
112+
insertNewline();
113+
e.consume();
104114
} else if (e.getKeyCode() == KeyEvent.VK_SPACE && e.isControlDown()) {
105115
autoComplete();
106116
e.consume();
@@ -138,6 +148,14 @@ private void autoComplete() {
138148
}
139149
}
140150
}
151+
152+
private void insertNewline() {
153+
try {
154+
getDocument().insertString(getCaretPosition(), "\n", null);
155+
} catch (BadLocationException ex) {
156+
log.error("Error inserting newline", ex);
157+
}
158+
}
141159
}
142160

143161
private class CommandDocument extends PlainDocument {

src/main/java/com/devoxx/genie/ui/component/input/PromptInputArea.java

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.devoxx.genie.ui.component.input;
22

3+
import com.devoxx.genie.ui.listener.NewlineShortcutChangeListener;
34
import com.devoxx.genie.ui.listener.PromptInputFocusListener;
45
import com.devoxx.genie.ui.listener.RAGStateListener;
56
import com.devoxx.genie.ui.listener.ShortcutChangeListener;
@@ -23,12 +24,13 @@
2324
import static com.devoxx.genie.ui.util.WindowPluginUtil.TOOL_WINDOW_ID;
2425

2526
@Getter
26-
public class PromptInputArea extends JPanel implements ShortcutChangeListener, ToolWindowManagerListener, RAGStateListener {
27+
public class PromptInputArea extends JPanel implements ShortcutChangeListener, NewlineShortcutChangeListener, ToolWindowManagerListener, RAGStateListener {
2728
private final CommandAutoCompleteTextField inputField;
2829
private final SearchOptionsPanel searchOptionsPanel;
2930
private final ResourceBundle resourceBundle;
3031
private final Project project;
3132
private String submitShortcut;
33+
private String newlineShortcut;
3234
private String lastActiveId = null;
3335

3436
public PromptInputArea(Project project, @NotNull ResourceBundle resourceBundle) {
@@ -70,6 +72,9 @@ public PromptInputArea(Project project, @NotNull ResourceBundle resourceBundle)
7072

7173
MessageBusUtil.subscribe(project.getMessageBus().connect(),
7274
AppTopics.SHORTCUT_CHANGED_TOPIC, this);
75+
76+
MessageBusUtil.subscribe(project.getMessageBus().connect(),
77+
AppTopics.NEWLINE_SHORTCUT_CHANGED_TOPIC, this);
7378

7479
MessageBusUtil.subscribe(project.getMessageBus().connect(),
7580
AppTopics.RAG_ACTIVATED_CHANGED_TOPIC, this);
@@ -133,7 +138,6 @@ public void requestInputFocus() {
133138
}
134139

135140
private void setPlaceholderWithKeyboardShortcut(String shortcut) {
136-
137141
// Clean up the shortcut text
138142
shortcut = shortcut.replace("pressed", "+")
139143
.replace("meta", "command");
@@ -144,6 +148,27 @@ private void setPlaceholderWithKeyboardShortcut(String shortcut) {
144148
.substring(0, 1).toUpperCase()
145149
+ shortcut.substring(1);
146150

151+
// Also get newline shortcut for the placeholder
152+
String newlineShortcut;
153+
if (SystemInfo.isWindows) {
154+
newlineShortcut = DevoxxGenieStateService.getInstance().getNewlineShortcutWindows();
155+
} else if (SystemInfo.isLinux) {
156+
newlineShortcut = DevoxxGenieStateService.getInstance().getNewlineShortcutLinux();
157+
} else {
158+
newlineShortcut = DevoxxGenieStateService.getInstance().getNewlineShortcutMac();
159+
}
160+
161+
// Format the newline shortcut text
162+
newlineShortcut = newlineShortcut.replace("pressed", "+")
163+
.replace("meta", "command");
164+
String[] newlineParts = newlineShortcut.split(" ");
165+
String formattedNewlineShortcut = String.join(" + ", newlineParts)
166+
.substring(0, 1).toUpperCase()
167+
+ newlineShortcut.substring(1);
168+
169+
// Store the formatted newline shortcut for use in updatePlaceHolder
170+
this.newlineShortcut = formattedNewlineShortcut;
171+
147172
updatePlaceHolder(Boolean.TRUE.equals(DevoxxGenieStateService.getInstance().getRagActivated()));
148173
}
149174

@@ -156,17 +181,40 @@ public void onShortcutChanged(String shortcut) {
156181
}
157182

158183
private void updatePlaceHolder(boolean ragEnabled) {
184+
String placeholderText;
185+
159186
if (ragEnabled) {
160-
inputField.setPlaceholder(submitShortcut + " " +
161-
resourceBundle.getString("rag.prompt.placeholder"));
187+
placeholderText = submitShortcut + " to submit, " + newlineShortcut + " for newline. " +
188+
resourceBundle.getString("rag.prompt.placeholder");
162189
} else {
163-
inputField.setPlaceholder(submitShortcut + " " +
164-
resourceBundle.getString("prompt.placeholder"));
190+
placeholderText = submitShortcut + " to submit, " + newlineShortcut + " for newline. " +
191+
resourceBundle.getString("prompt.placeholder");
165192
}
193+
194+
inputField.setPlaceholder(placeholderText);
166195
}
167196

168197
@Override
169198
public void onRAGStateChanged(boolean enabled) {
170199
updatePlaceHolder(enabled);
171200
}
201+
202+
@Override
203+
public void onNewlineShortcutChanged(String shortcut) {
204+
if (shortcut == null || shortcut.isEmpty()) {
205+
return;
206+
}
207+
// Format the newline shortcut text
208+
shortcut = shortcut.replace("pressed", "+")
209+
.replace("meta", "command");
210+
String[] newlineParts = shortcut.split(" ");
211+
String formattedNewlineShortcut = String.join(" + ", newlineParts)
212+
.substring(0, 1).toUpperCase()
213+
+ shortcut.substring(1);
214+
215+
// Store the formatted newline shortcut for use in updatePlaceHolder
216+
this.newlineShortcut = formattedNewlineShortcut;
217+
218+
updatePlaceHolder(Boolean.TRUE.equals(DevoxxGenieStateService.getInstance().getRagActivated()));
219+
}
172220
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.devoxx.genie.ui.listener;
2+
3+
public interface NewlineShortcutChangeListener {
4+
void onNewlineShortcutChanged(String shortcut);
5+
}

src/main/java/com/devoxx/genie/ui/settings/DevoxxGenieStateService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public static DevoxxGenieStateService getInstance() {
3737
private String submitShortcutWindows = "shift ENTER";
3838
private String submitShortcutMac = "shift ENTER";
3939
private String submitShortcutLinux = "shift ENTER";
40+
41+
private String newlineShortcutWindows = "ctrl ENTER";
42+
private String newlineShortcutMac = "meta ENTER"; // Command+Enter on Mac
43+
private String newlineShortcutLinux = "ctrl ENTER";
4044

4145
// Default excluded files for scan project
4246
private List<String> excludedFiles = new ArrayList<>(Arrays.asList(

src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsComponent.java

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,19 @@ public class PromptSettingsComponent extends AbstractSettingsComponent {
4848
@Getter
4949
@Setter
5050
private String submitShortcutLinux;
51+
52+
@Getter
53+
@Setter
54+
private String newlineShortcutWindows;
55+
56+
@Getter
57+
@Setter
58+
private String newlineShortcutMac;
5159

60+
@Getter
61+
@Setter
62+
private String newlineShortcutLinux;
63+
5264
@Getter
5365
private final JTextArea systemPromptField = new JTextArea(stateService.getSystemPrompt());
5466
@Getter
@@ -202,45 +214,95 @@ public JPanel createPanel() {
202214
// Add keyboard shortcuts section
203215
addSection(panel, gbc, "Configure keyboard submit shortcut");
204216

217+
gbc.gridy++;
218+
gbc.weighty = 0.0;
219+
gbc.fill = GridBagConstraints.BOTH;
220+
221+
if (SystemInfo.isWindows) {
222+
panel.add(createShortcutPanel("Windows", stateService.getSubmitShortcutWindows(), true), gbc);
223+
} else if (SystemInfo.isMac) {
224+
panel.add(createShortcutPanel("Mac", stateService.getSubmitShortcutMac(), true), gbc);
225+
} else {
226+
panel.add(createShortcutPanel("Linux", stateService.getSubmitShortcutLinux(), true), gbc);
227+
}
228+
229+
// Add keyboard shortcuts section for newline
230+
addSection(panel, gbc, "Configure keyboard newline shortcut");
231+
205232
gbc.gridy++;
206233
gbc.weighty = 1.0;
207234
gbc.fill = GridBagConstraints.BOTH;
208235

209236
if (SystemInfo.isWindows) {
210-
panel.add(createShortcutPanel("Windows", stateService.getSubmitShortcutWindows()), gbc);
237+
panel.add(createNewlineShortcutPanel("Windows", stateService.getNewlineShortcutWindows()), gbc);
211238
} else if (SystemInfo.isMac) {
212-
panel.add(createShortcutPanel("Mac", stateService.getSubmitShortcutMac()), gbc);
239+
panel.add(createNewlineShortcutPanel("Mac", stateService.getNewlineShortcutMac()), gbc);
213240
} else {
214-
panel.add(createShortcutPanel("Linux", stateService.getSubmitShortcutLinux()), gbc);
241+
panel.add(createNewlineShortcutPanel("Linux", stateService.getNewlineShortcutLinux()), gbc);
215242
}
216243

217244
return panel;
218245
}
219246

220-
private @NotNull JPanel createShortcutPanel(String os, String initialShortcut) {
247+
private @NotNull JPanel createShortcutPanel(String os, String initialShortcut, boolean isSubmitShortcut) {
221248
KeyboardShortcutPanel shortcutPanel = new KeyboardShortcutPanel(project, os, initialShortcut, shortcut -> {
222249
// Update the appropriate shortcut based on OS
223-
if ("Mac".equalsIgnoreCase(os)) {
224-
setSubmitShortcutMac(shortcut);
225-
} else if ("Windows".equalsIgnoreCase(os)) {
226-
setSubmitShortcutWindows(shortcut);
250+
if (isSubmitShortcut) {
251+
if ("Mac".equalsIgnoreCase(os)) {
252+
setSubmitShortcutMac(shortcut);
253+
} else if ("Windows".equalsIgnoreCase(os)) {
254+
setSubmitShortcutWindows(shortcut);
255+
} else {
256+
setSubmitShortcutLinux(shortcut);
257+
}
258+
notifyShortcutChanged(shortcut);
227259
} else {
228-
setSubmitShortcutLinux(shortcut);
260+
if ("Mac".equalsIgnoreCase(os)) {
261+
setNewlineShortcutMac(shortcut);
262+
} else if ("Windows".equalsIgnoreCase(os)) {
263+
setNewlineShortcutWindows(shortcut);
264+
} else {
265+
setNewlineShortcutLinux(shortcut);
266+
}
267+
notifyNewlineShortcutChanged(shortcut);
229268
}
230-
notifyShortcutChanged(shortcut);
231269
});
232270

233271
// Set initial values from state service
234-
if ("Mac".equalsIgnoreCase(os)) {
235-
submitShortcutMac = shortcutPanel.getCurrentShortcut();
236-
} else if ("Windows".equalsIgnoreCase(os)) {
237-
submitShortcutWindows = shortcutPanel.getCurrentShortcut();
272+
if (isSubmitShortcut) {
273+
if ("Mac".equalsIgnoreCase(os)) {
274+
submitShortcutMac = shortcutPanel.getCurrentShortcut();
275+
} else if ("Windows".equalsIgnoreCase(os)) {
276+
submitShortcutWindows = shortcutPanel.getCurrentShortcut();
277+
} else {
278+
submitShortcutLinux = shortcutPanel.getCurrentShortcut();
279+
}
238280
} else {
239-
submitShortcutLinux = shortcutPanel.getCurrentShortcut();
281+
if ("Mac".equalsIgnoreCase(os)) {
282+
newlineShortcutMac = shortcutPanel.getCurrentShortcut();
283+
} else if ("Windows".equalsIgnoreCase(os)) {
284+
newlineShortcutWindows = shortcutPanel.getCurrentShortcut();
285+
} else {
286+
newlineShortcutLinux = shortcutPanel.getCurrentShortcut();
287+
}
240288
}
241289

242290
return shortcutPanel;
243291
}
292+
293+
private @NotNull JPanel createShortcutPanel(String os, String initialShortcut) {
294+
return createShortcutPanel(os, initialShortcut, true);
295+
}
296+
297+
private @NotNull JPanel createNewlineShortcutPanel(String os, String initialShortcut) {
298+
return createShortcutPanel(os, initialShortcut, false);
299+
}
300+
301+
private void notifyNewlineShortcutChanged(String shortcut) {
302+
project.getMessageBus()
303+
.syncPublisher(AppTopics.NEWLINE_SHORTCUT_CHANGED_TOPIC)
304+
.onNewlineShortcutChanged(shortcut);
305+
}
244306

245307
private void setupCustomPromptsTable() {
246308
customPromptsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

src/main/java/com/devoxx/genie/ui/settings/prompt/PromptSettingsConfigurable.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public boolean isModified() {
6666
isModified |= !settings.getSubmitShortcutWindows().equals(promptSettingsComponent.getSubmitShortcutWindows());
6767
isModified |= !settings.getSubmitShortcutMac().equals(promptSettingsComponent.getSubmitShortcutMac());
6868
isModified |= !settings.getSubmitShortcutLinux().equals(promptSettingsComponent.getSubmitShortcutLinux());
69+
70+
isModified |= !settings.getNewlineShortcutWindows().equals(promptSettingsComponent.getNewlineShortcutWindows());
71+
isModified |= !settings.getNewlineShortcutMac().equals(promptSettingsComponent.getNewlineShortcutMac());
72+
isModified |= !settings.getNewlineShortcutLinux().equals(promptSettingsComponent.getNewlineShortcutLinux());
6973

7074
return isModified;
7175
}
@@ -86,7 +90,7 @@ public void apply() {
8690
settings.setProjectTreeDepth((Integer) promptSettingsComponent.getProjectTreeDepthSpinner().getValue());
8791
settings.setUseDevoxxGenieMdInPrompt(promptSettingsComponent.getUseDevoxxGenieMdInPromptCheckbox().isSelected());
8892

89-
// Apply shortcuts and notify changes
93+
// Apply submit shortcuts and notify changes
9094
String newShortcut = null;
9195
if (SystemInfo.isWindows) {
9296
settings.setSubmitShortcutWindows(promptSettingsComponent.getSubmitShortcutWindows());
@@ -105,6 +109,26 @@ public void apply() {
105109
.syncPublisher(AppTopics.SHORTCUT_CHANGED_TOPIC)
106110
.onShortcutChanged(newShortcut);
107111
}
112+
113+
// Apply newline shortcuts and notify changes
114+
String newNewlineShortcut = null;
115+
if (SystemInfo.isWindows) {
116+
settings.setNewlineShortcutWindows(promptSettingsComponent.getNewlineShortcutWindows());
117+
newNewlineShortcut = promptSettingsComponent.getNewlineShortcutWindows();
118+
} else if (SystemInfo.isMac) {
119+
settings.setNewlineShortcutMac(promptSettingsComponent.getNewlineShortcutMac());
120+
newNewlineShortcut = promptSettingsComponent.getNewlineShortcutMac();
121+
} else {
122+
settings.setNewlineShortcutLinux(promptSettingsComponent.getNewlineShortcutLinux());
123+
newNewlineShortcut = promptSettingsComponent.getNewlineShortcutLinux();
124+
}
125+
126+
// Notify newline shortcut change
127+
if (newNewlineShortcut != null) {
128+
project.getMessageBus()
129+
.syncPublisher(AppTopics.NEWLINE_SHORTCUT_CHANGED_TOPIC)
130+
.onNewlineShortcutChanged(newNewlineShortcut);
131+
}
108132

109133
project.getMessageBus()
110134
.syncPublisher(AppTopics.CUSTOM_PROMPT_CHANGED_TOPIC)

src/main/java/com/devoxx/genie/ui/topic/AppTopics.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ public class AppTopics {
4040

4141
public static final Topic<ShortcutChangeListener> SHORTCUT_CHANGED_TOPIC =
4242
Topic.create("shortcutChanged", ShortcutChangeListener.class);
43+
44+
public static final Topic<NewlineShortcutChangeListener> NEWLINE_SHORTCUT_CHANGED_TOPIC =
45+
Topic.create("newlineShortcutChanged", NewlineShortcutChangeListener.class);
4346

4447
public static final Topic<MCPLoggingMessage> MCP_LOGGING_MSG =
4548
Topic.create("mcpLoggingMessage", MCPLoggingMessage.class);

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
<UL>
4040
<Li>Feat #586 : Added Gemini 2.5 Pro model by @stephanj</LI>
4141
<LI>Fix #588 : Fix streaming responses regression by @stephanj</LI>
42+
<LI>Feat #590 : User can now configure which keys to use for newline by @stephanj</LI>
4243
</UL>
4344
<h2>v0.5.2</h2>
4445
<UL>

0 commit comments

Comments
 (0)