mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Add two variations to inline-completions sample
Co-authored-by: pierceboggan <1091304+pierceboggan@users.noreply.github.com>
This commit is contained in:
@ -1,10 +1,52 @@
|
||||
# Inline Completions Sample
|
||||
|
||||
This sample demonstrates usage of the inline completions API.
|
||||
It also demonstrates some proposed API of the inline completions feature that is not yet finalized.
|
||||
This sample demonstrates usage of the inline completions API with **two different variations**:
|
||||
|
||||
1. **Pattern-Based Provider** - Advanced features including proposed APIs
|
||||
2. **Simple Context-Aware Provider** - Basic inline completions for common code patterns
|
||||
|
||||

|
||||
|
||||
## Two Variations
|
||||
|
||||
### Variation 1: Pattern-Based Provider (Default)
|
||||
|
||||
This provider demonstrates advanced inline completion features:
|
||||
- Custom syntax for triggering completions via special comments
|
||||
- Support for snippets with the `s` flag
|
||||
- Bracket pair completion with the `b` flag
|
||||
- Proposed API features (`handleDidShowCompletionItem`, `handleDidPartiallyAcceptCompletionItem`)
|
||||
- Commands attached to completion items
|
||||
|
||||
**Usage**: Add special comment lines in your code like:
|
||||
```javascript
|
||||
// [0,*):console.log("Hello")
|
||||
// Type here and the completion will appear
|
||||
```
|
||||
|
||||
The syntax is: `// [start,end)flags:completion_text`
|
||||
- `start`: Starting column position (0-based)
|
||||
- `end`: Ending column position, or `*` for end of line
|
||||
- `flags`: Optional flags (`s` for snippet, `b` for bracket pairs)
|
||||
- `completion_text`: The text to insert
|
||||
|
||||
### Variation 2: Simple Context-Aware Provider
|
||||
|
||||
This provider demonstrates basic inline completion features:
|
||||
- Context-aware completions based on what you're typing
|
||||
- Simple pattern matching for common code constructs
|
||||
- No proposed API usage (more stable, production-ready)
|
||||
|
||||
**Examples**:
|
||||
- Type `console.` → suggests `log()`
|
||||
- Type `function ` → suggests `myFunction() { }`
|
||||
- Type `if ` → suggests `(condition) { }`
|
||||
- Type `for ` → suggests `(let i = 0; i < length; i++) { }`
|
||||
|
||||
### Switching Between Variations
|
||||
|
||||
You can switch between the two providers by running the command:
|
||||
**"Inline Completion: Switch Provider (Pattern-Based ↔ Simple)"** from the Command Palette (Ctrl+Shift+P / Cmd+Shift+P).
|
||||
|
||||
## Running the Sample
|
||||
|
||||
@ -13,3 +55,7 @@ It also demonstrates some proposed API of the inline completions feature that is
|
||||
- Run the `Run Extension` target in the Debug View. This will:
|
||||
- Start a task `npm: watch` to compile the code
|
||||
- Run the extension in a new VS Code window
|
||||
- Try both variations:
|
||||
- **Pattern-Based**: Use the playground.js file with special comment syntax
|
||||
- **Simple**: Type common code patterns like `console.`, `if `, `for `, etc.
|
||||
- Use the Command Palette to switch between providers and see the differences
|
||||
|
||||
@ -13,6 +13,7 @@ export default tseslint.config(
|
||||
ignores: [
|
||||
'out',
|
||||
'playground.js',
|
||||
'playground-simple.js',
|
||||
'**/vscode*.d.ts'
|
||||
]
|
||||
},
|
||||
|
||||
@ -23,6 +23,10 @@
|
||||
{
|
||||
"command": "extension.inline-completion-settings",
|
||||
"title": "My Inline Completion Demo Settings"
|
||||
},
|
||||
{
|
||||
"command": "extension.switch-inline-completion-provider",
|
||||
"title": "Inline Completion: Switch Provider (Pattern-Based ↔ Simple)"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
|
||||
19
inline-completions/playground-simple.js
Normal file
19
inline-completions/playground-simple.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Simple Provider Playground
|
||||
// This file demonstrates the Simple Context-Aware Provider
|
||||
// Switch to the Simple Provider using Command Palette: "Inline Completion: Switch Provider"
|
||||
|
||||
// Try typing the following patterns to see inline completions:
|
||||
|
||||
// 1. Console logging
|
||||
console.
|
||||
|
||||
// 2. Function declaration
|
||||
function
|
||||
|
||||
// 3. If statement
|
||||
if
|
||||
|
||||
// 4. For loop
|
||||
for
|
||||
|
||||
// The simple provider will suggest completions as you type these common patterns!
|
||||
@ -1,3 +1,5 @@
|
||||
// Pattern-Based Provider Playground
|
||||
// This file demonstrates the Pattern-Based Provider (default)
|
||||
// Trigger inline completions after each line
|
||||
|
||||
// [0,*):// Trigger inline completions in this line, they work!
|
||||
|
||||
@ -1,81 +1,169 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Range } from 'vscode';
|
||||
|
||||
/**
|
||||
* VARIATION 1: Pattern-Based Inline Completion Provider
|
||||
* This provider demonstrates advanced features including:
|
||||
* - Custom syntax for triggering completions via comments
|
||||
* - Snippet support
|
||||
* - Bracket pair completion
|
||||
* - Proposed API features (handleDidShowCompletionItem, handleDidPartiallyAcceptCompletionItem)
|
||||
* - Commands attached to completions
|
||||
*/
|
||||
const patternBasedProvider: vscode.InlineCompletionItemProvider = {
|
||||
async provideInlineCompletionItems(document, position, _context, _token) {
|
||||
console.log('[Pattern Provider] provideInlineCompletionItems triggered');
|
||||
const regexp = /\/\/ \[(.+?),(.+?)\)(.*?):(.*)/;
|
||||
if (position.line <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result: vscode.InlineCompletionList = {
|
||||
items: [],
|
||||
commands: [],
|
||||
};
|
||||
|
||||
let offset = 1;
|
||||
while (offset > 0) {
|
||||
if (position.line - offset < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
const lineBefore = document.lineAt(position.line - offset).text;
|
||||
const matches = lineBefore.match(regexp);
|
||||
if (!matches) {
|
||||
break;
|
||||
}
|
||||
offset++;
|
||||
|
||||
const start = matches[1];
|
||||
const startInt = parseInt(start, 10);
|
||||
const end = matches[2];
|
||||
const endInt =
|
||||
end === '*'
|
||||
? document.lineAt(position.line).text.length
|
||||
: parseInt(end, 10);
|
||||
const flags = matches[3];
|
||||
const completeBracketPairs = flags.includes('b');
|
||||
const isSnippet = flags.includes('s');
|
||||
const text = matches[4].replace(/\\n/g, '\n');
|
||||
|
||||
result.items.push({
|
||||
insertText: isSnippet ? new vscode.SnippetString(text) : text,
|
||||
range: new Range(position.line, startInt, position.line, endInt),
|
||||
completeBracketPairs,
|
||||
});
|
||||
}
|
||||
|
||||
if (result.items.length > 0) {
|
||||
result.commands!.push({
|
||||
command: 'demo-ext.command1',
|
||||
title: 'My Inline Completion Demo Command',
|
||||
arguments: [1, 2],
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
handleDidShowCompletionItem(_completionItem: vscode.InlineCompletionItem): void {
|
||||
console.log('[Pattern Provider] handleDidShowCompletionItem');
|
||||
},
|
||||
|
||||
/**
|
||||
* Is called when an inline completion item was accepted partially.
|
||||
* @param acceptedLength The length of the substring of the inline completion that was accepted already.
|
||||
*/
|
||||
handleDidPartiallyAcceptCompletionItem(
|
||||
_completionItem: vscode.InlineCompletionItem,
|
||||
_info: vscode.PartialAcceptInfo | number
|
||||
): void {
|
||||
console.log('[Pattern Provider] handleDidPartiallyAcceptCompletionItem');
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* VARIATION 2: Simple Context-Aware Inline Completion Provider
|
||||
* This provider demonstrates basic inline completion features:
|
||||
* - Context-aware completions based on current line content
|
||||
* - Simple pattern matching for common code constructs
|
||||
* - No proposed API usage (more stable, production-ready)
|
||||
*/
|
||||
const simpleProvider: vscode.InlineCompletionItemProvider = {
|
||||
async provideInlineCompletionItems(document, position, _context, _token) {
|
||||
console.log('[Simple Provider] provideInlineCompletionItems triggered');
|
||||
|
||||
const linePrefix = document.lineAt(position).text.substring(0, position.character);
|
||||
const items: vscode.InlineCompletionItem[] = [];
|
||||
|
||||
// Example 1: Complete console.log statements
|
||||
if (linePrefix.trim() === 'console.') {
|
||||
items.push({
|
||||
insertText: 'log()',
|
||||
range: new Range(position, position)
|
||||
});
|
||||
}
|
||||
|
||||
// Example 2: Complete function declarations
|
||||
if (linePrefix.trim() === 'function ') {
|
||||
items.push({
|
||||
insertText: 'myFunction() {\n\t\n}',
|
||||
range: new Range(position, position)
|
||||
});
|
||||
}
|
||||
|
||||
// Example 3: Complete if statements
|
||||
if (linePrefix.trim() === 'if ') {
|
||||
items.push({
|
||||
insertText: '(condition) {\n\t\n}',
|
||||
range: new Range(position, position)
|
||||
});
|
||||
}
|
||||
|
||||
// Example 4: Complete for loops
|
||||
if (linePrefix.trim() === 'for ') {
|
||||
items.push({
|
||||
insertText: '(let i = 0; i < length; i++) {\n\t\n}',
|
||||
range: new Range(position, position)
|
||||
});
|
||||
}
|
||||
|
||||
return items.length > 0 ? { items } : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export function activate(_context: vscode.ExtensionContext) {
|
||||
console.log('inline-completions demo started');
|
||||
console.log('inline-completions demo started with TWO variations');
|
||||
|
||||
// Register command used by the pattern-based provider
|
||||
vscode.commands.registerCommand('demo-ext.command1', async (...args) => {
|
||||
vscode.window.showInformationMessage('command1: ' + JSON.stringify(args));
|
||||
});
|
||||
|
||||
const provider: vscode.InlineCompletionItemProvider = {
|
||||
async provideInlineCompletionItems(document, position, _context, _token) {
|
||||
console.log('provideInlineCompletionItems triggered');
|
||||
const regexp = /\/\/ \[(.+?),(.+?)\)(.*?):(.*)/;
|
||||
if (position.line <= 0) {
|
||||
return;
|
||||
// Register command to switch between providers
|
||||
let currentProvider: 'pattern' | 'simple' = 'pattern';
|
||||
let providerDisposable: vscode.Disposable;
|
||||
|
||||
const switchProvider = () => {
|
||||
if (currentProvider === 'pattern') {
|
||||
currentProvider = 'simple';
|
||||
if (providerDisposable) {
|
||||
providerDisposable.dispose();
|
||||
}
|
||||
|
||||
const result: vscode.InlineCompletionList = {
|
||||
items: [],
|
||||
commands: [],
|
||||
};
|
||||
|
||||
let offset = 1;
|
||||
while (offset > 0) {
|
||||
if (position.line - offset < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
const lineBefore = document.lineAt(position.line - offset).text;
|
||||
const matches = lineBefore.match(regexp);
|
||||
if (!matches) {
|
||||
break;
|
||||
}
|
||||
offset++;
|
||||
|
||||
const start = matches[1];
|
||||
const startInt = parseInt(start, 10);
|
||||
const end = matches[2];
|
||||
const endInt =
|
||||
end === '*'
|
||||
? document.lineAt(position.line).text.length
|
||||
: parseInt(end, 10);
|
||||
const flags = matches[3];
|
||||
const completeBracketPairs = flags.includes('b');
|
||||
const isSnippet = flags.includes('s');
|
||||
const text = matches[4].replace(/\\n/g, '\n');
|
||||
|
||||
result.items.push({
|
||||
insertText: isSnippet ? new vscode.SnippetString(text) : text,
|
||||
range: new Range(position.line, startInt, position.line, endInt),
|
||||
completeBracketPairs,
|
||||
});
|
||||
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, simpleProvider);
|
||||
vscode.window.showInformationMessage('Switched to Simple Provider');
|
||||
} else {
|
||||
currentProvider = 'pattern';
|
||||
if (providerDisposable) {
|
||||
providerDisposable.dispose();
|
||||
}
|
||||
|
||||
if (result.items.length > 0) {
|
||||
result.commands!.push({
|
||||
command: 'demo-ext.command1',
|
||||
title: 'My Inline Completion Demo Command',
|
||||
arguments: [1, 2],
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
handleDidShowCompletionItem(_completionItem: vscode.InlineCompletionItem): void {
|
||||
console.log('handleDidShowCompletionItem');
|
||||
},
|
||||
|
||||
/**
|
||||
* Is called when an inline completion item was accepted partially.
|
||||
* @param acceptedLength The length of the substring of the inline completion that was accepted already.
|
||||
*/
|
||||
handleDidPartiallyAcceptCompletionItem(
|
||||
_completionItem: vscode.InlineCompletionItem,
|
||||
_info: vscode.PartialAcceptInfo | number
|
||||
): void {
|
||||
console.log('handleDidPartiallyAcceptCompletionItem');
|
||||
},
|
||||
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, patternBasedProvider);
|
||||
vscode.window.showInformationMessage('Switched to Pattern-Based Provider');
|
||||
}
|
||||
};
|
||||
vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, provider);
|
||||
|
||||
vscode.commands.registerCommand('extension.switch-inline-completion-provider', switchProvider);
|
||||
|
||||
// Register the pattern-based provider by default
|
||||
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, patternBasedProvider);
|
||||
_context.subscriptions.push(providerDisposable);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user