ホームページ  >  記事  >  開発ツール  >  vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

青灯夜游
青灯夜游転載
2021-12-31 19:40:182842ブラウズ

この記事は、vscode 変数変換プラグインをゼロから開発するのに役立ちます。この記事では、プラグイン全体の機能設計からリリースまでの完全なプロセスを 4 つの側面から完全に示します。誰にとっても役に立つでしょう。

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

需要の理由は、イギリス人のクソ野郎は開発プロセスで変数に遭遇することがよくあるためです。彼らは中国語の名前は知っていますが、英語の単語を忘れてしまう可能性があります。この時、私が以前にやったことは、ブラウザを開き、Google 翻訳を開き、中国語を入力し、英語をコピーし、vscode に戻って結果を貼り付けることでした。

本当に困ったものです。若い頃は記憶力が良くて、ほとんどの英単語を覚えていましたが、年を重ねるごとに髪の毛も薄くなり、記憶力もどんどん悪くなっていきます。可哀想に、上記の手順を何度も繰り返すので、その苦い経験から学び、このプラグインを開発しました。

私もここ数日プラグイン開発を一から勉強しているため、この記事は初心者が開発したプラグイン開発の軌跡を完全に記録しており、主に4つの側面からの実践的な紹介となっています。 . 機能設計からリリースまでのプラグイン全体のプロセスを完全に示します。

  • #機能設計

  • #環境構築
  • #プラグイン機能開発
  • プラグインのパッケージ化とリリース
  • ##[推奨学習: 「
vscode 入門チュートリアル

」] vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

機能設計

#機能は主に 2 つの機能で、中国語から英語、およびその他の言語を中国語に翻訳します。

置換中国語の変数と英語の変数を翻訳した場合、複数の単語を自動的にハンプする必要がある 解決すべきシナリオは、日々の開発でよく遭遇する「英語行き詰まり」 海外プロジェクトのソースコードのコメントを見てると、知らない単語や意味が分からず、効率に影響を与える

  • 環境構築

    まずは環境構築
  • スキャフォールディング、
  • yo

generator-code

をインストールします。これら 2 つのツールは、プロジェクトを迅速に構築するのに役立ちます。詳細は (https:// github .com/Microsoft/vscode-generator-code)

//安装
yarn global add yo generator-code

  • vsce をインストールします。vsce を使用すると、開発されたコードを .vsix サフィックスが付いたファイルにパッケージ化できます。 Microsoft プラグイン ストアまたはローカルにアップロードします。 インストール

    yarn global add vsce
    プロジェクトを生成して初期化し、独自の状況に応じて初期化情報を入力します
    //初始化生成项目
    yo code

    これに到達したら、ステップ、直接開くことを選択します。
  • コードで開く
  • 開いた後、ワークスペースが自動的に作成され、これらのファイルがこの手順を完了すると、直接開発してデバッグできるようになります。

デバッグ方法は? vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

実行とデバッグ

パネルに移動し、vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます実行拡張機能

をクリックするか、ショートカット キー

F5 をクリックします。Mac ではタッチで直接クリックできます。バーのデバッグ ボタン

を開くと、新しい vscode ウィンドウが表示されます。この新しいウィンドウがテスト環境 (Extended Development Host) です。実行すること プラグイン機能はこの新しいウィンドウでテストされます。出力されたメッセージは前のウィンドウの デバッグ コンソール にあります。たとえば、組み込みのサンプルは新しいウィンドウ

にあります。 cmd/ctrlShift p

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えますHello world

を入力すると、前のウィンドウのコンソールにいくつかの情報が表示されます

この時点で、開発準備環境が整ったので次のステップ 正式なプラグイン機能の開発を始めるだけですプラグイン機能の開発

プラグイン開発には 2 つの作業があります重要なファイル、1 つは vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えますpackage.json

、もう 1 つは

extension.js

重要なファイルの説明

package.json

##activationEvents はアクティベーション イベントを登録するために使用され、どのような状況で発生するかを示します。 extension.js 内のアクティブな関数がアクティブになります。一般的なものは、onLanguage

onCommandvscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます です...詳細については、vscode ドキュメントのアクティベーションイベント (https://code.visualstudio.com/api/references/activation-events) をご覧ください。

  • main はプラグインのメイン入口を表します

  • contributes用来注册命令(commands),绑定快捷键(keybindings),**配置设置项(configuration)**等等,更多可配置项可看文档(https://code.visualstudio.com/api/references/contribution-points)

extention.js

extention.js主要作用是作为插件功能的实现点,通过active,deactive函数,以及vscode提供的api以及一些事件钩子来完成插件功能的开发

实现翻译功能

翻译这里主要是使用了两个服务,谷歌和百度翻译。

谷歌翻译参考了别人的做法,使用google-translate-token获取到token,然后构造请求url,再处理返回的body,拿到返回结果。这里还有一个没搞懂的地方就是请求url的生成很迷,不知道这一块是啥意思。

const qs = require('querystring');
const got = require('got');
const safeEval = require('safe-eval');
const googleToken = require('google-translate-token');
const languages = require('../utils/languages.js');
const config = require('../config/index.js');

// 获取请求url
async function getRequestUrl(text, opts) {
    let token = await googleToken.get(text);
    const data = {
        client: 'gtx',
        sl: opts.from,
        tl: opts.to,
        hl: opts.to,
        dt: ['at', 'bd', 'ex', 'ld', 'md', 'qca', 'rw', 'rm', 'ss', 't'],
        ie: 'UTF-8',
        oe: 'UTF-8',
        otf: 1,
        ssel: 0,
        tsel: 0,
        kc: 7,
        q: text
    };
    data[token.name] = token.value;
    const requestUrl = `${config.googleBaseUrl}${qs.stringify(data)}`;
    return requestUrl;
}

//处理返回的body
async function handleBody(url, opts) {
    const result = await got(url);
    let resultObj = {
        text: '',
        from: {
            language: {
                didYouMean: false,
                iso: ''
            },
            text: {
                autoCorrected: false,
                value: '',
                didYouMean: false
            }
        },
        raw: ''
    };

    if (opts.raw) {
        resultObj.raw = result.body;
    }
    const body = safeEval(result.body);

    // console.log('body', body);
    body[0].forEach(function(obj) {
        if (obj[0]) {
            resultObj.text += obj[0];
        }
    });

    if (body[2] === body[8][0][0]) {
        resultObj.from.language.iso = body[2];
    } else {
        resultObj.from.language.didYouMean = true;
        resultObj.from.language.iso = body[8][0][0];
    }

    if (body[7] && body[7][0]) {
        let str = body[7][0];

        str = str.replace(/<b><i>/g, &#39;[&#39;);
        str = str.replace(/<\/i><\/b>/g, &#39;]&#39;);

        resultObj.from.text.value = str;

        if (body[7][5] === true) {
            resultObj.from.text.autoCorrected = true;
        } else {
            resultObj.from.text.didYouMean = true;
        }
    }
    return resultObj;
}

//翻译
async function translate(text, opts) {
    opts = opts || {};
    opts.from = opts.from || &#39;auto&#39;;
    opts.to = opts.to || &#39;en&#39;;

    opts.from = languages.getCode(opts.from);
    opts.to = languages.getCode(opts.to);

    try {
        const requestUrl = await getRequestUrl(text, opts);
        const result = await handleBody(requestUrl, opts);
        return result;
    } catch (error) {
        console.log(error);
    }
}

// 获取翻译结果
const getGoogleTransResult = async(originText, ops = {}) => {
    const { from, to } = ops;
    try {
        const result = await translate(originText, { from: from || config.defaultFrom, to: to || defaultTo });
        console.log(&#39;谷歌翻译结果&#39;, result.text);
        return result;
    } catch (error) {
        console.log(error);
        console.log(&#39;翻译失败&#39;);
    }
}

module.exports = getGoogleTransResult;

百度翻译,百度翻译的比较简单,申请服务,获得appid和key,然后构造请求url直接请求就行

不知道如何申请的,可查看我之前的一篇文章 Electron+Vue从零开始打造一个本地文件翻译器 进行申请

https://juejin.cn/post/6899581622471884813

const md5 = require("md5");
const axios = require("axios");
const config = require(&#39;../config/index.js&#39;);
axios.defaults.withCredentials = true;
axios.defaults.crossDomain = true;
axios.defaults.headers.post["Content-Type"] =
    "application/x-www-form-urlencoded";

// 百度翻译
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=${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(&#39;百度翻译结果&#39;, res.data.trans_result[0]);
        return res.data.trans_result[0];
    } catch (error) {
        console.log({ error });
    }
}

module.exports = getBaiduTransResult;

获取选中的文本

使用事件钩子onDidChangeTextEditorSelection,获取选中的文本

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

配置项的获取更新

通过vscode.workspace.getConfiguration获取到工作区的配置项,然后通过事件钩子onDidChangeConfiguration监听配置项的变动。

获取更新配置项

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

//注意get里面的参数其实就是package.json配置项里面的contributes.configuration.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方法,第三个参数为true代表应用到全局
config.update(SERVICE, selectedItem, true);

监听配置项的变动

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

//监听变动
const disposeConfig = onDidChangeConfiguration(() => {
  config = getConfiguration();
})

监听个别配置项的变动

const disposeConfig = onDidChangeConfiguration((e) => {
    if (e && e.affectsConfiguration(BAIDU_KEY)) {
        //干些什么
    }
})

获取当前打开的编辑器对象

vscode.window.activeTextEditor代表当前打开的编辑器,如果切换标签页,而没有设置监听,那么这个这个对象不会自动更新,所以需要使用onDidChangeActiveTextEditor来监听,并替换之前的编辑器对象

const { activeTextEditor, onDidChangeActiveTextEditor } = vscode.window;
let active = activeTextEditor;
const edit = onDidChangeActiveTextEditor((textEditor) => {
  console.log(&#39;activeEditor改变了&#39;);
  //更换打开的编辑器对象
  if (textEditor) {
      active = textEditor;
  }
})

划词翻译悬浮提示

通过vscode.languages.registerHoverProvider注册一个Hover,然后通过activeTextEditor拿到选中的词语进行翻译,然后再通过new vscode.Hover将翻译结果悬浮提示

// 划词翻译检测
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);
        // 谷歌翻译
        if (service === &#39;google&#39;) {
            response = await getGoogleTransResult(selected, { from: &#39;auto&#39;, to: &#39;zh-cn&#39; });
            responseText = response.text;
        }

        // 百度翻译
        if (service === &#39;baidu&#39;) {
            response = await getBaiduTransResult(selected, { from: "auto", to: "zh", appid: baiduAppid, key: baiduKey });
            responseText = response.dst;
        }
        // 悬浮提示
        return new vscode.Hover(`${responseText}`);
    }
})

替换选中的文本

获取到activeTextEditor,调用他的edit方法,然后使用回调中的replace

//是否替换原文
if (isReplace) {
  let selectedItem = active.selection;
  active.edit(editBuilder => {
    editBuilder.replace(selectedItem, result)
  })
}

复制到剪贴板

使用vscode.env.clipboard.writeText;

// 是否复制翻译结果
if (isCopy) {
  vscode.env.clipboard.writeText(result);
}

驼峰处理

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

module.exports = toHump;

快捷键绑定

通过vscode.commands.registerCommand注册绑定之前package.json中设置的keybindings,需要注意的是registerCommand的第一个参数需要与keybindings的command保持一致才能绑定

registerCommand(&#39;translateVariable.toEN&#39;, async() => {
  //do something
})


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

插件打包发布

打包

vsce package

打包后会在目录下生成.vsix后缀的插件

发布

插件发布主要是把打包的vsix后缀插件,传入微软vscode插件商店,当然也能本地安装使用。

传入商店

发布到线上需要到 微软插件商店管理页面(https://marketplace.visualstudio.com/manage/createpublisher),创建发布者信息,如果没有微软账号,需要去申请。

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

创建完成后,选择发布到vscode商店

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

本地安装

本地是可以直接安装.vsix后缀插件的,找到插件菜单

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

选择从VSIX安装,安装上面打包的插件就好了

vscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えます

最後に

#vscode には中国語の情報が少し含まれています。私はこの開発時間のほとんどを英語のドキュメントを読んだり、インターネットで情報を探したりするのに費やしました。英語は本当に重要です。後で私はもっと英語を学ぶ必要があります。将来的には、私が作成したプラグインを使用することが少なくなるといいのですが。プロジェクトはオープン ソースであり、説明書とソース コード ポータル (https://github.com/Kerinlin/translate) が付属しています。 -variable)

VSCode の詳細については、

vscode チュートリアル をご覧ください。 !

以上がvscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。