最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 教你用VS Code插件实现一段五彩斑斓的伪代码

    正文概述 掘金(大转转FE)   2020-12-18   940

    前言

    插件系统的设计是很多开源项目实现社区驱动的最为重要的手段,为项目提供了强大的可扩展性。在JavaScript生态圈中,有众多实现了插件机制的工具和库,诸如Babel、Webpack、Vue、Vue Cli,以及今天的主角VS Code。

    VS Code插件可以实现哪些功能?

    • 主题 主题包括界面的配色以及文件的图标,比如material theme和material file icon。
    • 自定义UI 扩展vscode的workbench,在侧边栏、底部状态栏添加自定义的按钮&界面。
    • Webview 在新标签中打开一个webview,最大化自定义界面元素。
    • New runtime support 对一个新的运行时提供支持。
    • 语言支持 为一门新的语言提供支持(比如我们自定义规则的伪代码)。

    ​ 今天我们将关注其中最后一个功能,支持一门新的编程语言。也许你会对这个功能感到困惑,为什么VS Code对一门语言的支持,是通过插件的形式?

    ​ 首先需要明确的是,VS Code本身并没有像大家想象的那样,内置了对各种编程语言的支持,包括JavaScript。VS Code为插件提供了一系列的API,令一个插件可以实现对特定语言的支持。比如HTML,就是通过HTML插件来提供支持的。

    ​ 再比如console.log,当你打出console.的时候,VS Code通知了名为Typescript Language Features的插件,然后插件对这个通知做出响应,让log出现在了补全提示中。

    ​ 这也就意味着,我们可以利用这些语言方面的API,来自定义一门自己的编程语言。所以接下来我们来探索一下,怎么实现这个听起来很酷的小目标。

    一个小建议:这篇文章的最佳阅读姿势是在电脑上打开,并跟着文章一步步做下去。

    效果展示

    ​ 首先我们写一小段伪代码。这段代码随便写在了一个fakeCode.zz的文件中,.zz是VS Code不支持的后缀,所以全部字符都是灰的(zz代表转转公司中的转转二字)。

    等文章结束,它们会变成这样: 教你用VS Code插件实现一段五彩斑斓的伪代码

    创建项目

    ​ 编写插件的第一步,就是创建我们的目录结构。这里我们使用一个叫做yo的脚手架工具。yo是一个富有高度扩展性的通用脚手架,可以通过插件来实现不同目录结构和初始选项。VS Code官方提供了名为generator-code的插件,来进行插件目录的创建。首先我们需要安装yo以及插件generator-code

    npm i -g yo generator-code
    

    在安装完成以后,使用下面的命令来创建目录结构。

    yo code
    

    ​ 在运行yo code以后,它会问你下面这些问题。建议大家和我的输入保持相同,以免遇到意外。这里我们给伪代码的取名为zhuanzhuan,并且告诉VS Code,当碰到一个文件的扩展名为.zhuanzhuan或者.zz时,就要运行我们这个插件。

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 输入完所有的选项以后,我们的插件目录就创建完成了。结构是这样子的:

    ├── CHANGELOG.md
    ├── README.md
    ├── language-configuration.json
    ├── package.json
    ├── syntaxes
    ├──     # 在tmLanguage.json中自定义语法
    │   └── zhuanzhuan.tmLanguage.json 
    └── vsc-extension-quickstart.md
    

    了解Scope

    ​ 想要实现语法高亮,就需要将一串代码字符串,拆分成无数的小碎片,然后分别为它们指定color等样式。这些拆分后的小碎片,被称作token。这里的tokenjwt中的token不同,并没有安全、令牌等方面的意思,而是更偏向"符号"的含义。我们来看一个简单例子?来理解一下这段话。

    function sum(a: number, b: number): number {
      return a + b;
    }
    

    ​ 在这段TS代码中,我们定义了一个用于求和的函数。这时候我们按下VS Code快捷键,shift+cmd+p,然后输入inspect editor tokens and scopes,就可以看到每个token对应的类型。比如sum这个token的类型就是functionab的类型是parameter

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 另外从截图的底部中,我们还可以看到,每个token还具有一个叫textmate scope的属性。通俗地说,scope指这个token所处的位置。比如下面的代码片段里,有两个a变量。第一个是一个变量声明,而第二个是函数的参数之一。虽然它们都可以被笼统地称为变量,但是因为所处的scope不同(也就是处于不同环境),所以被标上了不同的颜色。

    const a = 1;
    
    function sum(a: number, b: number): number {
      return a + b;
    }
    

    支持注释

    ​ 至此前置知识已经介绍完了,现在开始真正修改脚手架创建的代码。我们的第一个目标是,让zhuanzhuan语言支持注释。

    ​ 首先打开根目录下的language-configuration.json文件,找到comments字段,将lineComment从默认的//修改为注释:。完成以后按下F5启动Debug程序,VS Code会打开一个新的窗口,且我们的插件会在其中生效。在新窗口中,我们随意打开一个空文件夹,然后新建名为fakeCode.zz,并输入以下内容进行测试。

    注释: 当我们用中文伪代码来描述执行过程的时候,
    注释: 不管什么内容都被显示成灰色的字符串了。
    注释: 我们的目标就是让它们变得五彩斑斓。
    注释: 不要试图重构这个方法,不然你会虚度一天的光阴。
    
    如果 ([某个条件]) {
      做一些条件成立时的事情
    } 否则 {
      当条件不成立的时候...
    }
    
    遍历 商品
      打印 《商品id》
    结束
    
    函数 [函数名] {
      函数的内容
    }
    

    ​ 这时,我们按下注释转换的快捷键cmd+/,就会惊讶地发现,VS Code会为你自动转换注释内容,在这之间转换:注释:具体内容具体内容

    ​ 这样,我们的Hello World项目就完成了,开始做稍微复杂一些的事情。打开/syntexes/zhuanzhuan.tmLanguage.json文件,将这个文件的所有内容替换成下面的内容:

    {
    	"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
    	"name": "zhuanzhuan",
    	"scopeName": "source.zz",
    	"patterns": [
    		{
    			"include": "#comments"
    		}
    	],
    	"repository": {
    		"comments": {
    			"name": "punctuation.comment",
    			"begin": "注释:",
    			"end": "\\n",
    			"beginCaptures": {
    				"0": {
    					"name": "punctuation.comment.open"
    				}
    			},
    			"endCaptures": {
    				"0": {
    					"name": "punctuation.comment.close"
    				}
    			}
    		}
    	}
    }
    

    ​ 第一眼看的时候都会懵的,我们慢慢理解一下这到底是什么意思。

    • patterns & repository repository是规则的仓库,它规定了该条规则如何识别其适用的对象。而patterns则是规定了规则仓库中,哪些规则是需要生效的。所以如果我们想要加一条新的规则,需要在repository中加规则的内容,并在patterns中将这条规则include,不然即使在repository添加了规则也不会生效。

    • comments 这是我们加入的自定义规则,comments是规则的名字。

    • begin & end 决定这条规则的适用对象。这里我们将注释:开头,回车符结尾的这部分字符作为适用对象。

    • beginCapture & endCapture & name 这三个属性,代表着我们赋予适用对象的scope名称。比这样一条注释"注释:不要试图重构这个方法,不然你会虚度一天的光阴"。,对应到我们这条规则,就是注释:这部分被赋予了punctuation.comment.open scope,不要试图重构这个方法,不然你会虚度一天的光阴。scope为punctuation.comment,最后的回车符scope为punctuation.comment.open

    然后切换到刚才使用F5打开的Debug窗口,按下cmd+shift+p,运行reload window,让我们的修改生效,就可以看到scope名称的变化:

    教你用VS Code插件实现一段五彩斑斓的伪代码

    支持关键字

    ​ 关键字同样是编辑这个文件/syntexes/zhuanzhuan.tmLanguage.json,在repository中新加入keywords规则(记得在顶部的patterns中include它):

    {
      "keywords": {
        "patterns": [
          {
            "match": "\\b(如果|遍历|结束|打印|函数)\\b",
            "name": "keyword.control.zhuanzhuan",
          }
        ]
      }
    }
    

    解释一下这里的意思:

    • match 这是一个正则,如果碰上如果|遍历|结束|打印|函数其中之一,就将它标记为关键字。

    • name 这些关键字对应的scope是什么。

    ​ 效果如图:

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 从图中我们可以看出,正则中匹配的字符(如果、遍历、函数等)已经被一一高亮了。不过你的VS Code中不一定是蓝色,这取决于你当前使用的主题。

    支持字符串

    ​ 接着我们让zhuanzhuan语言支持字符串功能,同样是修改json文件。

    {
      "repository": {
        "strings": {
          "name": "string.quoted.book.zhuanzhuan",
          "begin": "《",
          "end": "》",
          "beginCaptures": {
            "0": {
              "name": "string.quoted.book.open"
            }
          },
          "endCaptures": {
            "0": {
              "name": "string.quoted.book.close"
            }
          }
        }
      }
    }
    

    ​ 就像JS中使用单双引号和模板字符串作为字符串的标志,为了体现zhuanzhuan语言的不同之处,我们使用书名号,而不是单双引号,来标志一个字符串。例如《xxxx》,它被分成了 xxxx 三个部分,这三个部分有各自的scope,对应关系如下:

    • string.quoted.book.open
    • xxxx string.quoted.book.zhuanzhuan
    • string.quoted.book.close

    ​ 为了看到修改后的效果,需要在调试窗口中,cmd+shift+p并运行reload window。重载后的效果是这样的:

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 这时候第13行发生了变化,从原来的黑色,变成了绿色。

    深入理解scope

    ​ 看到效果以后,再回过头看那份json文件,它到底表达了什么意思?

    ​ 首先我们规定了顶层的scope名字叫source.zz。也就是说,当我们新建了.zz结尾的文件,开始写代码,这时所有的代码都处在顶层scope

    patterns属性规定了在顶层scope中,有哪些方式可以开辟一个子scopepatterns数组inclucde(即引入)了名为stringskeywords的规则,这些规则被放在了repository(也就是仓库,一个规则的仓库)。

    {
      "strings": {
        "name": "string.quoted.book.zhuanzhuan",
        "begin": "《",
        "end": "》"
      }
    }
    

    ​ 在repository中,以strings规则为例,当VS Code解析引擎遇到以“《”开头,“》”结尾的token时,中间的内容会被认为是字符串。也就是说,我们让书名号具备了和JS中的单双引号相同的功能。字符串的scope变成了我们规定的string.quoted.book.zhuanzhuan。我们可以通过inspect editor tokens and scopes命令来验证这一点。 教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 图片中,xxxx所属的scope有两个,一个是constant.character.escape.zhuanzhuan,另一个就是根scope。一个token往往拥有多个scope,就像字符串,同时处于根scope和书名号创建的一个scope

    ​ 在上文的json文件中,还有一个叫keywords的属性,当有字符串满足match字段中的正则表达式时,会被认为是一个关键字。

    ​ 事实上,当我们把上文的json规则进行更多的扩展和嵌套,就会越来越接近现流行的其他语言,存在无数的嵌套。一个token会属于无数的scope

    ​ 那么问题来了,这些scope的作用是什么?我们花了很多的力气去定义json格式,来让不同位置的token拥有不同的scope。这样我们就拥有了一个类似于CSS选择器的东西,我们可以为不同scope指定不同的样式,从而让我们自创的语言高亮起来。

    使用Scope

    ​ 接下来我们要使用上文中定义的几个scope。因为目前为止,我们只是重新定义了zhuanzhuan语言中一部分情景下的scope名称,我们可以利用这些自定义的scope,做出更细致的高亮配置。

    ​ 使用scope的方式就是创建一个theme类型的插件(没错我们要写第二个插件了)。这次我们需要cd到用户文件夹下的.vscode/extensions,这样我们的主题就可以免安装,可以直接出现在VS Code主题列表中。

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 使用VS Code打开项目,然后编辑theme/zhuanzhuan-lang-theme-color-theme.json文件,文件的结构是这样的:

    {
     "name": "zhuanzhuan-lang-theme",
     "type": "light",
     "colors": {
      "editor.background": "#f5f5f5",
      "editor.foreground": "#333333"
     },
     "tokenColors": [
      {
       "name": "Comments",
       "scope": [
        "comment",
        "punctuation.definition.comment"
       ],
       "settings": {
        "fontStyle": "italic",
        "foreground": "#AAAAAA"
       }
      }
     ]
    }
    

    ​ 其中,tokenColors字段是我们需要关心的地方,它针对了不同的scope,指定不同的样式。name是这条规则的名字,可以随意命名,保证唯一性即可。scope类似于CSS选择器,是规则应用的对象。settings则是具体的样式。

    ​ 然后我们在tokenColors中,加上我们自定义的样式。

    {
      "tokenColors": [
        // 省略其他原有的规则,仅列出新增的规则。
        {
          "name": "quotedBookOpen",
          // 将scope为string.quoted.book.open的token,
          // 也就是《,颜色设置成#33ec0e(原谅色)。
          "scope": "string.quoted.book.open",
          "settings": {
            "foreground": "#33ec0e"
          }
        }
        // 省略了大段雷同的配置。
        // 只要scope和我们的zhuanzhuan语言定义中的scope相同,
        // 就可以高亮对应的token。
      ]
    }
    

    ​ 然后在zhuanzhuan-lang插件的调试窗口,打开主题选择列表,选择zhuanzhuan-lang-theme主题,就可以看到上面的三条规则对《xxxx》这部分生效了。

    教你用VS Code插件实现一段五彩斑斓的伪代码

    ​ 文字及其对应的scope和颜色如下:

      • scope: string.quoted.book.open
      • 颜色:#33ec0e
      • scope: string.quoted.book.close
      • 颜色:#33ec0e
    • xxxx
      • scope: string.quoted.book.open
      • 颜色:#eb8837

    成果

    ​ 经过上面一系列的努力,然后再添加亿点点细节,最终的效果就是下图。

    教你用VS Code插件实现一段五彩斑斓的伪代码

    总结

    ​ 通过阅读文章,我们总共创建了两个VS Code插件。一个是语言支持插件,通过简单的配置,使zhuanzhuan语言支持了中文关键字、书名号字符串以及中括号表示的变量。第二个是主题插件,为zhuanzhuan语言中自定义的scope提供了高亮规则。scope名称,是连接两个插件的枢纽。

    ​ 不过zhuanzhuan语言离一门完善的语言还需要海量的工作,我们需要定义更多的scope规则,规则之间往往还存在复杂的嵌套关系。这篇文章只是讲了冰山露出海面的那一角。如果想深入学习这方面的知识,仍需参考VS Code官方的文档,以及学习编译原理相关知识。

    另外附上文章中两个插件最终的代码:

    github.com/inkyMountai…

    github.com/inkyMountai…

    参考文档:https://code.visualstudio.com/api#vscode

    水平有限,若有错漏,敬请指正。


    起源地下载网 » 教你用VS Code插件实现一段五彩斑斓的伪代码

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元