Skip to content

Commit c15976d

Browse files
authored
feat: make the send shortcut configurable (#1149)
This change makes it so the user can select the key combination to send the message. Users may configure any combination of ctrl, alt, or shift (or the mac equivalents) plus enter. If any are configured, that combination plus enter will send the message, and enter by itself will insert a newline. If none are configured, enter by itself and any of the modifiers plus enter inserts a newline. This means the previous behavior of shift+enter to insert a newline is preserved.
1 parent 6a88119 commit c15976d

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

src/main/kotlin/ee/carlrobert/codegpt/settings/configuration/ChatCompletionConfigurationForm.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.intellij.ui.components.JBCheckBox
77
import com.intellij.ui.dsl.builder.panel
88
import com.intellij.util.ui.JBUI
99
import ee.carlrobert.codegpt.CodeGPTBundle
10+
import java.awt.Toolkit
1011

1112
class ChatCompletionConfigurationForm {
1213

@@ -29,6 +30,21 @@ class ChatCompletionConfigurationForm {
2930
service<ConfigurationSettings>().state.chatCompletionSettings.clickableLinksEnabled
3031
)
3132

33+
private val sendWithAltEnterCheckBox = JBCheckBox(
34+
Toolkit.getProperty("AWT.alt", "Alt"),
35+
service<ConfigurationSettings>().state.chatCompletionSettings.sendWithAltEnter
36+
)
37+
38+
private val sendWithCtrlEnterCheckBox = JBCheckBox(
39+
Toolkit.getProperty("AWT.ctrl", "Ctrl"),
40+
service<ConfigurationSettings>().state.chatCompletionSettings.sendWithCtrlEnter
41+
)
42+
43+
private val sendWithShiftEnterCheckBox = JBCheckBox(
44+
Toolkit.getProperty("AWT.shift", "Shift"),
45+
service<ConfigurationSettings>().state.chatCompletionSettings.sendWithShiftEnter
46+
)
47+
3248
fun createPanel(): DialogPanel {
3349
return panel {
3450
row {
@@ -50,6 +66,20 @@ class ChatCompletionConfigurationForm {
5066
cell(psiStructureAnalyzeDepthField)
5167
.comment(CodeGPTBundle.get("configurationConfigurable.section.chatCompletion.psiStructure.analyzeDepth.comment"))
5268
}
69+
group(CodeGPTBundle.get("configurationConfigurable.section.chatCompletion.sendMessageShortcut.title")) {
70+
row {
71+
comment(CodeGPTBundle.get("configurationConfigurable.section.chatCompletion.sendMessageShortcut.description"))
72+
}
73+
row {
74+
cell(sendWithCtrlEnterCheckBox)
75+
}
76+
row {
77+
cell(sendWithAltEnterCheckBox)
78+
}
79+
row {
80+
cell(sendWithShiftEnterCheckBox)
81+
}
82+
}
5383
}.withBorder(JBUI.Borders.emptyLeft(16))
5484
}
5585

@@ -58,6 +88,9 @@ class ChatCompletionConfigurationForm {
5888
psiStructureCheckBox.isSelected = prevState.psiStructureEnabled
5989
psiStructureAnalyzeDepthField.number = prevState.psiStructureAnalyzeDepth
6090
clickableLinksCheckBox.isSelected = prevState.clickableLinksEnabled
91+
sendWithAltEnterCheckBox.isSelected = prevState.sendWithAltEnter
92+
sendWithCtrlEnterCheckBox.isSelected = prevState.sendWithCtrlEnter
93+
sendWithShiftEnterCheckBox.isSelected = prevState.sendWithShiftEnter
6194
}
6295

6396
fun getFormState(): ChatCompletionSettingsState {
@@ -66,6 +99,9 @@ class ChatCompletionConfigurationForm {
6699
this.psiStructureEnabled = psiStructureCheckBox.isSelected
67100
this.psiStructureAnalyzeDepth = psiStructureAnalyzeDepthField.number
68101
this.clickableLinksEnabled = clickableLinksCheckBox.isSelected
102+
this.sendWithAltEnter = sendWithAltEnterCheckBox.isSelected
103+
this.sendWithCtrlEnter = sendWithCtrlEnterCheckBox.isSelected
104+
this.sendWithShiftEnter = sendWithShiftEnterCheckBox.isSelected
69105
}
70106
}
71107
}

src/main/kotlin/ee/carlrobert/codegpt/settings/configuration/ConfigurationSettings.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class ChatCompletionSettingsState : BaseState() {
5050
var psiStructureEnabled by property(true)
5151
var psiStructureAnalyzeDepth by property(3)
5252
var clickableLinksEnabled by property(true)
53+
var sendWithAltEnter by property(false)
54+
var sendWithCtrlEnter by property(false)
55+
var sendWithShiftEnter by property(false)
5356
}
5457

5558
class CodeCompletionSettingsState : BaseState() {

src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/PromptTextFieldEventDispatcher.kt

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package ee.carlrobert.codegpt.ui.textarea
22

3-
import com.intellij.codeInsight.lookup.impl.LookupImpl
43
import com.intellij.ide.IdeEventQueue
54
import com.intellij.openapi.application.runUndoTransparentWriteAction
65
import com.intellij.openapi.util.TextRange
@@ -13,6 +12,7 @@ import java.awt.event.KeyEvent
1312
import java.awt.event.MouseEvent
1413
import java.util.*
1514
import com.intellij.openapi.ide.CopyPasteManager
15+
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings
1616
import java.awt.datatransfer.DataFlavor
1717

1818
class PromptTextFieldEventDispatcher(
@@ -42,12 +42,31 @@ class PromptTextFieldEventDispatcher(
4242
}
4343
}
4444
KeyEvent.VK_ENTER -> {
45-
if (e.isShiftDown) {
46-
handleShiftEnter(e)
47-
} else if (e.modifiersEx and InputEvent.ALT_DOWN_MASK == 0
48-
&& e.modifiersEx and InputEvent.CTRL_DOWN_MASK == 0
49-
) {
50-
onSubmit(e)
45+
val settings =
46+
ConfigurationSettings.getState().chatCompletionSettings
47+
val anyModifierConfigured =
48+
settings.sendWithCtrlEnter || settings.sendWithAltEnter || settings.sendWithShiftEnter
49+
50+
if (anyModifierConfigured) {
51+
var expectedModifiers = 0
52+
if (settings.sendWithCtrlEnter) expectedModifiers = expectedModifiers or InputEvent.CTRL_DOWN_MASK
53+
if (settings.sendWithAltEnter) expectedModifiers = expectedModifiers or InputEvent.ALT_DOWN_MASK
54+
if (settings.sendWithShiftEnter) expectedModifiers = expectedModifiers or InputEvent.SHIFT_DOWN_MASK
55+
56+
val eventModifiers = e.modifiersEx and (InputEvent.CTRL_DOWN_MASK or InputEvent.ALT_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK)
57+
58+
if (eventModifiers == expectedModifiers) {
59+
onSubmit(e)
60+
} else {
61+
handleNewline(e)
62+
}
63+
} else {
64+
// No modifiers configured: send on plain Enter
65+
if (!e.isControlDown && !e.isAltDown && !e.isShiftDown) {
66+
onSubmit(e)
67+
} else {
68+
handleNewline(e)
69+
}
5170
}
5271
}
5372
}
@@ -65,7 +84,7 @@ class PromptTextFieldEventDispatcher(
6584
}
6685
}
6786

68-
private fun handleShiftEnter(e: KeyEvent) {
87+
private fun handleNewline(e: KeyEvent) {
6988
val parent = findParent()
7089
if (parent is PromptTextField) {
7190
runUndoTransparentWriteAction {

src/main/resources/messages/codegpt.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ configurationConfigurable.section.chatCompletion.psiStructure.analyzeDepth.comme
168168
configurationConfigurable.section.chatCompletion.psiStructure.description=If enabled, the class structure that is present in the imports of the attached files will be added in the context of the dialog. A structure refers to the source code in files that include constructors, fields, and methods, with all modifiers, arguments, and return types, but without an implementation. The implementation of dependencies is intentionally excluded in order to find a balance between a high-quality chat context and saving tokens.
169169
configurationConfigurable.section.chatCompletion.clickableLinks.title=Show clickable links for classes and methods
170170
configurationConfigurable.section.chatCompletion.clickableLinks.description=If enabled, code references in answers become clickable so you can jump to them in your IDE.
171+
configurationConfigurable.section.chatCompletion.sendMessageShortcut.title=Send Message Shortcut
172+
configurationConfigurable.section.chatCompletion.sendMessageShortcut.description=If none are selected, 'Enter' by itself sends the message. If any are selected, the chosen shortcut plus 'Enter' sends the message and 'Enter' by itself inserts a newline.
171173
settingsConfigurable.service.llama.predefinedModel.comment=Download and use vetted models from HuggingFace.
172174
settingsConfigurable.service.llama.customModel.comment=Use your own GGUF model file from a local path on your computer.
173175
settingsConfigurable.service.custom.openai.testConnection.label=Test Connection

0 commit comments

Comments
 (0)