Skip to content

Commit

Permalink
Reorganize files, split requestCompletion into its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
tmcw committed Jul 25, 2024
1 parent d96a9f4 commit 77c6eae
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 85 deletions.
2 changes: 1 addition & 1 deletion demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { EditorView, basicSetup } from "codemirror";
import { javascript } from "@codemirror/lang-javascript";
import {
codeiumOtherDocumentsConfig,
startCompletion,
Language,
copilotPlugin,
} from "../src/plugin.js";
import { python } from "@codemirror/lang-python";
import { keymap } from "@codemirror/view";
import { startCompletion } from "../src/commands.js";

new EditorView({
doc: "// Factorial function",
Expand Down
2 changes: 1 addition & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
addSuggestions,
clearSuggestion,
} from "./effects.js";
import { requestCompletion } from "./completionRequester.js";
import { requestCompletion } from "./requestCompletion.js";

/**
* Accepting a suggestion: we remove the ghost text, which
Expand Down
87 changes: 4 additions & 83 deletions src/completionRequester.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { CompletionContext, completionStatus } from "@codemirror/autocomplete";
import { ChangeSet, Transaction } from "@codemirror/state";
import { EditorView, type ViewUpdate } from "@codemirror/view";
import { completionsToChangeSpec, getCodeiumCompletions } from "./codeium.js";
import {
acceptSuggestion,
addSuggestions,
clearSuggestion,
} from "./effects.js";
import { acceptSuggestion, clearSuggestion } from "./effects.js";
import { completionDecoration } from "./completionDecoration.js";
import { copilotEvent, copilotIgnore } from "./annotations.js";
import { codeiumConfig, codeiumOtherDocumentsConfig } from "./config.js";
import { copilotEvent } from "./annotations.js";
import { codeiumConfig } from "./config.js";
import { requestCompletion } from "./requestCompletion.js";

/**
* To request a completion, the document needs to have been
Expand Down Expand Up @@ -48,80 +43,6 @@ function shouldIgnoreUpdate(update: ViewUpdate) {
}
}

/**
* Inner 'requestCompletion' API, which can optionally
* be run all the time if you set `alwaysOn`
*/
export async function requestCompletion(view: EditorView, lastPos?: number) {
const config = view.state.facet(codeiumConfig);
const { override } = view.state.facet(codeiumOtherDocumentsConfig);

const otherDocuments = await override();

// Get the current position and source
const state = view.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(view.state) !== "active" &&
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);

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 Down
2 changes: 2 additions & 0 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
rejectSuggestionCommand,
acceptSuggestionCommand,
nextSuggestionCommand,
startCompletion,
} from "./commands.js";
import {
type CodeiumConfig,
Expand Down Expand Up @@ -112,6 +113,7 @@ export {
codeiumConfig,
codeiumOtherDocumentsConfig,
nextSuggestionCommand,
startCompletion,
type CodeiumOtherDocumentsConfig,
type CodeiumConfig,
};
Expand Down
81 changes: 81 additions & 0 deletions src/requestCompletion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { completionStatus } from "@codemirror/autocomplete";
import { ChangeSet, Transaction } from "@codemirror/state";
import type { EditorView } from "@codemirror/view";
import { completionsToChangeSpec, getCodeiumCompletions } from "./codeium.js";
import { addSuggestions } from "./effects.js";
import { copilotEvent, copilotIgnore } from "./annotations.js";
import { codeiumConfig, codeiumOtherDocumentsConfig } from "./config.js";

/**
* Inner 'requestCompletion' API, which can optionally
* be run all the time if you set `alwaysOn`
*/
export async function requestCompletion(view: EditorView, lastPos?: number) {
const config = view.state.facet(codeiumConfig);
const { override } = view.state.facet(codeiumOtherDocumentsConfig);

const otherDocuments = await override();

// Get the current position and source
const state = view.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(view.state) !== "active" &&
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);

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));
}
}

0 comments on commit 77c6eae

Please sign in to comment.