1
1
// Copyright 2024 Cline Bot Inc. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
- package cc.unitmesh.devti.language. agenttool
2
+ package cc.unitmesh.devti.agenttool.search
3
3
4
- import com.google.gson.JsonParser
5
4
import com.intellij.execution.configurations.GeneralCommandLine
6
5
import com.intellij.execution.process.*
7
6
import com.intellij.openapi.diagnostic.Logger
8
- import com.intellij.openapi.diagnostic.logger
9
7
import com.intellij.openapi.project.Project
10
- import com.intellij.openapi.util.Key
11
- import kotlinx.serialization.Serializable
12
8
import org.jetbrains.annotations.NonNls
13
9
import org.jetbrains.annotations.SystemIndependent
14
10
import java.io.IOException
@@ -18,105 +14,6 @@ import java.nio.file.Paths
18
14
import java.util.*
19
15
import java.util.concurrent.CompletableFuture
20
16
import java.util.concurrent.TimeUnit
21
- import kotlin.text.compareTo
22
- import kotlin.text.get
23
-
24
-
25
- @Serializable
26
- public data class SearchResult (
27
- var filePath : String? = null ,
28
- var line : Int = 0 ,
29
- var column : Int = 0 ,
30
- var match : String? = null ,
31
- var beforeContext : MutableList <String ?> = ArrayList <String ?>(),
32
- var afterContext : MutableList <String ?> = ArrayList <String ?>()
33
- )
34
-
35
- public class RipgrepOutputProcessor : ProcessAdapter () {
36
- private val results: MutableList <SearchResult > = ArrayList <SearchResult >()
37
- private var currentResult: SearchResult ? = null
38
-
39
- override fun onTextAvailable (event : ProcessEvent , outputType : Key <* >) {
40
- if (outputType == = ProcessOutputTypes .STDOUT ) {
41
- parseJsonLine(event.text)
42
- }
43
- }
44
-
45
- private val jsonBuffer = StringBuilder ()
46
-
47
- fun parseJsonLine (line : String ) {
48
- if (line.isBlank()) {
49
- return
50
- }
51
-
52
- jsonBuffer.append(line)
53
-
54
- // Try to parse the buffer as JSON
55
- val json = try {
56
- JsonParser .parseString(jsonBuffer.toString())
57
- } catch (e: Exception ) {
58
- // If parsing fails, it might be because the JSON is incomplete
59
- // So we just return and wait for more lines
60
- return
61
- }
62
-
63
- // If parsing succeeds, clear the buffer and process the JSON
64
- jsonBuffer.clear()
65
-
66
- if (json.isJsonObject) {
67
- val jsonObject = json.asJsonObject
68
- val type = jsonObject.get(" type" ).asString
69
-
70
- when (type) {
71
- " match" -> {
72
- val data = jsonObject.getAsJsonObject(" data" )
73
- val path = data.getAsJsonObject(" path" ).get(" text" ).asString
74
- val lines = data.getAsJsonObject(" lines" ).get(" text" ).asString
75
- val lineNumber = data.get(" line_number" ).asInt
76
- val absoluteOffset = data.get(" absolute_offset" ).asInt
77
- val submatches = data.getAsJsonArray(" submatches" )
78
-
79
- currentResult = SearchResult (
80
- filePath = path,
81
- line = lineNumber,
82
- column = absoluteOffset,
83
- match = lines.trim()
84
- )
85
-
86
- submatches.forEach { submatch ->
87
- val submatchObj = submatch.asJsonObject
88
- val matchText = submatchObj.get(" match" ).asJsonObject.get(" text" ).asString
89
- currentResult?.match = matchText
90
- }
91
-
92
- results.add(currentResult!! )
93
- }
94
-
95
- " context" -> {
96
- val data = jsonObject.getAsJsonObject(" data" )
97
- val lines = data.getAsJsonObject(" lines" ).get(" text" ).asString
98
- val lineNumber = data.get(" line_number" ).asInt
99
-
100
- if (currentResult != null ) {
101
- if (lineNumber < currentResult!! .line) {
102
- currentResult!! .beforeContext.add(lines.trim())
103
- } else {
104
- currentResult!! .afterContext.add(lines.trim())
105
- }
106
- }
107
- }
108
- }
109
- }
110
- }
111
-
112
- fun getResults (): MutableList <SearchResult > {
113
- if (currentResult != null ) {
114
- results.add(currentResult!! )
115
- }
116
-
117
- return results
118
- }
119
- }
120
17
121
18
/* *
122
19
* 使用Ripgrep进行文件搜索
@@ -170,7 +67,7 @@ object RipgrepSearcher {
170
67
171
68
@Throws(IOException ::class )
172
69
private fun executeRipgrep (project : Project , rgPath : Path , directory : String , regex : String , filePattern : String? ):
173
- MutableList <SearchResult > {
70
+ MutableList <RipgrepSearchResult > {
174
71
val cmd = getCommandLine(rgPath, regex, filePattern, directory, project.basePath)
175
72
176
73
val handler: OSProcessHandler = ColoredProcessHandler (cmd)
@@ -213,14 +110,14 @@ object RipgrepSearcher {
213
110
return cmd
214
111
}
215
112
216
- private fun formatResults (results : MutableList <SearchResult >, basePath : String ): String {
113
+ private fun formatResults (results : MutableList <RipgrepSearchResult >, basePath : String ): String {
217
114
val output = StringBuilder ()
218
- val grouped: MutableMap <String ?, MutableList <SearchResult ?>? > =
219
- LinkedHashMap <String ?, MutableList <SearchResult ?>? > ()
115
+ val grouped: MutableMap <String ?, MutableList <RipgrepSearchResult ?>? > =
116
+ LinkedHashMap <String ?, MutableList <RipgrepSearchResult ?>? > ()
220
117
221
118
for (result in results) {
222
119
val relPath = getRelativePath(basePath, result.filePath!! )
223
- grouped.computeIfAbsent(relPath) { k: String? -> ArrayList <SearchResult ?>() }!! .add(result)
120
+ grouped.computeIfAbsent(relPath) { k: String? -> ArrayList <RipgrepSearchResult ?>() }!! .add(result)
224
121
}
225
122
226
123
for (entry in grouped.entries) {
0 commit comments