Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pluginVersion = 3.8.1

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 261
pluginUntilBuild = 261.*
pluginUntilBuild = 262.*

# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class ConfigurationComponent {
private final JBTextField temperatureField;
private final CodeCompletionConfigurationForm codeCompletionForm;
private final ChatCompletionConfigurationForm chatCompletionForm;
private final ContextSuggestionConfigurationForm contextSuggestionForm;
private final ScreenshotConfigurationForm screenshotForm;

public ConfigurationComponent(
Expand Down Expand Up @@ -75,6 +76,7 @@ public void changedUpdate(DocumentEvent e) {

codeCompletionForm = new CodeCompletionConfigurationForm();
chatCompletionForm = new ChatCompletionConfigurationForm();
contextSuggestionForm = new ContextSuggestionConfigurationForm();
screenshotForm = new ScreenshotConfigurationForm();
screenshotForm.loadState(configuration.getScreenshotWatchPaths());

Expand All @@ -96,6 +98,9 @@ public void changedUpdate(DocumentEvent e) {
.addComponent(new TitledSeparator(
CodeGPTBundle.get("configurationConfigurable.section.chatCompletion.title")))
.addComponent(chatCompletionForm.createPanel())
.addComponent(new TitledSeparator(
CodeGPTBundle.get("configurationConfigurable.section.contextSuggestions.title")))
.addComponent(contextSuggestionForm.createPanel())
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
Expand All @@ -114,6 +119,7 @@ public ConfigurationSettingsState getCurrentFormState() {
state.setAutoFormattingEnabled(autoFormattingCheckBox.isSelected());
state.setCodeCompletionSettings(codeCompletionForm.getFormState());
state.setChatCompletionSettings(chatCompletionForm.getFormState());
state.setContextSuggestionSettings(contextSuggestionForm.getFormState());

var screenshotPaths = screenshotForm.getState();
state.getScreenshotWatchPaths().clear();
Expand All @@ -132,6 +138,7 @@ public void resetForm() {
autoFormattingCheckBox.setSelected(configuration.getAutoFormattingEnabled());
codeCompletionForm.resetForm(configuration.getCodeCompletionSettings());
chatCompletionForm.resetForm(configuration.getChatCompletionSettings());
contextSuggestionForm.resetForm(configuration.getContextSuggestionSettings());
screenshotForm.loadState(configuration.getScreenshotWatchPaths());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ee.carlrobert.codegpt.settings.configuration

import com.intellij.openapi.components.*
import ee.carlrobert.codegpt.CodeGPTBundle
import ee.carlrobert.codegpt.actions.editor.EditorActionsUtil
import ee.carlrobert.codegpt.settings.prompts.CoreActionsState
import kotlin.math.max
Expand Down Expand Up @@ -36,6 +37,7 @@ class ConfigurationSettingsState : BaseState() {
var tableData by map<String, String>()
var chatCompletionSettings by property(ChatCompletionSettingsState())
var codeCompletionSettings by property(CodeCompletionSettingsState())
var contextSuggestionSettings by property(ContextSuggestionSettingsState())

init {
tableData.putAll(EditorActionsUtil.DEFAULT_ACTIONS)
Expand All @@ -57,6 +59,59 @@ class ChatCompletionSettingsState : BaseState() {
var sendWithShiftEnter by property(false)
}

object ContextSuggestionSettings {
const val DEFAULT_MAX_FILE_SUGGESTIONS = 50
const val DEFAULT_MAX_DIRECTORY_SUGGESTIONS = 25
const val MAX_FILE_SUGGESTIONS = 500
const val MAX_DIRECTORY_SUGGESTIONS = 70

private const val MIN_SUGGESTIONS = 1
private const val LOOKUP_RESULT_HEADROOM = 32

fun normalizeMaxFileSuggestions(value: Int): Int =
value.coerceIn(MIN_SUGGESTIONS, MAX_FILE_SUGGESTIONS)

fun normalizeMaxDirectorySuggestions(value: Int): Int =
value.coerceIn(MIN_SUGGESTIONS, MAX_DIRECTORY_SUGGESTIONS)

fun maxLookupResults(state: ConfigurationSettingsState = ConfigurationSettings.getState()): Int {
val fileLimit = normalizeMaxFileSuggestions(state.contextSuggestionSettings.maxFileSuggestions)
val directoryLimit =
normalizeMaxDirectorySuggestions(state.contextSuggestionSettings.maxDirectorySuggestions)
return fileLimit + directoryLimit + LOOKUP_RESULT_HEADROOM
}
}

class ContextSuggestionSettingsState : BaseState() {
var maxFileSuggestions by property(ContextSuggestionSettings.DEFAULT_MAX_FILE_SUGGESTIONS)
var maxDirectorySuggestions by property(ContextSuggestionSettings.DEFAULT_MAX_DIRECTORY_SUGGESTIONS)
var blankFileSuggestionMode by enum(ContextSuggestionBlankFileSuggestionMode.OPEN_AND_RECENT)
var fileSortMode by enum(ContextSuggestionFileSortMode.PRESERVE_CURRENT_ORDER)
var pathDetailsMode by enum(ContextSuggestionPathDetailsMode.FULL_PATH)
}

enum class ContextSuggestionBlankFileSuggestionMode(private val messageKey: String) {
OPEN_AND_RECENT("configurationConfigurable.section.contextSuggestions.blankFileSuggestionMode.option.openAndRecent"),
OPEN_RECENT_AND_PROJECT("configurationConfigurable.section.contextSuggestions.blankFileSuggestionMode.option.openRecentAndProject");

fun displayName(): String = CodeGPTBundle.get(messageKey)
}

enum class ContextSuggestionFileSortMode(private val messageKey: String) {
FILE_NAME_ASCENDING("configurationConfigurable.section.contextSuggestions.fileSortMode.option.fileNameAscending"),
FOLDER_THEN_FILE_ASCENDING("configurationConfigurable.section.contextSuggestions.fileSortMode.option.folderThenFileAscending"),
PRESERVE_CURRENT_ORDER("configurationConfigurable.section.contextSuggestions.fileSortMode.option.preserveCurrentOrder");

fun displayName(): String = CodeGPTBundle.get(messageKey)
}

enum class ContextSuggestionPathDetailsMode(private val messageKey: String) {
FULL_PATH("configurationConfigurable.section.contextSuggestions.pathDetailsMode.option.fullPath"),
DIRECTORY_ONLY("configurationConfigurable.section.contextSuggestions.pathDetailsMode.option.directoryOnly");

fun displayName(): String = CodeGPTBundle.get(messageKey)
}

class CodeCompletionSettingsState : BaseState() {
var treeSitterProcessingEnabled by property(true)
var gitDiffEnabled by property(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package ee.carlrobert.codegpt.settings.configuration

import com.intellij.openapi.components.service
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.DialogPanel
import com.intellij.ui.EnumComboBoxModel
import com.intellij.ui.components.fields.IntegerField
import com.intellij.ui.dsl.builder.panel
import com.intellij.util.ui.JBUI
import ee.carlrobert.codegpt.CodeGPTBundle
import java.awt.Component
import javax.swing.DefaultListCellRenderer
import javax.swing.JList

class ContextSuggestionConfigurationForm {

private val maxFileSuggestionsField = IntegerField(
"max_file_suggestions",
1,
ContextSuggestionSettings.MAX_FILE_SUGGESTIONS
).apply {
columns = 12
value = service<ConfigurationSettings>().state.contextSuggestionSettings.maxFileSuggestions
}

private val maxDirectorySuggestionsField = IntegerField(
"max_directory_suggestions",
1,
ContextSuggestionSettings.MAX_DIRECTORY_SUGGESTIONS
).apply {
columns = 12
value = service<ConfigurationSettings>().state.contextSuggestionSettings.maxDirectorySuggestions
}
private val blankFileSuggestionModeComboBox =
ComboBox(EnumComboBoxModel(ContextSuggestionBlankFileSuggestionMode::class.java)).apply {
selectedItem = service<ConfigurationSettings>().state.contextSuggestionSettings.blankFileSuggestionMode
renderer = object : DefaultListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val displayValue =
(value as? ContextSuggestionBlankFileSuggestionMode)?.displayName() ?: value
return super.getListCellRendererComponent(
list,
displayValue,
index,
isSelected,
cellHasFocus
)
}
}
}
private val fileSortModeComboBox =
ComboBox(EnumComboBoxModel(ContextSuggestionFileSortMode::class.java)).apply {
selectedItem = service<ConfigurationSettings>().state.contextSuggestionSettings.fileSortMode
renderer = object : DefaultListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val displayValue = (value as? ContextSuggestionFileSortMode)?.displayName() ?: value
return super.getListCellRendererComponent(
list,
displayValue,
index,
isSelected,
cellHasFocus
)
}
}
}
private val pathDetailsModeComboBox =
ComboBox(EnumComboBoxModel(ContextSuggestionPathDetailsMode::class.java)).apply {
selectedItem = service<ConfigurationSettings>().state.contextSuggestionSettings.pathDetailsMode
renderer = object : DefaultListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val displayValue = (value as? ContextSuggestionPathDetailsMode)?.displayName() ?: value
return super.getListCellRendererComponent(
list,
displayValue,
index,
isSelected,
cellHasFocus
)
}
}
}

fun createPanel(): DialogPanel {
return panel {
row {
label(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.maxFileSuggestions.title"
)
)
cell(maxFileSuggestionsField)
.comment(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.maxFileSuggestions.description"
)
)
}
row {
label(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.maxDirectorySuggestions.title"
)
)
cell(maxDirectorySuggestionsField)
.comment(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.maxDirectorySuggestions.description"
)
)
}
row {
label(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.blankFileSuggestionMode.title"
)
)
cell(blankFileSuggestionModeComboBox)
.comment(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.blankFileSuggestionMode.description"
)
)
}
row {
label(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.fileSortMode.title"
)
)
cell(fileSortModeComboBox)
.comment(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.fileSortMode.description"
)
)
}
row {
label(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.pathDetailsMode.title"
)
)
cell(pathDetailsModeComboBox)
.comment(
CodeGPTBundle.get(
"configurationConfigurable.section.contextSuggestions.pathDetailsMode.description"
)
)
}
}.withBorder(JBUI.Borders.emptyLeft(16))
}

fun resetForm(prevState: ContextSuggestionSettingsState) {
maxFileSuggestionsField.value = prevState.maxFileSuggestions
maxDirectorySuggestionsField.value = prevState.maxDirectorySuggestions
blankFileSuggestionModeComboBox.selectedItem = prevState.blankFileSuggestionMode
fileSortModeComboBox.selectedItem = prevState.fileSortMode
pathDetailsModeComboBox.selectedItem = prevState.pathDetailsMode
}

fun getFormState(): ContextSuggestionSettingsState {
return ContextSuggestionSettingsState().apply {
maxFileSuggestions = maxFileSuggestionsField.value
maxDirectorySuggestions = maxDirectorySuggestionsField.value
blankFileSuggestionMode =
blankFileSuggestionModeComboBox.selectedItem as? ContextSuggestionBlankFileSuggestionMode
?: ContextSuggestionBlankFileSuggestionMode.OPEN_AND_RECENT
fileSortMode = fileSortModeComboBox.selectedItem as? ContextSuggestionFileSortMode
?: ContextSuggestionFileSortMode.PRESERVE_CURRENT_ORDER
pathDetailsMode = pathDetailsModeComboBox.selectedItem as? ContextSuggestionPathDetailsMode
?: ContextSuggestionPathDetailsMode.FULL_PATH
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.intellij.util.IncorrectOperationException
import com.intellij.util.ui.JBUI
import ee.carlrobert.codegpt.CodeGPTBundle
import ee.carlrobert.codegpt.CodeGPTKeys.IS_PROMPT_TEXT_FIELD_DOCUMENT
import ee.carlrobert.codegpt.settings.configuration.ContextSuggestionSettings
import ee.carlrobert.codegpt.settings.service.FeatureType
import ee.carlrobert.codegpt.ui.dnd.FileDragAndDrop
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagManager
Expand Down Expand Up @@ -1005,7 +1006,7 @@ class PromptTextField(
) {
val reusableItems = lookupItems
.filterNot { it is LoadingLookupItem || it is StatusLookupItem }
.take(PromptTextFieldConstants.MAX_SEARCH_RESULTS)
.take(ContextSuggestionSettings.maxLookupResults())
if (reusableItems.isEmpty()) {
if (!lookupSearchLoading) {
clearVisibleLookupItems()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ee.carlrobert.codegpt.ui.textarea
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.project.Project
import com.intellij.psi.codeStyle.MinusculeMatcher
import ee.carlrobert.codegpt.settings.configuration.ContextSuggestionSettings
import ee.carlrobert.codegpt.settings.service.FeatureType
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagManager
import ee.carlrobert.codegpt.ui.textarea.lookup.LookupActionItem
Expand Down Expand Up @@ -202,7 +203,7 @@ class SearchManager(
}
.sortedByDescending { it.second }
.map { it.first }
.take(PromptTextFieldConstants.MAX_SEARCH_RESULTS)
.take(ContextSuggestionSettings.maxLookupResults())
}

private fun createMatcher(searchText: String): MinusculeMatcher {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ee.carlrobert.codegpt.ui.textarea.lookup.action

import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings
import ee.carlrobert.codegpt.settings.configuration.ContextSuggestionPathDetailsMode

internal fun contextSuggestionTypeText(project: Project, file: VirtualFile): String? {
val projectDir = project.guessProjectDir()
return when (ConfigurationSettings.getState().contextSuggestionSettings.pathDetailsMode) {
ContextSuggestionPathDetailsMode.FULL_PATH -> projectRelativePath(projectDir, file) ?: file.path
ContextSuggestionPathDetailsMode.DIRECTORY_ONLY -> parentDirectoryPath(projectDir, file)
}
}

private fun parentDirectoryPath(projectDir: VirtualFile?, file: VirtualFile): String? {
val parent = file.parent ?: return null
return if (projectDir != null) {
val relativeParentPath = VfsUtil.getRelativePath(parent, projectDir) ?: return parent.path
if (relativeParentPath.isEmpty()) "." else relativeParentPath
} else {
parent.path
}
}

private fun projectRelativePath(projectDir: VirtualFile?, file: VirtualFile): String? {
if (projectDir == null) {
return null
}
return VfsUtil.getRelativePath(file, projectDir)
}
Loading