この記事は、vscode 変数変換プラグインをゼロから開発するのに役立ちます。この記事では、プラグイン全体の機能設計からリリースまでの完全なプロセスを 4 つの側面から完全に示します。誰にとっても役に立つでしょう。
需要の理由は、イギリス人のクソ野郎は開発プロセスで変数に遭遇することがよくあるためです。彼らは中国語の名前は知っていますが、英語の単語を忘れてしまう可能性があります。この時、私が以前にやったことは、ブラウザを開き、Google 翻訳を開き、中国語を入力し、英語をコピーし、vscode に戻って結果を貼り付けることでした。
本当に困ったものです。若い頃は記憶力が良くて、ほとんどの英単語を覚えていましたが、年を重ねるごとに髪の毛も薄くなり、記憶力もどんどん悪くなっていきます。可哀想に、上記の手順を何度も繰り返すので、その苦い経験から学び、このプラグインを開発しました。
私もここ数日プラグイン開発を一から勉強しているため、この記事は初心者が開発したプラグイン開発の軌跡を完全に記録しており、主に4つの側面からの実践的な紹介となっています。 . 機能設計からリリースまでのプラグイン全体のプロセスを完全に示します。
」]
機能設計#機能は主に 2 つの機能で、中国語から英語、およびその他の言語を中国語に翻訳します。
置換中国語の変数と英語の変数を翻訳した場合、複数の単語を自動的にハンプする必要がある 解決すべきシナリオは、日々の開発でよく遭遇する「英語行き詰まり」 海外プロジェクトのソースコードのコメントを見てると、知らない単語や意味が分からず、効率に影響を与える//安装 yarn global add yo generator-code
yarn global add vsce
//初始化生成项目 yo code
開いた後、ワークスペースが自動的に作成され、これらのファイルがこの手順を完了すると、直接開発してデバッグできるようになります。
デバッグ方法は?
実行とデバッグパネルに移動し、実行拡張機能
をクリックするか、ショートカット キーF5 をクリックします。Mac ではタッチで直接クリックできます。バーのデバッグ ボタン
を開くと、新しい vscode ウィンドウが表示されます。この新しいウィンドウがテスト環境 (Extended Development Host) です。実行すること プラグイン機能はこの新しいウィンドウでテストされます。出力されたメッセージは前のウィンドウの デバッグ コンソール にあります。たとえば、組み込みのサンプルは新しいウィンドウ
にあります。 cmd/ctrlShift pHello world
を入力すると、前のウィンドウのコンソールにいくつかの情報が表示されますこの時点で、開発準備環境が整ったので次のステップ 正式なプラグイン機能の開発を始めるだけですプラグイン機能の開発
プラグイン開発には 2 つの作業があります重要なファイル、1 つは package.json
、もう 1 つはextension.js
package.json
##activationEvents はアクティベーション イベントを登録するために使用され、どのような状況で発生するかを示します。 extension.js 内のアクティブな関数がアクティブになります。一般的なものは、onLanguage
、onCommand です...詳細については、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, '['); str = str.replace(/<\/i><\/b>/g, ']'); 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 || 'auto'; opts.to = opts.to || 'en'; 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('谷歌翻译结果', result.text); return result; } catch (error) { console.log(error); console.log('翻译失败'); } } module.exports = getGoogleTransResult;
百度翻译,百度翻译的比较简单,申请服务,获得appid和key,然后构造请求url直接请求就行
不知道如何申请的,可查看我之前的一篇文章 Electron+Vue从零开始打造一个本地文件翻译器 进行申请
https://juejin.cn/post/6899581622471884813
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"; // 百度翻译 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('百度翻译结果', 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('activeEditor改变了'); //更换打开的编辑器对象 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 === 'google') { response = await getGoogleTransResult(selected, { from: 'auto', to: 'zh-cn' }); responseText = response.text; } // 百度翻译 if (service === 'baidu') { 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(' '); 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;
快捷键绑定
通过vscode.commands.registerCommand注册绑定之前package.json中设置的keybindings,需要注意的是registerCommand的第一个参数需要与keybindings的command保持一致才能绑定
registerCommand('translateVariable.toEN', 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商店
本地安装
本地是可以直接安装.vsix后缀插件的,找到插件菜单
选择从VSIX安装,安装上面打包的插件就好了
vscode チュートリアル をご覧ください。 !
以上がvscode 変数変換プラグインを開発する方法を最初からステップバイステップで教えますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。