summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-08-22 19:49:44 +0300
committerPaul Buetow <paul@buetow.org>2025-08-22 19:49:44 +0300
commit0478bd470c523c8a6e07d4fa4f11ca987c38cea9 (patch)
treed31b8c40d6eb44bc4acd7149bc21ba18de50b204 /internal
parentdcb0eaee01ddcb1fa931970df246764f09383c0d (diff)
chat: remove ';;' as in-editor chat trigger to avoid conflict with inline ';;text;' completion; update docs
Diffstat (limited to 'internal')
-rw-r--r--internal/lsp/handlers.go41
1 files changed, 35 insertions, 6 deletions
diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go
index 987bcbe..8c4fd51 100644
--- a/internal/lsp/handlers.go
+++ b/internal/lsp/handlers.go
@@ -527,7 +527,7 @@ func (s *Server) detectAndHandleChat(uri string) {
continue
}
pair := raw[j-1 : j+1]
- isTrigger := pair == ".." || pair == "??" || pair == "!!" || pair == "::" || pair == ";;"
+ isTrigger := pair == ".." || pair == "??" || pair == "!!" || pair == "::"
if !isTrigger {
continue
}
@@ -537,9 +537,8 @@ func (s *Server) detectAndHandleChat(uri string) {
if k < len(d.lines) && strings.HasPrefix(strings.TrimSpace(d.lines[k]), ">") {
continue
}
- // Derive prompt by removing 1 trailing char for punctuation pairs; remove both for ';;'
+ // Derive prompt by removing 1 trailing char for punctuation pairs
removeCount := 1
- if pair == ";;" { removeCount = 2 }
base := raw[:j+1-removeCount]
prompt := strings.TrimSpace(base)
if prompt == "" {
@@ -742,8 +741,9 @@ func (s *Server) tryLLMCompletion(p CompletionParams, above, current, below, fun
logging.AnsiGreen, logging.PreviewForLog(cleaned), logging.AnsiBase)
return s.makeCompletionItems(cleaned, inParams, current, p, docStr), true, false
}
- // If there is a bare ';;' (no valid ';;text;'), do not auto-trigger unless it was a manual invoke.
- if strings.Contains(current, ";;") && !hasDoubleSemicolonTrigger(current) && !manualInvoke {
+ // If there is a bare ';;' on the current or next line (no valid ';;text;'),
+ // do not auto-trigger unless it was a manual invoke.
+ if (isBareDoubleSemicolon(current) || isBareDoubleSemicolon(below)) && !manualInvoke {
logging.Logf("lsp ", "%scompletion skip=empty-double-semicolon line=%d char=%d current=%q%s", logging.AnsiYellow, p.Position.Line, p.Position.Character, trimLen(current), logging.AnsiBase)
return []CompletionItem{}, true, false
}
@@ -950,7 +950,11 @@ func (s *Server) isTriggerEvent(p CompletionParams, current string) bool {
b, _ := json.Marshal(p.Context)
_ = json.Unmarshal(b, &ctx)
}
- // TriggerKind 1 = Invoked (manual) — always allow
+ // If the line contains a bare ';;' (no ';;text;'), do not treat as a trigger source.
+ if strings.Contains(current, ";;") && !hasDoubleSemicolonTrigger(current) {
+ return false
+ }
+ // TriggerKind 1 = Invoked (manual) — always allow (unless bare ';;' above)
if ctx.TriggerKind == 1 {
return true
}
@@ -974,6 +978,10 @@ func (s *Server) isTriggerEvent(p CompletionParams, current string) bool {
if idx <= 0 || idx > len(current) {
return false
}
+ // Bare ';;' should not trigger via fallback char either
+ if strings.Contains(current, ";;") && !hasDoubleSemicolonTrigger(current) {
+ return false
+ }
ch := string(current[idx-1])
for _, c := range s.triggerChars {
if c == ch {
@@ -1217,6 +1225,27 @@ func lineHasInlinePrompt(line string) bool {
return hasDoubleSemicolonTrigger(line)
}
+// isBareDoubleSemicolon reports whether the line contains a standalone
+// double-semicolon marker with no inline content (";;" possibly with only
+// whitespace after it). It explicitly excludes the valid form ";;text;".
+func isBareDoubleSemicolon(line string) bool {
+ t := strings.TrimSpace(line)
+ if !strings.Contains(t, ";;") {
+ return false
+ }
+ if hasDoubleSemicolonTrigger(t) {
+ return false
+ }
+ if strings.HasPrefix(t, ";;") {
+ rest := strings.TrimSpace(t[2:])
+ // Bare if nothing follows or only semicolons/spaces remain without closing pattern
+ if rest == "" || rest == ";" {
+ return true
+ }
+ }
+ return false
+}
+
// stripDuplicateAssignmentPrefix removes a duplicated assignment prefix (e.g.,
// "name :=") from the beginning of the model suggestion when that same prefix
// already appears immediately to the left of the cursor on the current line.