Skip to content

Commit bf314d2

Browse files
committed
Update JsonCompletionProvider.kt
1 parent 9ba2975 commit bf314d2

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

src/main/kotlin/com/github/teahousestudios/akaribotdevplugin/completion/JsonCompletionProvider.kt

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.teahousestudios.akaribotdevplugin.completion
33
import com.github.teahousestudios.akaribotdevplugin.services.JsonLookupService
44
import com.intellij.codeInsight.completion.*
55
import com.intellij.codeInsight.lookup.LookupElementBuilder
6+
import com.intellij.openapi.util.TextRange
67
import com.intellij.util.ProcessingContext
78

89
class JsonCompletionProvider : CompletionProvider<CompletionParameters>() {
@@ -14,32 +15,68 @@ class JsonCompletionProvider : CompletionProvider<CompletionParameters>() {
1415
val project = parameters.position.project
1516
val items = JsonLookupService.getInstance(project).getLocaleData()
1617

18+
// find the string literal element ancestor to compute a prefix relative to the string start
19+
val stringElem = findStringLiteralElement(parameters)
20+
val doc = parameters.editor.document
21+
val caret = parameters.offset
22+
val prefix = if (stringElem != null) {
23+
try {
24+
val start = stringElem.textRange.startOffset
25+
val raw = doc.getText(TextRange(start, caret))
26+
// take substring after last space within the string literal
27+
val lastSpace = raw.lastIndexOf(' ')
28+
val token = if (lastSpace >= 0) raw.substring(lastSpace + 1) else raw
29+
// strip leading quote characters and non-alphanumeric chars so matching focuses on the token
30+
val cleaned = token.trimStart { ch -> ch == '\'' || ch == '"' || !ch.isLetterOrDigit() }
31+
cleaned
32+
} catch (_: Exception) {
33+
""
34+
}
35+
} else {
36+
""
37+
}
38+
39+
val localResult = result.withPrefixMatcher(prefix)
40+
1741
for (item in items) {
18-
result.addElement(LookupElementBuilder.create(item.key).withTypeText(item.value))
42+
localResult.addElement(LookupElementBuilder.create(item.key).withTypeText(item.value))
1943

2044
// I18N form with InsertHandler to avoid duplicate '{' when user already typed it
2145
val i18n = "{I18N:${item.key}}"
2246
val i18nElement = LookupElementBuilder.create(i18n).withTypeText(item.value)
2347
.withInsertHandler { ctx, _ ->
24-
val doc = ctx.document
25-
val start = ctx.startOffset
26-
if (start > 0) {
48+
val d = ctx.document
49+
val startOff = ctx.startOffset
50+
if (startOff > 0) {
2751
try {
28-
// look backwards skipping whitespace to find a previous non-space character
29-
var i = start - 1
30-
val seq = doc.charsSequence
52+
var i = startOff - 1
53+
val seq = d.charsSequence
54+
// skip whitespace backwards
3155
while (i >= 0 && seq[i].isWhitespace()) i--
3256
if (i >= 0 && seq[i] == '{') {
33-
// delete from the '{' up to the insertion start (removes brace and any spaces)
34-
doc.deleteString(i, start)
57+
d.deleteString(i, startOff)
3558
}
3659
} catch (_: Exception) {
3760
// ignore
3861
}
3962
}
4063
}
4164

42-
result.addElement(i18nElement)
65+
localResult.addElement(i18nElement)
66+
}
67+
}
68+
69+
private fun findStringLiteralElement(parameters: CompletionParameters): com.intellij.psi.PsiElement? {
70+
var element = parameters.position
71+
var depth = 0
72+
while (element != null && depth < 40) {
73+
val name = element::class.java.simpleName
74+
if (name.contains("PyStringLiteralExpression") || name.contains("StringTemplateExpression") || name.contains("LiteralExpression") || name.contains("StringLiteralExpression") || name.contains("KtLiteralStringTemplateEntry")) {
75+
return element
76+
}
77+
element = element.parent
78+
depth++
4379
}
80+
return null
4481
}
4582
}

0 commit comments

Comments
 (0)