-
Notifications
You must be signed in to change notification settings - Fork 270
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5ec0d24
Showing
13 changed files
with
17,037 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
vscode.d.ts | ||
vscode.proposed.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/**@type {import('eslint').Linter.Config} */ | ||
// eslint-disable-next-line no-undef | ||
module.exports = { | ||
root: true, | ||
parser: '@typescript-eslint/parser', | ||
plugins: [ | ||
'@typescript-eslint', | ||
], | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
], | ||
rules: { | ||
'semi': [2, "always"], | ||
'@typescript-eslint/no-unused-vars': 0, | ||
'@typescript-eslint/no-explicit-any': 0, | ||
'@typescript-eslint/explicit-module-boundary-types': 0, | ||
'@typescript-eslint/no-non-null-assertion': 0, | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
out | ||
node_modules | ||
.vscode-test/ | ||
*.vsix | ||
|
||
yarn.lock | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// A launch configuration that compiles the extension and then opens it inside a new window | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
{ | ||
"version": "0.2.0", | ||
"configurations": [{ | ||
"name": "Run Extension", | ||
"type": "extensionHost", | ||
"request": "launch", | ||
"runtimeExecutable": "${execPath}", | ||
"args": [ | ||
"--extensionDevelopmentPath=${workspaceFolder}" | ||
], | ||
"outFiles": [ | ||
"${workspaceFolder}/out/**/*.js" | ||
], | ||
"preLaunchTask": "npm: watch" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// See https://go.microsoft.com/fwlink/?LinkId=733558 | ||
// for the documentation about the tasks.json format | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"type": "npm", | ||
"script": "watch", | ||
"problemMatcher": "$tsc-watch", | ||
"isBackground": true, | ||
"presentation": { | ||
"reveal": "never" | ||
}, | ||
"group": { | ||
"kind": "build", | ||
"isDefault": true | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copilot clone | ||
|
||
A clone version of [Github Copilot](https://copilot.github.com/). Instead of using AI, this extension send your search query to google, retrive stackoverflow answers and autocomplete them for you. | ||
|
||
 | ||
|
||
Note: vscode inline-completions feature is still not ready for production (VSCode store won't accept extension like this yet). Check out the original [Microsoft/examples/inline-completions](https://github.com/microsoft/vscode-extension-samples/tree/main/inline-completions) repository | ||
|
||
|
||
## Running the Sample | ||
|
||
- Download this repository to your local machine | ||
- Run `npm install` in terminal to install dependencies. _A `postinstall` script would download latest version of `vscode.proposed.d.ts`_ | ||
- Run the `Run Extension` target in the Debug View. Or from the top menu, choose `Run > Start Debugging`. | ||
|
||
This will: | ||
- Start a task `npm: watch` to compile the code | ||
- Run the extension in a new VS Code window (you should play the code here) | ||
|
||
## Play with Copilot | ||
|
||
To trigger inline completion, you'll need to type `//find {your keyword}.` (start with `//find`, end with a dot `.`) | ||
|
||
For example | ||
```js | ||
//find binary search in javascript. | ||
``` | ||
|
||
Make sure that `showInlineCompletions` is enabled in your settings! | ||
``` | ||
"editor.inlineSuggest.enabled": true | ||
``` | ||
|
||
# Have fun |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ | ||
"enableProposedApi": true, | ||
"name": "inline-completion-sample", | ||
"displayName": "Inline Completion Sample", | ||
"description": "Sample showing how to implement an inline completion provider", | ||
"version": "0.0.1", | ||
"publisher": "vscode-samples", | ||
"repository": "https://github.com/Microsoft/vscode-extension-samples", | ||
"engines": { | ||
"vscode": "^1.34.0" | ||
}, | ||
"categories": [ | ||
"Other" | ||
], | ||
"activationEvents": [ | ||
"*" | ||
], | ||
"main": "./out/extension.js", | ||
"contributes": { | ||
"commands": [ | ||
{ | ||
"command": "extension.inline-completion-settings", | ||
"title": "Inline Completion Settings" | ||
} | ||
], | ||
"menus": { | ||
"editor/inlineCompletions/actions": [ | ||
{ | ||
"command": "extension.inline-completion-settings" | ||
} | ||
] | ||
} | ||
}, | ||
"scripts": { | ||
"vscode:prepublish": "npm run compile", | ||
"compile": "tsc -p ./", | ||
"lint": "eslint . --ext .ts,.tsx", | ||
"watch": "tsc -watch -p ./", | ||
"download-api": "vscode-dts dev", | ||
"postdownload-api": "vscode-dts main", | ||
"postinstall": "npm run download-api" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^12.12.0", | ||
"@types/node-fetch": "^2.5.10", | ||
"@typescript-eslint/eslint-plugin": "^4.16.0", | ||
"@typescript-eslint/parser": "^4.16.0", | ||
"eslint": "^7.21.0", | ||
"typescript": "^4.2.2", | ||
"vscode-dts": "^0.3.1" | ||
}, | ||
"dependencies": { | ||
"@types/jsdom": "^16.2.12", | ||
"jsdom": "^16.6.0", | ||
"node-fetch": "^2.6.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import * as vscode from 'vscode'; | ||
import { search } from './search'; | ||
|
||
const KEYWORD = `//find` | ||
|
||
export function activate(context: vscode.ExtensionContext) { | ||
const disposable = vscode.commands.registerCommand( | ||
'extension.inline-completion-settings', | ||
() => { | ||
vscode.window.showInformationMessage('Show settings'); | ||
} | ||
); | ||
|
||
context.subscriptions.push(disposable); | ||
|
||
function longestSuffixPrefixLength(a: string, b: string): number { | ||
for (let i = Math.min(a.length, b.length); i > 0; i--) { | ||
if (a.substr(-i) == b.substr(0, i)) { | ||
return i; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
interface CustomInlineCompletionItem extends vscode.InlineCompletionItem { | ||
trackingId: string; | ||
} | ||
|
||
const provider: vscode.InlineCompletionItemProvider<CustomInlineCompletionItem> = { | ||
provideInlineCompletionItems: async (document, position, context, token) => { | ||
const textBeforeCursor = document.getText( | ||
new vscode.Range(position.with(undefined, 0), position) | ||
); | ||
|
||
if (textBeforeCursor.indexOf(KEYWORD) == 0 && textBeforeCursor[textBeforeCursor.length - 1] === ".") { | ||
|
||
const rs = await search(textBeforeCursor) | ||
|
||
if (rs == null) { | ||
return { items: [] } | ||
} | ||
|
||
const suggestions = rs.results.map(item => item.code) | ||
const items = new Array<CustomInlineCompletionItem>(); | ||
|
||
suggestions.forEach(code => { | ||
const l = longestSuffixPrefixLength(textBeforeCursor, code); | ||
items.push({ | ||
text: `\n` + code, | ||
range: new vscode.Range(position.translate(0, -l), position), | ||
trackingId: 'some-id', | ||
}); | ||
}) | ||
// for (const s of suggestions) { | ||
// const l = longestSuffixPrefixLength(textBeforeCursor, s); | ||
// if (l > 0) { | ||
// items.push({ | ||
// text: s, | ||
// range: new vscode.Range(position.translate(0, -l), position), | ||
// trackingId: 'some-id', | ||
// }); | ||
// } | ||
// } | ||
return { items }; | ||
} | ||
return { items: [] } | ||
}, | ||
}; | ||
|
||
vscode.languages.registerInlineCompletionItemProvider({ pattern: "**" }, provider); | ||
|
||
// Be aware that the API around `getInlineCompletionItemController` will not be finalized as is! | ||
vscode.window.getInlineCompletionItemController(provider).onDidShowCompletionItem(e => { | ||
const id = e.completionItem.trackingId; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import fetch from "node-fetch"; | ||
import { JSDOM } from "jsdom"; | ||
|
||
const GURL = `https://www.google.com/search?q=site%3Astackoverflow.com+`; | ||
|
||
type SnippetResult = { | ||
results: { votes: number, code:string, textContent: string }[], | ||
url: string | ||
} | ||
|
||
// Get search results from google, then return a list of stackoverflow links | ||
function getGoogleResults(keyword: string): Promise<string[] | null> { | ||
return new Promise((resolve, reject) => { | ||
return fetch(`${GURL}${keyword.replace(/\s/, '+')}`) | ||
.then(rs => rs.text()) | ||
.then(rs => resolve( | ||
rs.match(/(https:\/\/stackoverflow.com\/[a-z0-9-/]+)/g)) | ||
) | ||
.catch(reject) | ||
}) | ||
|
||
} | ||
|
||
async function getStackoverflowContent(url: string): Promise<{ content: string, url: string }> { | ||
return new Promise((resolve, reject) => { | ||
return fetch(url) | ||
.then(rs => rs.text()) | ||
.then(rs => resolve({ content: rs, url })) | ||
.catch(reject) | ||
}) | ||
} | ||
|
||
// Extract and sort stackoverflow answers | ||
function getSnippetResults(options: { content: string, url: string }): SnippetResult { | ||
var doc = new JSDOM(options.content) | ||
|
||
let els = Array.from(doc.window.document.querySelectorAll(".answer")) | ||
.filter((item: any) => item.querySelector("code") != null) | ||
|
||
let results = els.map((item: any) => ({ | ||
textContent: item.textContent, | ||
votes: parseInt(item.querySelector(".js-vote-count").textContent), | ||
code: item.querySelector("code").textContent | ||
})) | ||
|
||
// Sort results by code length | ||
results.sort((a,b) => b.code.length - a.code.length) | ||
|
||
return { url: options.url, results } | ||
} | ||
|
||
// Send search query to google, get answers from stackoverflow | ||
// then extract and return code results | ||
export async function search(keyword: string) { | ||
const urls = await getGoogleResults(keyword) | ||
|
||
if (urls === null) { | ||
return null | ||
} | ||
|
||
// Iterate through all urls if you want | ||
// I also use the first results to avoid having too many requests | ||
const snippets = await getStackoverflowContent(urls[0]); | ||
return getSnippetResults(snippets) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"target": "es2019", | ||
"lib": ["ES2019"], | ||
"outDir": "out", | ||
"sourceMap": true, | ||
"strict": true, | ||
"rootDir": "src", | ||
"skipDefaultLibCheck": true, | ||
"skipLibCheck": true | ||
}, | ||
"exclude": ["node_modules", ".vscode-test"] | ||
} |
Oops, something went wrong.