diff options
| author | Paul Buetow <paul@buetow.org> | 2025-08-16 23:16:54 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-08-16 23:16:54 +0300 |
| commit | 765eda955eb811d08d867ff4d3914fc6d60c22dd (patch) | |
| tree | fdc87da6af9d86dbda2ea9ab08244e93fd167188 /internal/lsp/handlers.go | |
| parent | 1b01e35c34b953cbf51298f4650dc3215c382a4f (diff) | |
refactor(config): drop env-based config (except OPENAI_API_KEY)
- Switch to config-file-only; only OPENAI_API_KEY read from env.\n- llm: replace env autodetect with Config + NewFromConfig; add newOpenAI/newOllama.\n- lsp: NewServer now accepts injected llm.Client.\n- cli: remove env overrides; extend appConfig with provider-specific fields; build client from config + OPENAI_API_KEY.\n- docs: update README (config-only, defaults to OpenAI, minimal example); simplify flags table.\n- add config.json.example.\n- prompts: enforce ;text; (no spaces) and add ;;text; to remove entire line; tests added.
Diffstat (limited to 'internal/lsp/handlers.go')
| -rw-r--r-- | internal/lsp/handlers.go | 106 |
1 files changed, 78 insertions, 28 deletions
diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go index d8c13a1..8edfbb6 100644 --- a/internal/lsp/handlers.go +++ b/internal/lsp/handlers.go @@ -237,36 +237,86 @@ func (s *Server) tryLLMCompletion(p CompletionParams, above, current, below, fun // collectPromptRemovalEdits returns edits to remove all inline prompt markers. // Supported form (inclusive): -// - ";...;" (optional single space after trailing ';') +// - ";...;" where there is no space immediately after the first ';' +// and no space immediately before the last ';'. An optional single space +// after the trailing ';' is also removed for cleanliness. // Multiple markers per line are supported. func (s *Server) collectPromptRemovalEdits(uri string) []TextEdit { - d := s.getDocument(uri) - if d == nil || len(d.lines) == 0 { - return nil - } - var edits []TextEdit - for i, line := range d.lines { - // Scan for ;...; markers - startSemi := 0 - for startSemi < len(line) { - j := strings.Index(line[startSemi:], ";") - if j < 0 { - break - } - j += startSemi - k := strings.Index(line[j+1:], ";") - if k < 0 { - break - } - endChar := j + 1 + k + 1 // include trailing ';' - if endChar < len(line) && line[endChar] == ' ' { - endChar++ - } - edits = append(edits, TextEdit{Range: Range{Start: Position{Line: i, Character: j}, End: Position{Line: i, Character: endChar}}, NewText: ""}) - startSemi = endChar - } - } - return edits + d := s.getDocument(uri) + if d == nil || len(d.lines) == 0 { + return nil + } + var edits []TextEdit + for i, line := range d.lines { + // If the line contains a double-semicolon trigger of the form + // ";;text;" (no space after the ";;" and no space before the closing ';'), + // remove the entire line. + removeWholeLine := false + { + pos := 0 + for pos < len(line) { + j := strings.Index(line[pos:], ";;") + if j < 0 { break } + j += pos + // ensure there's a non-space after the two semicolons + if j+2 >= len(line) || line[j+2] == ' ' { pos = j + 2; continue } + // find closing ';' after the content + k := strings.Index(line[j+2:], ";") + if k < 0 { break } + closeIdx := j + 2 + k + // ensure char before closing ';' is not a space + if closeIdx-1 < 0 || line[closeIdx-1] == ' ' { pos = closeIdx + 1; continue } + removeWholeLine = true + break + } + } + if removeWholeLine { + edits = append(edits, TextEdit{Range: Range{Start: Position{Line: i, Character: 0}, End: Position{Line: i, Character: len(line)}}, NewText: ""}) + continue + } + // Scan for ;...; markers that have no spaces directly inside the semicolons + startSemi := 0 + for startSemi < len(line) { + j := strings.Index(line[startSemi:], ";") + if j < 0 { + break + } + j += startSemi + k := strings.Index(line[j+1:], ";") + if k < 0 { + break + } + // Require no space immediately after the first ';' + if j+1 >= len(line) || line[j+1] == ' ' { + startSemi = j + 1 + continue + } + // Ignore patterns that start with double semicolon here; handled above + if line[j+1] == ';' { + startSemi = j + 2 + continue + } + // Index of the closing ';' + closeIdx := j + 1 + k + // Require no space immediately before the closing ';' + if closeIdx-1 < 0 || line[closeIdx-1] == ' ' { + startSemi = closeIdx + 1 + continue + } + // Require at least one character between the semicolons + if closeIdx-(j+1) < 1 { + startSemi = closeIdx + 1 + continue + } + endChar := closeIdx + 1 // include trailing ';' + if endChar < len(line) && line[endChar] == ' ' { + endChar++ + } + edits = append(edits, TextEdit{Range: Range{Start: Position{Line: i, Character: j}, End: Position{Line: i, Character: endChar}}, NewText: ""}) + startSemi = endChar + } + } + return edits } func inParamList(current string, cursor int) bool { |
