I believe you also have such feelings, in the work, sometimes will be some simple and repeated operations affect the efficiency, this plug-in checked a lot of information, but also through some pits, now finally completed a first version, the code posted for everyone’s reference. PS: All English documents are a bit unfriendly to me
Introduction to the main process of VScode plug-in development (please slide down)
In order to facilitate VSCode plug-in development, Microsoft has launched a VSCode scaffolding, through this scaffolding can be quickly developed, you can install the following command:
npm install -g yo generator-code
After the installation is complete, there will be a prompt to select the language. In my case, I chose JS and there will be no mapping here.
The extension. Js file:
Extension.js is an entry file. In this file, we can see that there are two methods: activate and deactivate: This method is called when the plug-in is activated (activationEvents in package.json define the conditions under which the plug-in is activated), and we can register the package.json method in this method
function activate(context){ let disposable = vscode.commands.registerCommand('start-plug.helloWorld', () => {// fill in the code to be executed when the command is executed (it is recommended to encapsulate a separate JS file)}); }Copy the code
Deactivate: This method is called when the extension is disabled, optionally adding some friendly hints
function deactivate(){ }
Copy the code
Package. Json file:
Package. json configures the plug-in. The main fields are as follows: activationEvents: Defines the events, or conditions, that the plug-in activates. It could be
- onLanguag
- onCommand
- onDebug
- onDebugInitialConfigurations
- onDebugResolve
- workspaceContains
- onFileSystem
- onView
- onUri
- .
Refer to the Activation Events declaration documentation for details
"activationEvents": [
"onStartupFinished"
]
Copy the code
Main: Used to define the path to the entry file
Contributes: Contributes can be regarded as a statement such as Keys that contributes, as shown in this statement in the documentation: “When a command is invoked (from a key binding, from a command panel, any other menu, or programmatically), VS Code will issue activationEvent onCommand:${command}”; In other words, upon receiving commands(commands) issued by the client, the activationEvent will look for the behavior of commands in accordance with the user input command, and execute it after finding it, which is displayed in the command panel (Ctrl+Shift+P) by default.
Menus: used to define when the mouse selects a file, the menu options displayed, and the menu command, represents the menu bar, the command to execute the command, the menu bar title, corresponding to the command in the menu in commands title
- breakpoints
- colors
- commands
- customEditors
- debuggers
- keybindings
- languages
- menus
- .
For a detailed list, see the Contributes Declaration document
The body of the
The project I am taking over is a bit special. In the production environment, it is necessary to comment out the code calling a method, otherwise it will lead to errors in JS files. In the pre-release environment, it is necessary to restore the previously commented out method and make it take effect again. As a result, during each iteration, we need to search for this method in JS file and comment it one by one, and then uncomment it one by one during pre-release, which is very troublesome. As a code farmer, how willing to accept this low-level and repeated operation! Therefore, I wondered if I could develop a vsCode plug-in to help me traverse, find and replace. At the same time, since it is a plug-in, it must not be developed only for the project I took over. In order to be compatible with more situations in the future, text box input can be used to determine the code to be annotated out. Roll up your sleeves and do it!
Directories created in scaffolding using javascript:
First take a look at the entry file extension.js
The FileHanding is a file created by myself. It is recommended that the handling methods of the file be individually wrapped into one or several JS.
// The module 'VS Code' contains The VS Code extensibility API module 'VS Code' contains The VS Code extension API // Import The module and reference It with the alias vscode in your code below imports the module and references it with the alias vscode in the code below const vscode = require('vscode'); Const FileHanding = require('./ FileHanding ') // FileHanding belongs to a custom JS method /** * @param {vscode.extensionContext} context */ function activate(context) { console.log('context',context); //TODO : // This line of code will only execute console.log once your extension is activated ('Congratulations, your extension "start-plug" is now active! '); Vscode. Window. ShowInformationMessage (' plugin has been activated); // This command already defines json files in packages // events defined in package you need to register here // parameters must match the command field in package.json let codeClear = vscode.commands.registerCommand('custom-code.clear', (params) = > {/ / call vscode input box API vscode. Window. ShowInputBox ({password: false, placeHolder: }). Then (MSG => {MSG => {MSG => {MSG => { If (MSG) {const fileOptions = {encoding: 'utf-8'}; FileHanding. HandleMain (params. FsPath fileOptions, ` ${MSG} `). Then (res = > {vscode. Window. ShowInformationMessage (' file has been updated, '); },err => { vscode.window.showErrorMessage(err) }) } }) }); context.subscriptions.push(disposable, codeClear); } // This method is called when your extension is disabled. Function deactivate() {} module.exports = {activate, deactivate}Copy the code
This is the fileHanding. Js file used to handle the contents of the file: in this file I’ve added node’s FS module to read and write the file.
//TODO: I want to create a log-like TXT file, which is used to save the record of each change, but facing the MAC and Windows directory difference, how to determine the location? //TODO: Do I need to add type filtering? const FileSystem = require('fs'); Function isFolder(path) {return filesystem.lStatsync (path).isdirectory (); } function handleMain(path, options, MSG){return new Promise((resolve,reject) => {if (isFolder(path)) { Const filePathList = filesystem.readdirsync (path); Console. log(' file list ',filePathList,path); if (filePathList.length) { for (let index = 0; index < filePathList.length; index++) { const childPath = `${path}/${filePathList[index]}`; HandleMain (childPath,options, MSG)}}else{reject(' reject ')}}else{const result = readFile(path, options, MSG) msg) result.state ? resolve() : reject(result.errCode); } }) } function readFile(path, options, msg) { if (! path || ! MSG) {return {state: false, errCode: 'current status is abnormal'}} if (! FileSystem. ExistsSync (path)) {// Check whether the file exists return {state: false, errCode: }} try {const fileData = FileSystem. ReadFileSync (path, options); const fileCodeList = fileData.toString().split('\n'); // Split clearHandleFile(path, fileCodeList, options, MSG) by action unit after converting Buffer to string; Return {state: true}} Catch (error) {return {state: false, errCode: ${error} '}}} function clearHandleFile(path, fileStringList, options, MSG) {const handleCodeList = []; let isUpdate = false; for (let index = 0; index < fileStringList.length; index++) { const element = fileStringList[index]; If (isAccordCondition(element.replace(/(^\s*)/g, ""), MSG)) {// Const insertIndex = element.search(MSG); const handleString = `${element.slice(0,insertIndex)}// ${element.slice(insertIndex)}`; handleCodeList.push(handleString); isUpdate = true; } else {handlecodelist.push (element)}} if (isUpdate) { Const handleFileStr = handlecodelist.join ('\n'); FileSystem.writeFileSync(path, handleFileStr, options); } } function isAccordCondition(str, msg) { //TODO: If (/^\/ /.test(STR)) {return false} let exp = RegExp(' ^${MSG} '); Return exp. Test (STR); } module.exports = { readFile, handleMain }Copy the code
Json file is contributed, where I use the activation condition onStartupFinished
// The activation condition I used here is onStartupFinished. This activation event will be emitted some time after VS Code launches and the extension of interest will be activated. This is similar to the * activation event, but does not slow down VS Code's startup. Currently, this event is emitted after all * active extensions have been activated. {"name": "start-plug", "displayName": "yln-plug", "description": "private plug", "version": "0.0.1", "engines": {"vscode": "^1.60.0"}, "Categories ": ["Other"], "activationEvents": ["onStartupFinished"], "main": "./extension.js", "contributes": { "commands": [ { "command": "custom-code.clear", "title": "code-clear" } ], "menus": { "explorer/context": [ { "command": "custom-code.clear", "when": "filesExplorerFocus", "group": "navigation@1" } ] } }, "scripts": { "lint": "eslint .", "pretest": "npm run lint", "test": "Node. / test/runTest. Js"}, "devDependencies" : {" @ types/vscode ":" ^ 1.60.0 ", "@ types/glob" : "^ 7.1.4", "@ types/mocha" : "^ 9.0.0 @ types/"," node ": 14." x ", "eslint" : "^ 7.32.0", "the glob" : "^ 7.1.7", "mocha" : "^ 9.1.1", "typescript" : "^4.4.3", "@vscode/test-electron": "^1.6.2"}}Copy the code
Final implementation result
Press F5 to start the plug-in for debugging, and then use Command + Shift +P on MAC to bring up the command line and input the configured command. Since I configured menu in package.json, I can directly right-click the file
Enter a string in the pop-up box
The plugin can be used to clean console.log before a project goes live, or to perform batch operations based on business needs. Of course, there are still many defects in this plugin, such as:
- Comment matching in /* */ format is not currently supported
- You can only match the beginning of each line of code with the action unit
- There is no one-click restoration of commented code
- I’ve been meaning to make a change log and haven’t done anything yet…
- .
How can I say, this is only the first version, if the business needs or interest, I will also find a time to continue to expand and improve its function, because we have finished the most difficult step ↓
The best time to plant a tree was ten years ago, followed by now.
In addition, in the process of plug-in development, I learned from The ideas of The God of Cold grass, plus some of my own small ideas, which promoted the birth of this plug-in and this blog post, which is also a relatively innovative attempt of my own. The moment the plugin was developed and tested, I took a deep breath and, lo and behold, the sense of accomplishment was in the air. Special thanks: Han Grass: “teach you to use ten minutes to develop a vscode plug-in to improve work experience 🌿” console, debugger one-click delete | custom code template