By Ali Yun-Qin Qi
As front-end developers must have used VsCode this powerful tool, and its powerful plug-in ability is undoubtedly let us deeply in love with it. According to incomplete statistics, the number of VsCode plug-ins in the market is over 30,000, which shows how enthusiastic people are. There are plugins for a variety of functions, from theme songs to code development, such as snippets, Git plug-ins, TSLint, and so on. As a developer, I’m sure I’ve used a variety of code prompt plug-ins, including TabNine, Copilot, and so on. Today let’s do it ourselves and develop an exclusive code prompt plug-in. After all, no matter how good others are, they are also others, and what belongs to oneself is the best.
Pre-development preparation
Environment set up
There are many tutorials about VsCode plug-in development environment construction on the Internet, here is not to repeat, specific can refer to the official documentation here.
About code Tips
The code hint here means that VsCode will pop up a panel showing some of your possible inputs, based on the current input, during code writing. If there is the input you expect, just press Enter or TAB (which can be changed in Settings) to enter the recommended code into the editor. This can greatly improve the efficiency of our development, after all, pressing a key directly line of code, far more efficient than we typed out a character.
If you look at this, you might wonder, with all these recommended options, where did all this code come from? Why do I get recommended for something I don’t want at all? Here, according to my research (I haven’t seen the source code), there are several options available from the following sources:
-
LSP (language service protocol) implementation, is actually VsCode support language. For example, with TypeScript, ts syntactic prompts appear when writing code. For example, if con is entered, const, console, and continue are all keywords in the TS syntax.
-
Various built-in Code snippets. VsCode itself has a lot of built-in code snippets. Code snippets can also help us to type quickly. Most code snippets are more than one line of code, which can help us to omit a lot of input. In addition to the built-in snippets, we can also configure our own snippets as part of defining our own plugins.
-
Object path, export object prompt, such as I have one in another file
APP
Constant and oneTest
, and then in the current file, enterAP
You can see that the first one is the constant defined earlier. Press this buttontab
After that, it not only completes the variable name, but also adds it at the topimport
statements -
Finally, there are the options provided by the various plug-ins, and this is the main part of the development of our own plug-ins today. It can be seen that the various plug-ins bring a lot of hints, but at the same time, it also increases the burden of identifying and thinking, looking for the code we want in page after page of hints, but this time may have all been typed out. Therefore, plug-ins are not a panacea, nor the more the better, just install some commonly used, easy to use plug-ins.
Plug-in development
Snippet configuration
There are two ways to configure snippets:
- Directly configure in VsCode as follows:
-
Call out to the VsCode command panel to find the code snippet configuration
-
Selecting the language to configure, such as typescriptrect, is a common.tsx file. (this is the TSX file type key in vscode)
-
The selection shows the current native default code snippet configuration, such as Python. All we need to do is add our own code snippets to the JSON file.
- Plug-ins to develop snippets of code:
You can also develop a snippet-related plug-in, so that it can be downloaded from anywhere and used by multiple editors, rather than stored locally. Snippet plug-in development is relatively simple in two steps:
- Add a json configuration file to the plug-in scaffolding root directory.
- in
package.json
To add the following configuration. Declare information about the code snippet, including: the corresponding language, that is, the file type, the path of the code snippet. The following shows that the same configuration file is applied simultaneously tots
,tsx
,js
andjsx
File.
"contributes": {
"snippets": [{"language": "typescriptreact"."path": "./snippets.json"
},
{
"language": "typescript"."path": "./snippets.json"
},
{
"language": "javascript"."path": "./snippets.json"
},
{
"language": "javascriptreact"."path": "./snippets.json"}},Copy the code
Some ideas for code snippets
The code snippet is relatively simple, just a few fixed pattern configuration, through the shortcut key directly enter. Here are a few ideas:
- Component development snippets. Because there is so much fixed content every time a new component is developed, it is easy to think of keeping this code in snippets. Here is a reference:
"component": {
"prefix": [
"component"]."body": [
"import * as React from 'react';".""."export interface IProps {"."\t${1}"."}".""."const ${2}: React.FC<IProps> = (props) => {"."\tconst { } = props;".""."\treturn ("."\t\t<div className=\"component-$3\">"."\t\t\t$4"."\t\t</div>"."\t);"."};.""."export default ${2};"."",]."description": "Generate component templates"
},
Copy the code
- Import statement, the import statement itself actually has, but the default is double quotes, every time need autofix also annoying, just a simple definition of a sentence
"import": {
"prefix": "import"."body": [
"import ${1} from '${2}';"]."description": "Import"
}
Copy the code
- I like to customize some code blocks, so I use them often
region
Action, so write it down as a code snippet as well
"region": {
"prefix": "region"."body": [
"// #region ${1}\n ${2}\n// #endregion"]."description": "Custom code block"
},
Copy the code
Tips: As you can see, there are a lot of variables, such as ${1}, etc. Please refer to the official documentation for details. Some common, fixed templates are handy to write down.
Code recommendation plug-in
This is where we get down to business, customizing our own plugins.
Learn about scaffolding
First, after the scaffolding is initialized, we look in the code directory. SRC’s extension.ts is the extension code we want to write. It contains two methods, activate and deactivate, and lots of comments. Each plug-in has its own life cycle, and these two life cycle methods are the corresponding plug-in activation and logout life cycle. Our main recommendation logic is also written in the Activate method.
Use the API
We use the most basic API is registerCompletionItemProvider, located in vscode. Languages under the namespace. As the name suggests, this method is to register a code completion provider. Please refer to the official documentation for details of the API.
Basic code
import * as vscode from 'vscode';
/** Supported language types */
const LANGUAGES = ['typescriptreact'.'typescript'.'javascript'.'javascriptreact'];
export function activate(context: vscode.ExtensionContext) {
/** Triggers a list of recommended characters */
const triggers = [' '];
const completionProvider = vscode.languages.registerCompletionItemProvider(LANGUAGES, {
async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
const completionItem: vscode.CompletionItem = {
label: 'Hello VsCode'};return[completionItem]; }},... triggers); context.subscriptions.push(completionProvider); }Copy the code
Register a completionProvider and return an array of vscode.CompletionItem. The above code F5 Debug can see the effect
Custom logic
The demo above was definitely not what we wanted, and since we were aiming for exclusivity, there had to be something different.
Word completion is supported
As an English residue, slightly longer words have to look up the dictionary, so why not through plug-in to help us achieve this operation? In fact, the idea is also simple, is to find a slightly improved English thesaurus, download to the local, and then according to the current input to check the thesaurus each time to return the best match. Here is the simplest implementation logic
import * as vscode from 'vscode';
/** Supported language types */
const LANGUAGES = ['typescriptreact'.'typescript'.'javascript'.'javascriptreact'];
const dictionary = ['hello'.'nihao'.'dajiahao'.'leihaoa'];
export function activate(context: vscode.ExtensionContext) {
/** Triggers a list of recommended characters */
const triggers = [' '];
const completionProvider = vscode.languages.registerCompletionItemProvider(LANGUAGES, {
async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
const range = new vscode.Range(new vscode.Position(position.line, 0), position);
const text = document.getText(range);
const completionItemList: vscode.CompletionItem[] = dictionary.filter(item= > item.startsWith(text)).map((item, idx) = > ({
label: item,
preselect: idx === 0.documentation: 'my exclusive VsCode plugin provides'.sortText: `my_completion_${idx}`,}));returncompletionItemList; }},... triggers); context.subscriptions.push(completionProvider); }Copy the code
Here’s how it looks:
Of course, the code snippet above leaves a lot to be desired, such as:
- Recommended matching logic. Now the string of the current line matches the beginning of the word, which is obviously a problem, adding other characters in the middle will not match, you need to consider segmentation, even discontinuous matching, such as input
lh
, recommend theleihaoa
. Another option is to add no matching logic, throw whatever you input to Vscode, and Vscode matches it. This is fine, but when your thesaurus is large enough, it’s not a good idea to do a simple filter yourself first. - Words have too little information. For now, there is only one word. It would be better to add some explanation and usage
Personalization code recommendation
There’s nothing like personalized code recommendations to suit you better, because no one knows you better. Our general idea is simple and doesn’t involve deep learning or anything like that. It is to record their own input in the process of writing code, process this data, and form a document similar to the dictionary. The method is similar to the word completion above. According to the input, consult the dictionary to obtain the most matching recommendation. And to be personalized, the dictionary must be updated automatically to meet our individual needs. In a nutshell, there are a few things you need to do:
- How do I get the initial documentation?
- How to implement automatic dictionary update logic?
Simple idea:
- Directly take their own code base code for extraction, processing, the formation of the initial dictionary. In theory, the richer the code base, the more accurate the dictionary. Which brings up another problem, namely:
- How do I convert from code –> dictionary? Similarly simple processing, you can directly put the code according to the space for word segmentation, record the corresponding dictionary
- How to determine the order of recommendations? You can simply determine the order of recommendations based on the number of occurrences of the word. The greater the number of occurrences, the higher the order
- You can record the current document content and update the dictionary each time you accept recommendations
Here the code to deal with the formation of the dictionary process and automatic dictionary update code will not put, simple modification of the above code as follows: roughly the code is as follows;
import * as vscode from 'vscode';
/** Register the command */ triggered when selecting recommendations
function registerCommand(command: string) {
vscode.commands.registerTextEditorCommand(
command,
(editor, edit, ... args) = > {
const [text] = args;
// TODO records the current contents to the dictionary and automatically updates the dictionary}); }/** Supported language types */
const LANGUAGES = ['typescriptreact'.'typescript'.'javascript'.'javascriptreact'];
const dictionary = ['hello'.'nihao'.'dajiahao'.'leihaoa'];
/** The command to trigger after the user selects */
const COMMAND_NAME = 'my_code_completion_choose_item';
export function activate(context: vscode.ExtensionContext) {
/** Triggers a list of recommended characters */
const triggers = [' '];
registerCommand(COMMAND_NAME);
const completionProvider = vscode.languages.registerCompletionItemProvider(LANGUAGES, {
async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
const range = new vscode.Range(new vscode.Position(position.line, 0), position);
const text = document.getText(range);
const completionItemList: vscode.CompletionItem[] = dictionary.filter(item= > item.startsWith(text)).map((item, idx) = > ({
label: item,
preselect: idx === 0.documentation: 'my exclusive VsCode plugin provides'.sortText: `my_completion_${idx}`.command: {
arguments: [text],
command: COMMAND_NAME,
title: 'choose item'}}));returncompletionItemList; }},... triggers); context.subscriptions.push(completionProvider); }Copy the code
As you can see, registerCommand is used instead of word completion, and a command parameter is added to each recommendation. The logic is to trigger this command every time the recommendation is selected, and then do the dictionary update. The implementation is for reference only, if you do it better, you can try:
- The auto-update logic needs to be refined and put in the background
- Try sentence recommendations, not just individual words
- The sorting logic can be further optimized according to the number of occurrences that are still too primitive
Write in the last
The above shows the power of VsCode plug-ins to aid development through some simple code completion examples. You can see that it is not difficult to write a plug-in, you are welcome to write their own personalized plug-in. At the same time, also want to provide an idea for everyone, in the development, there are some ideas can be written plug-in way to try, perhaps is to improve the effectiveness of the artifact ~