惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

BMPI

一个 WebRTC 聊天室的三次演进 我是如何构建一个 AI 原生量化系统的 构建自己的信息简报 2.0 我的退休计划:把无期变成有期 从情绪化交易到系统化投资 反脆弱 系统化思维 策引2025 实盘大考:当算法跑赢人性 三十五 我的AI投资助手 我的投资之路 BMPI周记008:设止损而勇试错 BMPI周记007:经济下行 BMPI周记006:时光机 BMPI周记005:直播小完结 BMPI周记004:不要做空 BMPI周记003:十年前的今天 BMPI周记002:交易之难 BMPI周记001:开始直播 对交易的思考 AI驱动开发:从Prompt到Product(直播) 策引全球投资组合:A股1号 策引全球投资组合:A股2号 策引全球投资组合:A股3号 策引全球投资组合:A股全球 策引全球投资组合:加密币1号 策引全球投资组合:加密币2号 策引全球投资组合:美股1号 策引全球投资组合:美股2号 策引全球投资组合:美股3号 策引全球投资组合:美股4号 策引全球投资组合:美股全球 全球投资开户完全指南:A股与美股篇 我的2023 全球经济中的隐形巨人 海外银行证券开户薅羊毛小记 我与ChatGPT结对编程的体验 ChatGPT背后的语言模型简史 ChatGPT应用开发小记 我的AI阅读助手 SQLite的文艺复兴 2022亏了多少 # 组合季报(2022Q4) 我的2022 AI降临 构建自己的信息简报 善用GitHub Real-time Web应用开发新体验 我的巨亏经历 # 组合季报(2022Q3) Google软件工程之工具篇 构建自己的杠杆 我的投资助手 Google软件工程之过程篇 Google软件工程之文化篇 交易之难 # 组合季报(2022Q2) 从技术难题中学习 编程语言是如何实现并发的之并发模型篇 疫情与战争 # 组合季报(2022Q1) 编程语言是如何实现并发的之操作系统篇 编程语言是如何实现泛型的 写在第二十五万字 走进 Web3 财富常识 复盘2021 # 组合季报(2021Q4) 我的2021 分布式系统中的时间 分布式系统下的认证与授权 如何学习一门技术 K8S 云原生应用开发小记 使用 Beancount 管理家庭财务 三周年小记 # 组合月报(202109) 仓位管理是核心 # 组合月报(202108) 云端 IDE 护城河还在但城没了 # 组合月报(202107) 构建高质量的信息输入渠道 最牛指数 # 组合月报(202106) 国际化与本地化 慢慢变富 # 组合月报(202105) 失败驱动开发 加密币挖矿小记 家庭资产配置的阶段 # 组合月报(202104) OKR + GTD + Note => Logseq 我的个人项目技术栈 长期投资之难 # 组合月报(202103) 我的人生管理系统 重新思考估值策略 # 组合月报(202102) 当别人的股票基金上涨时 # 组合月报(202101) 基于Serverless实现静态博客访问统计功能 构建终身学习体系进行自我提升 我的家庭理财规划 投资的秘密 # 组合月报(202012) 零成本搭建现代博客之优化国内访问速度 我的2020 我的绘图工具箱 关于银行分期贷款的坑 # 组合月报(202011) 投资交易的心理建设 # 组合月报(202010) 大跌时我们能做什么 # 组合月报(202009) 双均线交易策略 # 组合月报(202008) Serverless应用开发小记 投资理财书籍推荐 # 组合月报(202007) 我的笔记系统
VSCode插件开发小记
2019-12-22 · via BMPI

VSCode介绍

VSCode是微软开源的一款基于Electron开发的代码编辑器。Electron 是一个基于 Chromium 的项目,可用于开发基于 Node.js 的本地应用程序。VSCode 使用 Blink 排版引擎渲染用户界面。虽然基于 Electron 框架,但并不是Atom的复刻。Code是由“Monaco”的编辑器核心制作,与 Visual Studio Team Services 相同。

在2019年的Stack Overflow组织的开发者调研中,VS Code被认为是最受开发者欢迎的开发环境,据调查87317名受访者中有50.7%的受访者声称正在使用VS Code1

Feature Overview

Visual Studio Code feature overview

Visual Studio Code feature overview

Context View

Context view diagram

Context view diagram

Module Organization

Module organization

Module organization

VSCode Architecture

VSCode architecture

VSCode architecture

Process structure of VSCode

Process structure of VSCode

从上图可以看出来渲染进程与调试/插件进程都是隔离的,通过RPC去调用,这保证了VSCode在安装很多插件时都能以极快的速度启动,这点对于用户体验很重要,因为启动太慢会让人焦虑(想想IDEA和Emacs在插件多的时候的感人启动速度)。

更多关于 VSCode 架构设计见 VSCode 团队负责人 Erich Gamma 的这个分享:Building an App Using JS/TypeScript, Node, Electron & 100 OSS Components • Erich Gamma • GOTO 2016

Emacs Architecture

EMACS Conceptual Architecture

EMACS Conceptual Architecture

分析完VSCode的架构后,我们还可以学习下上古神器Emacs的架构,Emacs拥有极其强大的扩展能力,号称伪装成操作系统的编辑器(只差一个内核了)。

在Emacs的世界里,用户的输入通过终端输入给Command Dispatcher组件,前者与Lisp解释器共同处理用户的输入,然后调用底层的Display Processer(处理显示)和Primitives(提供基本功能,例如刷新屏幕,插入一个字符并加载文件),这两个组件又调用最底层的Buffer(缓存区)和OS(操作系统原生命令)。

这种架构很类似我们Web开发中的MVC架构,通过Lisp解释器提供强大的定制能力,用户可以编写elisp代码给Emacs添加各种功能。

同样的VSCode也提供了各种插件API,虽不及Emacs这么强大,但是对于我们的很多需求都足够了,加上VSCode的生态的确要远比Emacs的好,入门门槛极低,我在不了解VSCode插件开发到发布第一款插件总共花了不到两天的时间(还是断断续续的开发)。

VSCode插件开发

背景

如果只是做一个很简单的demo插件,可能不到半小时就搞定了,不过真实的场景一般是比较复杂的,在《我的时间管理工具》这篇文章中提到我开发了VSCode插件TODO++,这是一款基于别人插件的修改版本,我需要的很多功能vscode-todo-plus都已经提供了,但是我需要查看我当前正在做的事情以及当前标记为很重要但是未开始做的事情,我需要在VSCode左侧的窗口中再提供两个窗口(DOING/CRITICAL)。

step1/开发

因为要添加TreeView的两个窗口,首先要了解TreeView的基本知识,可以查看VSCode官方的Tree View Guideyour-first-extension

全部的代码在这里 add doing task tree view

需要注意的是需要先在package.json的加入自己的command,因为我们要在TreeView中添加刷新按钮,当点击刷新按钮时,需要调用我们添加的这个刷新命令。

{
    "command": "todo.refreshDoingEntry",
    "title": "Refresh",
    "icon": {
        "light": "resources/icons/refresh_light.svg",
        "dark": "resources/dark/refresh_dark.svg"
    }
}

这个json会注册 todo.refreshDoingEntry 到VSCode的命令表中,那这个命令真正在commands.ts中:

function refreshDoingEntry () {
  DoingFiles.refresh ( true );
}
class Doing extends View {

  id = 'todo.views.0doing';
  clear = false;
  filePathRe = /^(?!~).*(?:\\|\/)/;

  getTreeItem ( item: Item ): vscode.TreeItem {
    return item
  }

  async getChildren ( item?: Item ): Promise<Item[]> {

    if ( this.clear ) {

      setTimeout ( this.refresh.bind ( this ), 0 );

      return [];

    }

    let obj = item ? item.obj : await Utils.files.get ();

    while ( obj && '' in obj ) obj = obj['']; // Collapsing unnecessary groups

    if ( _.isEmpty ( obj ) ) return [new Placeholder ( 'No todo files found' )];

    if ( obj.textEditor ) {

      const items = [],
            lineNr = obj.hasOwnProperty ( 'lineNr' ) ? obj.lineNr : -1;

      Utils.ast.walkChildren ( obj.textEditor, lineNr, data => {

        data.textEditor = obj.textEditor;
        data.filePath = obj.filePath;
        data.lineNr = data.line.lineNumber;

        let isDoing = data.line.text.includes("@doing") || (data.line.text.includes("@started") && !data.line.text.includes("@done"));

        let isGroup = false;

        Utils.ast.walkChildren2 ( obj.textEditor, data.line.lineNumber, data => {
          if ((data.line.text.includes("@doing") || data.line.text.includes("@started")) && !data.line.text.includes("@done")) {
            isGroup = true;
            return false;
          }
          return true;
      });

        if (isDoing || isGroup) {
          const label = _.trimStart ( data.line.text ),
              item = isGroup ? new Group ( data, label ) : new Todo ( data, label );
          items.push ( item );
        }
      });

      if ( !items.length ) { return []; }

      return items;

    } else {

      const keys = Object.keys ( obj ).sort ();

      return keys.map ( key => {

        const val = obj[key];

        if ( this.filePathRe.test ( key ) ) {

          const uri = Utils.view.getURI ( val );

          return new File ( val, uri );

        } else {

          return new Group ( val, key, this.config.embedded.view.icons );

        }

      });

    }

  }

  refresh ( clear? ) {

    this.clear = !!clear;

    super.refresh ();

  }

}

Doing extends View implements vscode.TreeDataProvider<Item>,这就是VSCode的TreeView,以id = 'todo.views.0doing'注册,在package.json中:

"views": {
      "todo": [
        {
          "id": "todo.views.0doing",
          "name": "Doing"
        },
        {
          "id": "todo.views.3critical",
          "name": "Critical"
        },
        {
          "id": "todo.views.1files",
          "name": "Files"
        },
        {
          "id": "todo.views.2embedded",
          "name": "Embedded"
        }
      ]
    }

注册刷新按钮到TreeView中:

"view/title": [
        {
          "command": "todo.refreshDoingEntry",
          "when": "view == todo.views.0doing",
          "group": "navigation@0"
        }
    ]

最后别忘了在index.ts中export:

export default [Doing, Critical, Files, Embedded];

step2/发布

开发完毕后,我们可以利用Github Actions提供的自动化发布插件Vscode release plugin编写自己的插件发布pipeline:

on: push
name: "Release Vscode Plugin "
jobs:
  npmInstall:
    name: npm install
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: npm install
        run: npm install
      - name: Vscode release plugin
        uses: JCofman/vscodeaction@master
        env:
          PUBLISHER_TOKEN: ${{ secrets.PUBLISHER_TOKEN }}
        with:
          args: publish -p $PUBLISHER_TOKEN

这样每次push都会触发自动发布至VSCode Marketplace。当然要了解详细的发布知识,可以查看官方的Publishing Extensions

进一步阅读

可研究下VSCode官方提供了一些插件的Demo: vscode-extension-samples

插件开发中不可避免要Debug,VSCode也提供了强大的Debug能力,可参考Debugging extensions

References


  1. Developer Survey Results 2019 - Most Popular Development Environments ↩︎