Skip to content

Commit f552e0d

Browse files
committed
feat(completion): add support for text replacement in code completion
- Add `isReplacement` parameter to `CodeCompletionRequest` class. - Modify `CodeCompletionRequest.create()` method to include `isReplacement` parameter. - Add `Replace` interaction type in `TeamPromptExecTask.kt`. - Implement text replacement logic in `BaseCompletionTask.kt`. - Create `replaceText()` function in `InsertUtil.kt` to perform text replacement. This commit adds support for text replacement in code completion. It introduces a new `isReplacement` parameter to the `CodeCompletionRequest` class, which allows specifying whether the code completion is for replacement purposes. The `CodeCompletionRequest.create()` method is modified to include this new parameter. In `TeamPromptExecTask.kt`, a new interaction type called `Replace` is added, which triggers the code completion process with text replacement enabled. The text replacement logic is implemented in the `BaseCompletionTask.kt` file, which replaces the selected text with the suggested completion. Finally, a new function called `replaceText()` is created in `InsertUtil.kt` to perform the actual text replacement.
1 parent c99ed29 commit f552e0d

File tree

5 files changed

+50
-6
lines changed

5 files changed

+50
-6
lines changed

src/main/kotlin/cc/unitmesh/devti/custom/team/CustomActionPrompt.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,6 @@ enum class InteractionType {
125125
AppendCursor,
126126
AppendCursorStream,
127127
OutputFile,
128+
Replace
128129
;
129130
}

src/main/kotlin/cc/unitmesh/devti/custom/team/TeamPromptExecTask.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import cc.unitmesh.devti.gui.chat.ChatActionType
77
import cc.unitmesh.devti.gui.sendToChatWindow
88
import cc.unitmesh.devti.intentions.action.task.BaseCompletionTask
99
import cc.unitmesh.devti.intentions.action.task.CodeCompletionRequest
10+
import com.intellij.openapi.application.invokeLater
1011
import com.intellij.openapi.application.runReadAction
12+
import com.intellij.openapi.application.runWriteAction
1113
import com.intellij.openapi.editor.Editor
1214
import com.intellij.openapi.progress.ProgressIndicator
1315
import com.intellij.openapi.progress.ProgressManager
@@ -72,7 +74,21 @@ class TeamPromptExecTask(
7274
ProgressManager.getInstance()
7375
.runProcessWithProgressAsynchronously(task, BackgroundableProcessIndicator(task))
7476
}
77+
78+
InteractionType.Replace -> {
79+
val msgString = systemPrompt + "\n" + userPrompt
80+
val request = runReadAction {
81+
CodeCompletionRequest.create(editor, offset, element, null, msgString, isReplacement = true)
82+
} ?: return
83+
84+
val task = object : BaseCompletionTask(request) {
85+
override fun keepHistory(): Boolean = false
86+
override fun promptText(): String = msgString
87+
}
88+
89+
ProgressManager.getInstance()
90+
.runProcessWithProgressAsynchronously(task, BackgroundableProcessIndicator(task))
91+
}
7592
}
7693
}
77-
7894
}

src/main/kotlin/cc/unitmesh/devti/intentions/action/task/BaseCompletionTask.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ abstract class BaseCompletionTask(private val request: CodeCompletionRequest) :
5353
var currentOffset = request.offset
5454

5555
indicator.isIndeterminate = true
56-
indicator.fraction = 0.8
56+
indicator.fraction = 0.5
5757
indicator.text = AutoDevBundle.message("intentions.request.background.process.title")
5858

5959
LLMCoroutineScope.scope(request.project).launch {
@@ -67,13 +67,18 @@ abstract class BaseCompletionTask(private val request: CodeCompletionRequest) :
6767

6868
suggestion.append(char as String)
6969
invokeLater {
70-
if (!isCanceled) {
70+
if (!isCanceled && !request.isReplacement) {
7171
InsertUtil.insertStreamingToDoc(project, char, editor, currentOffset)
7272
currentOffset += char.length
7373
}
7474
}
7575
}
7676

77+
if (request.isReplacement) {
78+
InsertUtil.replaceText(project, editor, request.element, suggestion.toString())
79+
}
80+
81+
indicator.fraction = 0.8
7782
AutoDevStatusService.notifyApplication(AutoDevStatus.Done)
7883
logger.info("Suggestion: $suggestion")
7984
}

src/main/kotlin/cc/unitmesh/devti/intentions/action/task/CodeCompletionRequest.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,18 @@ class CodeCompletionRequest(
1919
val documentVersion: Long,
2020
val element: PsiElement?,
2121
val editor: Editor,
22-
val suffixText: String
22+
val suffixText: String,
23+
val isReplacement: Boolean = false,
2324
) : Disposable {
2425
companion object {
25-
fun create(editor: Editor, offset: Int, element: PsiElement?, prefix: String?, suffix: String?): CodeCompletionRequest? {
26+
fun create(
27+
editor: Editor,
28+
offset: Int,
29+
element: PsiElement?,
30+
prefix: String?,
31+
suffix: String?,
32+
isReplacement: Boolean = false
33+
): CodeCompletionRequest? {
2634
val project = editor.project ?: return null
2735
val document = editor.document
2836
val file = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return null
@@ -47,7 +55,8 @@ class CodeCompletionRequest(
4755
documentVersion,
4856
element,
4957
editor,
50-
suffixText
58+
suffixText,
59+
isReplacement
5160
)
5261

5362
}

src/main/kotlin/cc/unitmesh/devti/util/InsertUtil.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package cc.unitmesh.devti.util
22

33
import cc.unitmesh.devti.AutoDevBundle
4+
import com.intellij.openapi.application.runReadAction
45
import com.intellij.openapi.command.WriteCommandAction
56
import com.intellij.openapi.editor.Document
67
import com.intellij.openapi.editor.Editor
78
import com.intellij.openapi.editor.ScrollType
89
import com.intellij.openapi.project.Project
910
import com.intellij.openapi.util.TextRange
1011
import com.intellij.psi.PsiDocumentManager
12+
import com.intellij.psi.PsiElement
1113
import com.intellij.psi.codeStyle.CodeStyleManager
1214

1315
object InsertUtil {
@@ -42,4 +44,15 @@ object InsertUtil {
4244
editor.caretModel.moveToOffset(currentOffset + char.length)
4345
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
4446
}
47+
48+
fun replaceText(project: Project, editor: Editor, element: PsiElement?, output: String) {
49+
val primaryCaret = editor.caretModel.primaryCaret;
50+
val start = runReadAction { primaryCaret.selectionStart }
51+
val end = runReadAction { primaryCaret.selectionEnd }
52+
val document = runReadAction { editor.document }
53+
54+
WriteCommandAction.runWriteCommandAction(project) {
55+
document.replaceString(start, end, output)
56+
}
57+
}
4558
}

0 commit comments

Comments
 (0)