乐趣区

关于前端:vscode语音注释-让信息更丰富-上

vscode 语音正文, 让信息更丰盛 (上)

     这个系列我会将我制作 ” 语音正文 ” 插件的残缺过程分享进去, 还是那句话 ’ 过程 ’ 比 ’ 后果 ’ 更乏味。

用法展现

下载: voice-annotation

配置 + 创立 语音文件寄存地址

右键呼出 ’ 录制音频正文 ’

录制实现点击 ’ 保留到我的项目 ’

悬停即可播放语音

背景

     当你开始浏览一份工程代码时, 兴许偶然就会读到一些不知其意的代码, 如果其有正文然而看后仍是一头雾水或者其就压根没写正文, 那么解决这个问题最不便的方法就是间接问问本来的开发者, 同学这里为啥这么写啊?

     不仅是 js 语言里, 大部分语言都曾经提供了 ” 文字正文 ” 的语法, 为什么咱们还是会遇到上述问题那? 假如咱们每段代码里都写了正文但还是看不懂, 看看都有哪些问题是咱们能够通过语音插件 ” 缓解 ” 的:

  1. 写的挺明确了, 看不懂确实是读者本身的问题 (无奈解决)
  2. 写了然而没写明确, 开发者本身表达能力 (无奈解决, 介于 ” 达克效应 ”&” 常识的咒骂 ” 无奈自我发觉)
  3. 兴许与某几个需要无关, 用文字描述分明甚是 ‘ 简单 ’, 索性不写了 ( 兴许能够缓解)
  4. 文字的模式说不明确, 咱们日常沟通中比拟常见, 线上说不清楚了, 间接面对面 solo (兴许能够缓解)
  5. 跨页的形容, 比方论述大段的 ” 调试办法 ”, 暗藏哪个变量, 强行赋值某个变量, 某些操作能够达到某些成果, 罕用于前端 mock 某些场景 (兴许能够缓解)

没做过 vscode 插件的同学举荐先读读我写的入门教程:

  • 记一次前端 ”vscode 插件编写实战 ” 超具体的分享会(倡议珍藏哦)(上篇)
  • 记一次前端 ”vscode 插件编写实战 ” 超具体的分享会(倡议珍藏哦)(下篇)

一、性能点 ’ 技术计划 ’ 剖析

① 辨认特定正文

     咱们须要约定一个特定的写法, 插件将这种写法辨认为 ” 语音正文 ”, 并且当鼠标悬停在其上时能够正确的进行播报, 以后我应用的就是 // voice_annotation + _数字 这种模式。

② 播放正文音频

     既然写在 vscode 外面, 那其实第一抉择就是应用 node 来管制音频输出设备, 如果采纳关上一个 web 新页面的形式播放声音, 会增长用户的操作链路, 调研了市场上现有的音频插件, 以音乐播放插件为主还是通过关上 web 页面的形式, 然而咱们这里对播放没有其余的操作, 比方快进循环播放等略微简单一点的需要, 所以抉择应用 node 播放。

③ 录制正文内容

     想吃鸡蛋当然要有🐔下蛋, 录音性能必须要能够将用户的录音放入对应的工程, 返回给用户 ’ 特定正文 ’ 的写法, 假如返回voice_annotation_20220201, 用户间接粘贴到工程里就能够失常应用了, 这个性能应用场景应该不多, 所以要思考性能相干问题。

④ 贮存音频信息

     大部分开发者电脑上不止一个工程, 如何可能让每个工程都能够精确播放对应工程下的语音, 并且每次录音完结都能够将生成的音频文件放入对应工程, 并且能够反对团队应用。

二、初始工程, 这次咱们应用 ts

     全局装置 vscode 开发工具, 并初始化我的项目:

npm install -g yo generator-code 

yo code

     (ts的确太香了) 后面几次开发插件都是应用原生 js 开发, 因为这次开发的插件会用到一些 ’ 生僻 ” 的 api, 坦白说vscode 的文档不是很敌对, 所以咱们间接看代码的 ts 类型才最不便。

    "activationEvents": ["onStartupFinished"],

来到 package.json 文件外面, 批改一下这里插件激活的配置:

onStartupFinished 规定了插件在 vscode 初始化启动实现后启动, 它不会占用用户初始化 vscode 时的性能, 并且咱们的语音正文也并不是那种很紧急启动的程序。

来到 extension.ts 文件外面, 将无用的代码全副清空

清空前

清空后

     执行 yarn watch 后开始编译代码,fn + F5调试代码会报错:

     看到下面的报错我也很蒙, 之前用原生 js 写如同没遇到过, 我还给 vscode 编辑器升了级还是报错, 而后就去代码里查了一下:

     这就很清朗了, 咱们圈定一个兼容范畴就好了, 查看了一下官网日志, 最初选定了最低 2020 年 10 月左右的版本。

    "engines": {"vscode": "^1.50.0"},

果然再次调试就能够呈现提示框了:

要留神:
     下方的 @types/vscode 也要改成与下面雷同的版本号, 不然只是现阶段不报错, 打包公布的时候会报错。

  "dependencies": {"@types/vscode": "^1.50.0",}

三、辨认特地正文

     这个性能是辨认出页面上的 ”voice-annotation” 并高亮显示, 之所以优先开发这个性能是因为其本身性能上比拟独立, 并且能够很直观的看到成果, 浏览 vscode 官网的时候我发现两种形式能够实现特定语句 ’ 高亮 ’ 的成果。

     这里咱们能够事后定义几个辨认 “ 语音正文 ” 的正则, 假如有这样的一串字符 // voice_annotation_202202070612135678, 首先咱们要辨认出 // 正文符, 拿到 ’//’ 前面的 voice_annotation_202202070612135678 这一串字符能力为其赋予 ’ 款式 ’, 并且匹配内容中的数字202202070612135678, 这样能力精确播放语音。

src/util/index.ts

export const targetName = "voice_annotation"; // 独自拿进去不便后续的更改
export const getAllTargetReg = new RegExp(`//\\s(${targetName}_\\d+)`, "g");
export const testTargetReg = new RegExp(`${targetName}_(\\d+)`);

四、计划一: 自定义语法高亮

     比方 js 中这种写法 function (){}, 就是函数的语法, in 属于关键字, 这些有特定意义的写法都会被赋予各种 ’ 高亮 ’, 那咱们能够将// voice_annotation 设置为关键字,

第一步: 在 package.json 文件退出 jojo作用域

     它的作用于 jststsx 文件。

  "contributes": {
    "grammars": [
      {
        "path": "./syntaxes/injection.json",
        "scopeName": "jojo.injection",
        "injectTo": [
          "source.js",
          "source.ts",
          "source.tsx"
        ]
      }
    ]
  },
第二步: 创立 injection.json 文件
{
  "scopeName": "jojo.injection",
  "injectionSelector": "L:comment.line.double-slash",
  "patterns": [
    {"include": "#jojo"}
  ],
  "repository": {
    "jojo": {
      "match": "jojo_黄金体验",
      "name": "support.constant.color.0xFF00.css",
      "settings": {"foreground": "FFFFFF"}
    }
  }
}
  1. scopeName顾名思义定义了作用域名称。
  2. injectionSelector 定义了作用域失效的范畴, 这里的意思就是对 // 前面的内容失效。
  3. jojo.match进行关键词的匹配。
  4. jojo.name这个有点非凡, 它是定义这个关键字款式的, 但并不是一般的 css 款式, 而是须要你在定义语言款式的文件里定义好, 而后在这边只能进行应用。

     这种计划弊病很多, 比方不好 ’ 定制款式 ’, 不好动静更改设置等等, 最初我并没有抉择这种实现形式。

五、计划二: 文档检索

     也就是获取以后所在 ’ 文档 ’ 的所有文字内容, 为其赋予相似 css 款式的能力, 这种形式更灵便, 并且能够通过 伪元素 实现一些有意思的成果。

     首先咱们须要独自形象出一个 initVoiceAnnotationStyle 办法, 这个办法专门用来设置 voice-annotation 的款式, 不便随时随地辨认出 ” 语音正文 ”:

extension.ts文件内进行批改

import * as vscode from 'vscode';
import initVoiceAnnotationStyle from './initVoiceAnnotationStyle'; // 新增

export function activate(context: vscode.ExtensionContext) {initVoiceAnnotationStyle() // 新增
    context.subscriptions.push( // 新增
        vscode.window.onDidChangeActiveTextEditor(() => {initVoiceAnnotationStyle()
        })
    )
}

export function deactivate() {}
  1. context.subscriptions.push 是在注册命令, 这里是注册了一个生命周期事件。
  2. vscode.window.onDidChangeActiveTextEditor 监听了当咱们在 vscode 中切换开发文件的事件, 也就是每次关上文件时, 之所以应用这个, 是因为咱们的 ’ 语音正文 ’ 简直不会被改变, 没必要占用 vscode 的性能。
定义款式

initVoiceAnnotationStyle文件

import * as vscode from 'vscode';
import {getAllTargetReg} from './util/index'

export default function () {vscode.window.visibleTextEditors.map((res) => {const documentText = res.document.getText();
        const decorator = vscode.window.createTextEditorDecorationType({
            color: 'gray',
            cursor: "pointer",
            textDecoration: "underline",
            before: {
                contentText: "📢",
                width: "10px",
                height: '10px',
                margin: "0 8px 0 0"
            }
        })

        let n;
        const ranges = [];
        while (n = getAllTargetReg.exec(documentText)) {const startPos = res.document.positionAt(n.index + 3);
            const endPos = res.document.positionAt(n.index + 3 + n[1].length);
            const range = new vscode.Range(startPos, endPos)
            ranges.push(range);
        }
        res.setDecorations(decorator, ranges)
    })}

这里的知识点很有意思, 配合截图讲一下

  1. vscode.window.visibleTextEditors 你能够了解为获取到以后 ’ 激活 ’ 的代码编辑页的属性, 外面包含以后翻阅到了第几行, 某些款式是否激活等属性。
  2. res.document.getText()获取以后激活页面的内容。
  3. vscode.window.createTextEditorDecorationType制作一个款式, 这里只定义固定的几种款式, 然而厉害的点是这里能够制作 ’ 伪元素 ’ 这样玩法就多样性了, 咱们能够把它的返回后果打印看看。

    这里返回的 key 其实是个className

  4. ranges用来记录 voice-annotation 所在的起始地位与完结地位。
  5. 之所以抉择 while 循环来解决, 是因为可能存在多个voice-annotation
  6. n.index + 3 是因为 // voice-annotation 的后面是 // 这个我抉择保留原样。

具体的调整款式咱们能够通过 vscode 开发者工具

六、悬停 // voice_annotation 播放款式

     首先这须要咱们新定义一个 hover 模块, 这个模块负责 hover 后的款式+ 播放音频

extension.ts减少:

import * as vscode from 'vscode';
import hover from './hover'; // 新增
import initVoiceAnnotationStyle from './initVoiceAnnotationStyle';

export function activate(context: vscode.ExtensionContext) {initVoiceAnnotationStyle()
    context.subscriptions.push(hover); // 新增
    context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(() => {initVoiceAnnotationStyle()
        })
    )
}

export function deactivate() {}
定义文件内容

hover.ts

import * as vscode from 'vscode';
import {getVoiceAnnotationDirPath, targetName, testTargetReg} from './util'
let stopFn: () => void;

function playVoice(id: string) {// 这里是具体播放音频的逻辑...}

export default vscode.languages.registerHoverProvider("*", {provideHover(documennt: vscode.TextDocument, position: vscode.Position) {stopFn?.()
        const word = documennt.getText(documennt.getWordRangeAtPosition(position));
        const testTargetRes = testTargetReg.exec(word);
        if (testTargetRes) {playVoice(testTargetRes[1])
            return new vscode.Hover('播放中 ...')
        }
    }
})
  1. documennt.getText(documennt.getWordRangeAtPosition(position))能够获取到以后 hover 的文本内容。
  2. testTargetReg.exec(word) 校验以后 hover 的文本是否为指标文本。
  3. return new vscode.Hover('播放中 ...') 这里返回的文本只能是 markdown 的格局。
  4. stopFn是前期要做的进行播放逻辑, 因为有的音频可能很长, 听了一半咱们不想听了, 亦或者听着某个音频的同时我又悬停在了另一个 语音正文 上, 那么咱们应该进行上一个音频并播放以后的音频。

end

     下一篇该讲到 vscode 如何播放声音, 音频文件如何传递与贮存, 等多坑点等我来跳 这次就是这样, 心愿与你一起提高。

退出移动版