Skip to content

Commit

Permalink
Add always-on option
Browse files Browse the repository at this point in the history
  • Loading branch information
tmcw committed Jul 25, 2024
1 parent 450fb92 commit 88b2c0d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 65 deletions.
138 changes: 73 additions & 65 deletions src/completionRequester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,76 @@ function shouldIgnoreUpdate(update: ViewUpdate) {
}
}

async function requestCompletion(update: ViewUpdate, lastPos?: number) {
const config = update.view.state.facet(codeiumConfig);
const { override } = update.view.state.facet(codeiumOtherDocumentsConfig);

const otherDocuments = await override();

// Get the current position and source
const state = update.state;
const pos = state.selection.main.head;
const source = state.doc.toString();

// Request completion from the server
try {
const completionResult = await getCodeiumCompletions({
text: source,
cursorOffset: pos,
config,
otherDocuments,
});

if (!completionResult || completionResult.completionItems.length === 0) {
return;
}

// Check if the position is still the same. If
// it has changed, ignore the code that we just
// got from the API and don't show anything.
if (
!(
(lastPos === undefined || pos === lastPos) &&
completionStatus(update.view.state) !== "active" &&
update.view.hasFocus
)
) {
return;
}

// Dispatch an effect to add the suggestion
// If the completion starts before the end of the line,
// check the end of the line with the end of the completion
const changeSpecs = completionsToChangeSpec(completionResult);

const index = 0;
const firstSpec = changeSpecs.at(index);
if (!firstSpec) return;
const insertChangeSet = ChangeSet.of(firstSpec, state.doc.length);
const reverseChangeSet = insertChangeSet.invert(state.doc);

update.view.dispatch({
changes: insertChangeSet,
effects: addSuggestions.of({
index,
reverseChangeSet,
changeSpecs,
}),
annotations: [
copilotIgnore.of(null),
copilotEvent.of(null),
Transaction.addToHistory.of(false),
],
});
} catch (error) {
console.warn("copilot completion failed", error);
// Javascript wait for 500ms for some reason is necessary here.
// TODO - FIGURE OUT WHY THIS RESOLVES THE BUG

await new Promise((resolve) => setTimeout(resolve, 300));
}
}

/**
* A view plugin that requests completions from the server after a delay
*/
Expand All @@ -57,7 +127,7 @@ export function completionRequester() {

return EditorView.updateListener.of((update: ViewUpdate) => {
const config = update.view.state.facet(codeiumConfig);
const { override } = update.view.state.facet(codeiumOtherDocumentsConfig);
if (!config.alwaysOn) return;

if (!shouldRequestCompletion(update)) return;

Expand Down Expand Up @@ -85,76 +155,14 @@ export function completionRequester() {
return;
}

const source = state.doc.toString();

// Set a new timeout to request completion
timeout = setTimeout(async () => {
// Check if the position has changed
if (pos !== lastPos) return;

const otherDocuments = await override();

// Request completion from the server
try {
const completionResult = await getCodeiumCompletions({
text: source,
cursorOffset: pos,
config,
otherDocuments,
});

if (
!completionResult ||
completionResult.completionItems.length === 0
) {
return;
}

// Check if the position is still the same. If
// it has changed, ignore the code that we just
// got from the API and don't show anything.
if (
!(
pos === lastPos &&
completionStatus(update.view.state) !== "active" &&
update.view.hasFocus
)
) {
return;
}

// Dispatch an effect to add the suggestion
// If the completion starts before the end of the line,
// check the end of the line with the end of the completion
const changeSpecs = completionsToChangeSpec(completionResult);

const index = 0;
const firstSpec = changeSpecs.at(index);
if (!firstSpec) return;
const insertChangeSet = ChangeSet.of(firstSpec, state.doc.length);
const reverseChangeSet = insertChangeSet.invert(state.doc);

update.view.dispatch({
changes: insertChangeSet,
effects: addSuggestions.of({
index,
reverseChangeSet,
changeSpecs,
}),
annotations: [
copilotIgnore.of(null),
copilotEvent.of(null),
Transaction.addToHistory.of(false),
],
});
} catch (error) {
console.warn("copilot completion failed", error);
// Javascript wait for 500ms for some reason is necessary here.
// TODO - FIGURE OUT WHY THIS RESOLVES THE BUG

await new Promise((resolve) => setTimeout(resolve, 300));
}
await requestCompletion(update, lastPos);
}, config.timeout);

// Update the last position
lastPos = pos;
});
Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export interface CodeiumConfig {
* when there are multiple suggestions to cycle through.
*/
widgetClass?: typeof DefaultCycleWidget | null;

/**
* Always request completions after a delay
*/
alwaysOn?: boolean;
}

export const codeiumConfig = Facet.define<
Expand All @@ -50,6 +55,7 @@ export const codeiumConfig = Facet.define<
language: Language.TYPESCRIPT,
timeout: 150,
widgetClass: DefaultCycleWidget,
alwaysOn: true,
},
{},
);
Expand Down

0 comments on commit 88b2c0d

Please sign in to comment.