Develop vscode plug-in variable translation from zero to one

The reason for the demand is that English learners often encountered a variable in the development process and knew what the Chinese name was, but they might forget the English word, or did not know it. At this time, I used to open the browser, open Google translate, input Chinese, copy English, and then cut back to vscode and paste the result. It’s really too much trouble. When I was young, I had a good memory and could remember most Of the English words. But as I get older and older, my hair is getting less and less, my memory is getting worse and worse, and the steps above are repeated more and more. Because oneself is also these days from scratch to learn plug-in development, so this article completely recorded a small white development of plug-in development road, the content is mainly the actual combat class introduction, mainly from four aspects to show the complete process of the whole plug-in from functional design to release.

  1. Functional design
  2. Environment set up
  3. Plug-in function development
  4. Plug-in package distribution

Translate Variable = Translate Variable = Translate Variable = Translate Variable = Translate Variable = Translate Variable

Functional design

The function is mainly two functions, translation from Chinese to English and translation from other languages to Chinese

  1. To replace the Chinese variable with the translated English variable, multiple words need to be automatically humped, which solves the scenario of “English jam” frequently encountered in daily development.
  2. Delimit word translation, automatically translate a variety of languages into Chinese, which solves the scene is sometimes look at foreign project source code annotations encounter not know what the meaning of the word affect efficiency

Environment set up

The first step is to build the environment

  1. Scaffolding, Yo, and Generator-Code are two tools that can help you quickly build projects. See Github for details

    / / installation
    yarn global add yo generator-code
    Copy the code
  2. Install VSCE, which can be used to package your developed code into a.vsix file that can be uploaded to the Microsoft Plug-in Store or installed locally

    yarn global add vsce
    Copy the code
  3. Generate and initialize the project. Fill in the initialization information according to your own situation

    // Initialize the project
    yo code
    Copy the code

    When you get to this point, you can just go ahead and Open with code

    After opening, it will automatically create a workspace and generate these files, which can be deleted according to their own needs. After completing this step, we can directly develop and debug

    How to debug?

    Go to Run with the Debug panel by clicking Run Extention, or F5. MAC can directly click the debug button in the touch bar

    This new window is your test environment (extension development host). The plugins you do will be tested in this new window. The printed messages will be in the debug console of the previous window, such as the built-in examples. Typing Hello World after CMD/CTRL + Shift + P in our new window will print some information on the console of the previous window

    At this point, the development readiness environment is in place, and the next step is to begin formal plug-in functionality development

Plug-in function development

In plug-in development, there are two important files, package.json and extension.js

Notes on Important Documents

package.json

  • ActivationEvents is used to register activationEvents that indicate when the active function in extention.js will be activated. OnLanguage,onCommand… See the vscode document activationEvents for more information

  • Main represents the main entry for the plug-in

  • Contributes to register commands, keybindings,** configuration Settings, etc. More configurable items are contributed by the documentation

extention.js

Extention.js is mainly used as the implementation point of plug-in functions. Active and deactive functions, apis provided by vscode and some event hooks are used to complete the development of plug-in functions

Implement translation function

Translation here is mainly used in three services, Google, Baidu Translation, Youdao Translation.

  1. Google Translate uses **@vitalets/ Google-translate-API **. No configuration required, but you need to be able to access the external environment yourself

    const translate = require('@vitalets/google-translate-api');
    async function getGoogleTransResult(text, opt) {
      const { from, to } = opt;
      try {
        const result = await translate(text, { from: from.to: to });
        console.log([Google Translate], result);
        return result.text;
      } catch (error) {
        console.log(error); }}module.exports = getGoogleTransResult
    Copy the code
  2. Apply for the service, obtain the appID and key, and then construct the request URL to request it directly. If you don’t know how to apply, you can check my previous article. Electron+Vue builds a local file translator from scratch to apply

    const md5 = require("md5");
    const axios = require("axios");
    const config = require('.. /config/index.js');
    axios.defaults.withCredentials = true;
    axios.defaults.crossDomain = true;
    axios.defaults.headers.post["Content-Type"] =
        "application/x-www-form-urlencoded";
    
    // Baidu Translation
    async function getBaiduTransResult(text = "", opt = {}) {
        const { from, to, appid, key } = opt;
        try {
            const q = text;
            const salt = parseInt(Math.random() * 1000000000);
            let str = `${appid}${q}${salt}${key}`;
            const sign = md5(str);
            const query = encodeURI(q);
            const params = `q=${query}&from=The ${from}&to=${to}&appid=${appid}&salt=${salt}&sign=${sign}`;
            const url = `${config.baiduBaseUrl}${params}`;
            console.log(url);
            const res = await axios.get(url);
            console.log('Baidu Translation Results', res.data.trans_result[0]);
            return res.data.trans_result[0];
        } catch (error) {
            console.log({ error }); }}module.exports = getBaiduTransResult;
    Copy the code
  3. Youdao Translation needs to apply for an application ID and an application key. A free coupon of 50 yuan is provided for new registrators, but it will be charged after use, which is not cost-effective

    
    const config = require('.. /config/index.js');
    const { createHash } = require('crypto');
    const qs = require('querystring');
    const axios = require("axios");
    
    function hash(string) {
      return createHash('sha256').update(string).digest('hex');
    }
    
    function getInput(text) {
      if(! text) {return;
      }
      let input;
      const strLength = text.length;
      if (strLength <= 20) {
        input = text;
      } else {
        input = `${text.substring(0.10)}${strLength}${text.substring(strLength - 10, strLength)}`;
      }
      return input;
    }
    
    async function getYouDaoTransResult(text, opt = {}) {
      const { from, to, appid, secretKey } = opt;
      const input = getInput(text);
      const salt = (new Date).getTime();
      const curtime = Math.round(new Date().getTime() / 1000);
      const str = `${appid}${input}${salt}${curtime}${secretKey}`;
      const sign = hash(str);
      const params = {
        q: text,
        appKey: appid,
        salt: salt,
        from: from.to: to,
        sign: sign,
        signType: "v3".curtime: curtime,
      }
      try {
        const res = await axios.post(config.youdaoBaseUrl, qs.stringify(params));
        console.log('Youdao translation results${res.data.translation[0]}`);
        return res.data.translation[0];
      }
      catch (err) {
        console.log(error); }}module.exports = getYouDaoTransResult
    
    Copy the code

Gets the selected text

Use the event hooks onDidChangeTextEditorSelection, access to the selected text

    onDidChangeTextEditorSelection(({ textEditor, selections }) = > {
        text = textEditor.document.getText(selections[0]);
    })
Copy the code

Get updates to configuration items

Through vscode. Workspace. GetConfiguration access to the configuration items of work area, and then through the event hooks onDidChangeConfiguration to monitor the change of configuration items.

Gets the updated configuration item

const { getConfiguration } = vscode.workspace;
const config = getConfiguration();

/ / pay attention to the get parameter is actually inside package. The json configuration items contributes. Inside the configuration. The properties. XXX
const isCopy = config.get(IS_COPY);
const isReplace = config.get(IS_REPLACE);
const isHump = config.get(IS_HUMP);
const service = config.get(SERVICE);
const baiduAppid = config.get(BAIDU_APPID);
const baiduKey = config.get(BAIDU_KEY);

// Update uses the update method, and the third parameter is true to indicate that it is applied globally
config.update(SERVICE, selectedItem, true);
Copy the code

Listen for changes to configuration items

const { getConfiguration, onDidChangeConfiguration } = vscode.workspace;
const config = getConfiguration();

// Listen for changes
const disposeConfig = onDidChangeConfiguration(() = > {
  config = getConfiguration();
})

Copy the code

Listen for changes to individual configuration items

const disposeConfig = onDidChangeConfiguration((e) = > {
    if (e && e.affectsConfiguration(BAIDU_KEY)) {
        // What to do}})Copy the code

Gets the currently open editor object

Vscode. Window. ActiveTextEditor represent the current open editors, if switch tabs, but did not set up to monitor, so that the object will not automatically update, so you need to use onDidChangeActiveTextEditor to listen, and replace the editor before the object

const { activeTextEditor, onDidChangeActiveTextEditor } = vscode.window;
let active = activeTextEditor;
const edit = onDidChangeActiveTextEditor((textEditor) = > {
  console.log('activeEditor changes');
  // Replace the open editor object
  if(textEditor) { active = textEditor; }})Copy the code

Underline word translation suspension hints

Through vscode. Languages. RegisterHoverProvider register a Hover, then through activeTextEditor selected words for translation, and then through the new vscode. The suspension will Hover translation results

// word translation detection
const disposeHover = vscode.languages.registerHoverProvider("*", {
    async provideHover(document, position, token) {
        const service = config.get(SERVICE);
        const baiduAppid = config.get(BAIDU_APPID);
        const baiduKey = config.get(BAIDU_KEY);

        let response, responseText;
        const selected = document.getText(active.selection);
        // Google Translate
        if (service === 'google') {
            response = await getGoogleTransResult(selected, { from: 'auto'.to: 'zh-cn' });
            responseText = response.text;
        }

        // Baidu Translation
        if (service === 'baidu') {
            response = await getBaiduTransResult(selected, { from: "auto".to: "zh".appid: baiduAppid, key: baiduKey });
            responseText = response.dst;
        }
        // Hover prompt
        return new vscode.Hover(`${responseText}`); }})Copy the code

Replaces the selected text

Get the activeTextEditor, call his Edit method, and then use replace in the callback

// Whether to replace the original text
if (isReplace) {
  let selectedItem = active.selection;
  active.edit(editBuilder= > {
    editBuilder.replace(selectedItem, result)
  })
}
Copy the code

Copy to clipboard

Using vscode. Env. Clipboard. WriteText;

// Whether to copy the translation result
if (isCopy) {
  vscode.env.clipboard.writeText(result);
}
Copy the code

Hump processing

function toHump(str) {
    if(! str) {return
    }
    const strArray = str.split(' ');
    const firstLetter = [strArray.shift()];
    const newArray = strArray.map(item= > {
        return `${item.substring(0.1).toUpperCase()}${item.substring(1)}`;
    })
    const result = firstLetter.concat(newArray).join(' ');
    return result;
}

module.exports = toHump;
Copy the code

Shortcut key binding

Via vscode.com mands. RegisterCommand registered before binding package. Set in json keybindings, it’s important to note that the first parameter to the registerCommand conform to the command of keybindings To bind

registerCommand('translateVariable.toEN'.async() = > {//do something
})


//package.json
"keybindings": [{
  "key": "ctrl+t"."mac": "cmd+t"."when": "editorTextFocus"."command": "translateVariable.toEN"}].Copy the code

Plug-in package distribution

packaging

vsce package
Copy the code

When packaged, plugins with the. Vsix suffix are generated in the directory

release

Plug-in distribution is mainly to package the vsix suffix plug-in, into the Microsoft vscode plug-in store, of course, can also be used locally.

Into the store

To publish online, you need to go to the Microsoft Plug-in store management page and create publisher information. If you do not have a Microsoft account, you need to apply for it.

Once created, select publish to vscode store

The local installation

You can install the.vsix plugin directly locally, find the plugin menu

Choose to install from VSIX and just install the plug-in packaged above

The last

The Chinese materials of VScode are a little little, so I spent most of the development time looking at English documents and searching for materials on the Internet. English is really very important, and I need to learn more English in the future. I hope that I will use this plug-in made by myself less and less in the future