Skip to content

Commit

Permalink
feat: Add shouldComplete option (#27)
Browse files Browse the repository at this point in the history
- Adds some more JSDoc documentation
- Adds a new option `shouldComplete`, that accepts a `CompletionContext` and lets you decide whether to complete at a particular part of the document
  • Loading branch information
tmcw authored May 14, 2024
1 parent b344db6 commit ce70e64
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
7 changes: 7 additions & 0 deletions demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ const hiddenValue = "https://macwright.com/"`,
}),
copilotPlugin({
apiKey: "d49954eb-cfba-4992-980f-d8fb37f0e942",
shouldComplete(context) {
if (context.tokenBefore(["String"])) {
return true;
}
let match = context.matchBefore(/(@(?:\w*))(?:[./](\w*))?/);
return !match;
},
}),
],
parent: document.querySelector("#editor")!,
Expand Down
14 changes: 13 additions & 1 deletion src/completionRequester.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { completionStatus } from "@codemirror/autocomplete";
import { CompletionContext, completionStatus } from "@codemirror/autocomplete";
import { ChangeSet, Transaction } from "@codemirror/state";
import { EditorView, ViewUpdate } from "@codemirror/view";
import {
Expand Down Expand Up @@ -77,6 +77,18 @@ export function completionRequester() {
// Get the current position and source
const state = update.state;
const pos = state.selection.main.head;

// If we've configured a custom rule for when to show completions
// and that rule says no, don't offer completions.
if (
config.shouldComplete &&
!config.shouldComplete(
new CompletionContext(update.view.state, pos, false),
)
) {
return;
}

const source = state.doc.toString();

// Set a new timeout to request completion
Expand Down
19 changes: 19 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { Facet, combineConfig } from "@codemirror/state";
import { Language } from "./api/proto/exa/codeium_common_pb/codeium_common_pb.js";
import { Document } from "./api/proto/exa/language_server_pb/language_server_pb.js";
import { type PartialMessage } from "@bufbuild/protobuf";
import { type CompletionContext } from "@codemirror/autocomplete";

export interface CodeiumConfig {
/**
* Codeium API key
*/
apiKey: string;

/**
* The programming language of the given document.
*/
language?: Language;
/**
* Time in millseconds after typing to fetch
Expand All @@ -16,6 +21,15 @@ export interface CodeiumConfig {
timeout?: number;

authSource?: number;

/**
* An optional method that lets you decide whether Codeium
* should be triggered at a particular place in a document.
*
* Might be useful for if you're fighting with overlapping
* autocomplete sources.
*/
shouldComplete?: (context: CompletionContext) => boolean;
}

export const codeiumConfig = Facet.define<
Expand All @@ -40,6 +54,11 @@ export interface CodeiumOtherDocumentsConfig {
override?: () => Promise<OtherDocuments> | OtherDocuments;
}

/**
* Configuration for other documents included with the completion
* request. Adding other documents helps you get more accurate
* suggestions by adding context.
*/
export const codeiumOtherDocumentsConfig = Facet.define<
CodeiumOtherDocumentsConfig,
Required<CodeiumOtherDocumentsConfig>
Expand Down
19 changes: 18 additions & 1 deletion src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import {
import { Language } from "./api/proto/exa/codeium_common_pb/codeium_common_pb.js";
import { copilotIgnore } from "./annotations.js";

function isDecorationClicked(view: EditorView) {
/**
* Clicking a completion accepts it. This figures out
* whether a given click event is within the completion's area.
*/
function isDecorationClicked(view: EditorView): boolean {
let inRange = false;
const head = view.state.selection.asSingle().ranges.at(0)?.head;
const stateField = view.state.field(completionDecoration);
Expand All @@ -29,6 +33,15 @@ function isDecorationClicked(view: EditorView) {
return false;
}

/**
* Handles the behavior in which if you have a completion like
*
* foo|bar
*
* (the cursor is at |) and you type an x, it rejects
* the completion because that isn't part of the suggested
* code.
*/
function completionPlugin() {
return EditorView.domEventHandlers({
keydown(event, view) {
Expand All @@ -53,6 +66,10 @@ function completionPlugin() {
});
}

/**
* Changing the editor's focus - blurring it by clicking outside -
* rejects the suggestion
*/
function viewCompletionPlugin() {
return EditorView.updateListener.of((update) => {
if (update.focusChanged) {
Expand Down

0 comments on commit ce70e64

Please sign in to comment.