forked from huggingface/llm-vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtextListener.ts
116 lines (106 loc) · 3.42 KB
/
textListener.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import {
Position,
TextDocument,
TextDocumentChangeEvent,
TextDocumentContentChangeEvent,
TextLine,
} from "vscode";
import { debounce } from "debounce";
import {
getCurrentSuggestion,
setSuggestionsState,
} from "./inlineSuggestionState";
import runCompletion from "../runCompletion";
import setInlineSuggestion from "./setInlineSuggestion";
import clearInlineSuggestionsState from "./clearDecoration";
import { isInSnippetInsertion } from "./snippets/blankSnippet";
import { URI_SCHEME_FILE } from "../globals/consts";
import { sleep } from "../utils/utils";
import { Capability, isCapabilityEnabled } from "../capabilities/capabilities";
import getCurrentPosition, {
isEmptyLinesWithNewlineAutoInsert,
isOnlyWhitespaces,
} from "./positionExtracter";
import { AutocompleteResult } from "../binary/requests/requests";
import { completionIsAllowed } from "../provideCompletionItems";
const EMPTY_LINE_WARMUP_MILLIS = 250;
const EMPTY_LINE_DEBOUNCE = 550;
const debouncedEmptyLinesRequest = debounce(
(document: TextDocument, currentPosition: Position) => {
runCompletion(document, currentPosition)
.then((autocompleteResult) =>
setCompletion(autocompleteResult, document, currentPosition)
)
.catch((err) =>
console.error("Could not request completion at empty line: ", err)
);
},
EMPTY_LINE_DEBOUNCE
);
export default async function textListener({
document,
contentChanges,
}: TextDocumentChangeEvent): Promise<void> {
const [change] = contentChanges;
if (!change) {
return;
}
const currentTextPosition = getCurrentPosition(change);
if (!completionIsAllowed(document, currentTextPosition)) {
return;
}
const emptyLinesEnabled = isCapabilityEnabled(
Capability.EMPTY_LINE_SUGGESTIONS
);
const shouldHandleEmptyLine =
emptyLinesEnabled &&
isEmptyLine(change, document.lineAt(currentTextPosition.line)) &&
!isInSnippetInsertion();
debouncedEmptyLinesRequest.clear();
if (shouldHandleEmptyLine) {
await runCompletion(document, currentTextPosition);
await sleep(EMPTY_LINE_WARMUP_MILLIS);
debouncedEmptyLinesRequest(document, currentTextPosition);
return;
}
if (
(shouldHandleEmptyLine || isSingleTypingChange(contentChanges, change)) &&
document.uri.scheme === URI_SCHEME_FILE
) {
const autocompleteResult = await runCompletion(
document,
currentTextPosition
);
await setCompletion(autocompleteResult, document, currentTextPosition);
}
}
async function setCompletion(
autocompleteResult: AutocompleteResult | null | undefined,
document: TextDocument,
currentTextPosition: Position
): Promise<void> {
await setSuggestionsState(autocompleteResult);
const currentSuggestion = getCurrentSuggestion();
if (currentSuggestion) {
await setInlineSuggestion(document, currentTextPosition, currentSuggestion);
return;
}
void clearInlineSuggestionsState();
}
function isEmptyLine(
change: TextDocumentContentChangeEvent,
currentLine: TextLine
): boolean {
return (
isEmptyLinesWithNewlineAutoInsert(change) ||
isOnlyWhitespaces(currentLine.text)
);
}
export function isSingleTypingChange(
contentChanges: readonly TextDocumentContentChangeEvent[],
change: TextDocumentContentChangeEvent
): boolean {
const isSingleSelectionChange = contentChanges.length === 1;
const isSingleCharacterChange = change.text.length === 1;
return isSingleSelectionChange && isSingleCharacterChange;
}