zoukankan      html  css  js  c++  java
  • vscode自定义插件开发

    1.vscode插件开发有什么用

    每个公司、项目组、各人都有自己特殊的定制化、可公用的需求,vscode的已有插件显然不能满足我们各种各样的要求,所以开发一个适用于我们自己的定制化插件,无疑能大大提高我们的开发效率以及团队的语法规范

    2.vscode插件开发、发布主要流程

    1. 插件开发前的准备:vscode、nodejs、vscode插件生产工具、git、微软账号
    2. 插件开发:插件构思、官方文档查阅
    3. 插件发布:打包、上传、插件市场操作
    4. 插件维护:更新迭代后打包、上传、插件市场操作

    3.插件开发前的准备:

    vscode、nodejs、git、微软账号
    vscode插件生产工具:官方推荐使用Yeoman 和 VS Code Extension Generator。用如下命令安装:

    npm install -g yo generator-code
    

    3.1使用生产工具初始化代码

    yo code
    
    • 目录如下
    ├── .vscode      // 资源配置文件
    ├── CHANGELOG.md // 更改记录文件,会展示到vscode插件市场
    ├── extension.js // 拓展源代码文件
    ├── jsconfig.json
    ├── package.json // 资源配置文件
    ├── README.md    // 插件介绍文件,会展示到vscode插件市场
    ├── test         // 测试文件
    └── vsc-extension-quickstart.md
    

    在js拓展项目下,最重要的就是extension.js和package.json。

    4.开发的插件功能

    1. 初始化react的组件模块
    2. 初始化项目里面能共用的模块

    4.1项目结构以及代码

    extention.js 代码
    'use strict';
    const vscode = require('vscode');
    const paramCase = require('change-case').paramCase;
    const utils = require('./utils');
    const { logger, generators } = utils;
    
    function activate(context) {
      let createComponent = (uri, type) => {
        console.log('Create-react-component activated...');
    
        new Promise(resolve =>
          vscode.window
            .showInputBox({
              prompt: 'Enter component name'
            })
            .then(inputValue => resolve(inputValue))
        )
          .then(val => {
            if (val.length === 0) {
              logger('error', 'Component name can not be empty!');
              throw new Error('Component name can not be empty!');
            }
    
            let componentName = paramCase(val);
            // if 是初始化页面写入的路径 else 初始化页面整体模板
            let componentDir = type === 'initReactComponent' ? generators.createComponentDir(uri, componentName, true)
              : generators.createComponentDir(uri, componentName);
            // if 是初始化页面写入的路径 else 初始化页面整体模板
            if (type === 'initReactComponent') {
              return Promise.all([
                generators.createComponent(componentDir, componentName, type),
                generators.createTestFile(componentDir, componentName, type),
                generators.createCSS(componentDir, componentName, type),
              ]);
            }
            return Promise.all([
              generators.createComponent(componentDir, componentName, type),
              generators.createTestFile(componentDir, componentName),
              generators.createCSS(componentDir, componentName),
              generators.createModelFile(componentDir, componentName),
              generators.createServiceFile(componentDir, componentName)
            ]);
          })
          .then(
            () => logger('success', 'React component successfully created!'),
            err => logger('error', err.message)
          );
      };
      // 注册命令
      const componentsList = [
        {
          type: 'class',
          commandID: 'extension.createReactClassComponent'
        },
        {
          type: 'initReactComponent',
          commandID: 'extension.initReactComponent'
        }
      ];
    
      componentsList.forEach(comp => {
        let type = comp.type;
        let disposable = vscode.commands.registerCommand(comp.commandID, uri => {
          createComponent(uri, type);
        });
        context.subscriptions.push(disposable);
      });
    }
    
    /**
     * 插件被激活时触发,所有代码总入口
     * @param {*} context 插件上下文
     */
    module.exports = {
      activate
    };
    
    
    utils.js 代码(做写入文件的操作)
    'use strict';
    const vscode = require('vscode');
    const fse = require('fs-extra');
    const fs = require('fs');
    const path = require('path');
    const pascalCase = require('change-case').pascalCase;
    const camelCase = require('change-case').camelCase;
    
    function logger(type, msg = '') {
      switch (type) {
        case 'success':
          return vscode.window.setStatusBarMessage(`Success: ${msg}`, 5000);
        case 'warning':
          return vscode.window.showWarningMessage(`Warning: ${msg}`);
        case 'error':
          return vscode.window.showErrorMessage(`Failed: ${msg}`);
      }
    }
    
    module.exports = {
      logger,
      generators: {
        templatesDir: path.join(__dirname, '/templates'),
    
        createFile: (file, data) =>
          new Promise(resolve => {
            let output = fse.outputFile(file, data);
            resolve(output);
          }),
    
        resolveWorkspaceRoot: path =>
          path.replace('${workspaceFolder}', vscode.workspace.rootPath),
        // 返回需要返回的路径
        createComponentDir: function (uri, componentName, isInit) {
          let contextMenuSourcePath;
    
          if (uri && fs.lstatSync(uri.fsPath).isDirectory()) {
            contextMenuSourcePath = uri.fsPath;
          } else if (uri) {
            contextMenuSourcePath = path.dirname(uri.fsPath);
          } else {
            contextMenuSourcePath = vscode.workspace.rootPath;
          }
          // if 是初始化页面写入的路径 else 初始化页面整体模板
          let componentDir = isInit ? `${contextMenuSourcePath}/${pascalCase(
            componentName
          )}` : `${contextMenuSourcePath}`;
          fse.mkdirsSync(componentDir);
    
          return componentDir;
        },
        // 创建组件
        createComponent: function (componentDir, componentName, type) {
          // 读取我们自定义的模板
          let templateFileName = this.templatesDir + `/${type}.template`;
          // 处理驼峰大小写的名称
          const compName = pascalCase(componentName);
          const cName = camelCase(componentName);
          console.log(componentDir, 23123);
          let componentContent = fs
            .readFileSync(templateFileName)
            .toString()
            .replace(/{componentName}/g, compName).replace(/{cName}/g, cName);
          // if 是初始化页面写入的路径 else 初始化页面整体模板
          let filename = type === 'class' ? `${componentDir}/components/${compName}/${compName}.js` : `${componentDir}/${compName}.js`;
    
          return this.createFile(filename, componentContent);
        },
        // 创建index.js
        createTestFile: function (componentDir, componentName, type) {
          let templateFileName = this.templatesDir + `/test.template`;
    
          const compName = pascalCase(componentName);
    
          let componentContent = fs
            .readFileSync(templateFileName)
            .toString()
            .replace(/{componentName}/g, compName);
    
          let filename = type ? `${componentDir}/index.js` : `${componentDir}/components/${compName}/index.js`;
    
          return this.createFile(filename, componentContent);
        },
        // 创建models文件
        createModelFile: function (componentDir, componentName) {
          let templateFileName = this.templatesDir + `/models.template`;
    
          const compName = camelCase(componentName);
    
          let componentContent = fs
            .readFileSync(templateFileName)
            .toString()
            .replace(/{componentName}/g, compName);
    
          let filename = `${componentDir}/models/${compName}.js`;
    
          return this.createFile(filename, componentContent);
        },
        // 创建services文件
        createServiceFile: function (componentDir, componentName) {
          let templateFileName = this.templatesDir + `/services.template`;
    
          const compName = camelCase(componentName);
    
          let componentContent = fs
            .readFileSync(templateFileName)
            .toString()
            .replace(/{componentName}/g, compName);
    
          let filename = `${componentDir}/services/${compName}.js`;
    
          return this.createFile(filename, componentContent);
        },
        // 创建less文件
        createCSS: function (componentDir, componentName, type) {
          let templateFileName = `${this.templatesDir}/sass.template`;
    
          const compName = camelCase(componentName);
          let cssContent = fs
            .readFileSync(templateFileName)
            .toString()
            .replace(/{componentName}/g, compName);
    
          let filename = type ? `${componentDir}/less/${compName}.less` : `${componentDir}/components/${compName}/less/${compName}.less`;
    
          return this.createFile(filename, cssContent);
        }
      }
    };
    
    

    4.2运行调试

    • 操作效果

    • 实现效果

    发布

    官方插件发布流程:https://code.visualstudio.com...

    网上详细的发布流程 https://www.cnblogs.com/...

    项目地址:https://github.com/huanglovesong...

  • 相关阅读:
    VS2017gets的使用
    UITableViewCell自定义高度
    登录注册页面的
    监听键盘- KeyBoard
    UITableViewDelete 删除
    UITabView 添加
    navigationbar背景图 设置左右按钮
    Navigation1 PUSH & POP
    母传键老师课堂笔记 -----ViewController的生命周期
    可折叠tableView
  • 原文地址:https://www.cnblogs.com/Hsong/p/12176610.html
Copyright © 2011-2022 走看看